Guías8 de 11

Qué hacer cuando el CAE viene rechazado

Un pedido de CAE puede terminar de cuatro formas, y sólo una de las cuatro se reintenta sin pensar. Distinguirlas es la diferencia entre una integración que se recupera sola y una que emite un comprobante fiscal duplicado.

Todas las respuestas de esta guía se provocaron y se ejecutaron. Los desenlaces que no se pueden forzar contra ARCA —un corte, una respuesta ilegible— se produjeron contra la frontera falseada, que es el mismo circuito con ARCA sustituido en el último salto.

Los cuatro desenlaces

Qué pasóRespuesta¿Hay CAE?¿El número quedó tomado?¿Reintentar?
Autorizado201No hace falta
Autorizado con observaciones201No. El comprobante vale
ARCA rechazó422 ARCA_WSFEV1_REJECTEDNoNo, se liberóSí, corrigiendo el pedido
No se sabe409 ARCA_CAE_UNKNOWNNo se sabeNUNCA a ciegas

Autorizado con observaciones no es un fallo

ARCA puede aprobar y observar el mismo comprobante. Una emisión real:

HTTP 201 · status=AUTHORIZED · cae=70001000000001
observations=[
  {
    "code": 10217,
    "message": "El credito fiscal discriminado en el presente comprobante solo podra ser computado a efectos del Procedimiento permanente de transicion al Regimen General."
  }
]
arcaMetadata={"service":"wsfev1","resultado":"A","authorized":true,"observaciones":1}

resultado: "A" con CAE: el comprobante es válido. La observación es información para tu cliente, no un error tuyo.

El antipatrón concreto: if (respuesta.observations.length) throw. Eso rompe emisiones que ARCA aprobó. El campo que decide es status.

ARCA rechazó: el número se libera

Cuando ARCA contesta con errores, no hay CAE y el número vuelve a estar disponible. Provocado con el error 10015:

{
  "statusCode": 422,
  "errorCode": "ARCA_WSFEV1_REJECTED",
  "message": "ARCA rechazó el comprobante"
}

El comprobante queda registrado como rechazado:

filas tras el rechazo: [{"number":1,"status":"REJECTED","cae":null}]

Y la emisión siguiente —ya corregida— tomó el número 1 otra vez:

la emision siguiente tomo el numero 1 (status 201)

Eso es lo que hay que entender: un rechazo no deja un hueco. ARCA nunca registró ese comprobante, así que del otro lado el número sigue libre, y Emissa libera el suyo para que coincidan.

Es también la razón por la que un rechazo se reintenta: corregí lo que ARCA señaló y volvé a emitir. Lo que no hay que hacer es reintentar sin corregir: el mismo pedido produce el mismo rechazo.

Cómo leer el motivo

El message es genérico a propósito; el motivo va en details, con el código y el texto que devolvió ARCA. Leé siempre details: es el único lugar donde está la causa.

Los códigos son del catálogo de ARCA, no de Emissa, y el organismo es la fuente autoritativa de qué significa cada número. Lo que sí conviene saber es en qué dos familias caen:

  • Los que se arreglan corrigiendo el pedido — combinaciones de tipo de comprobante, documento del receptor e importes que no cierran. En el rango 10015 a 10021 aparecen varios de éstos.
  • Los que hablan de la serie — el número enviado no es el que ARCA esperaba. El 10016 es el que se ve en este caso, y está explicado en cómo se numera una serie.

(La correspondencia exacta entre cada número y su causa no está verificada acá: se la toma del details que ARCA devuelve en cada rechazo.)

La buena noticia es que muchas de esas combinaciones Emissa las rechaza antes de llegar a ARCA, con un 400 que no consume número. Las nueve que están medidas una por una viven en por qué hay comprobantes A, B y C.

ARCA_CAE_UNKNOWN: el caso que hay que leer entero

Éste es el único que puede costarte un comprobante duplicado.

{
  "statusCode": 409,
  "errorCode": "ARCA_CAE_UNKNOWN",
  "message": "Se perdió la respuesta de ARCA y no se sabe si el comprobante quedó autorizado. Consultalo antes de reintentar."
}

Qué pasó: el pedido salió, y la respuesta no volvió o no se pudo leer. ARCA pudo haber autorizado el comprobante y perderse la confirmación en el camino. Desde afuera, autorizado y no autorizado se ven igual.

Es un 409 y no un 502 a propósito: un 502 invita a reintentar, y acá reintentar es exactamente lo que no hay que hacer.

El comprobante queda registrado, con su número tomado:

quedo en la base: number=1 status=UNKNOWN cae=null

Y aparece en la lista de irresueltos:

curl "https://api.emissa.com.ar/v1/invoices/unresolved?taxpayerId=TU_TAXPAYER_ID" \
  -H "X-API-Key: $EMISSA_API_KEY"
HTTP 200 · 1 comprobante(s) · [{"comprobante":"0001-00000001","status":"UNKNOWN"}]

Qué pasa si reintentás a ciegas

Esto se ejecutó. Un UNKNOWN, y después un reintento con una Idempotency-Key nueva —que es lo que hace un reintento automático—:

intento 1: HTTP 409 ARCA_CAE_UNKNOWN
intento 2 (clave NUEVA): HTTP 201 numero=2 cae=70001000000002

la serie quedo asi:
[
  { "number": 1, "status": "UNKNOWN",    "cae": null },
  { "number": 2, "status": "AUTHORIZED", "cae": "70001000000002" }
]

comprobantes en total: 2

Dos números consumidos, y el primero sin resolver. Si ARCA había autorizado el número 1 —que es precisamente lo que no se sabe—, tu cliente acaba de recibir dos comprobantes fiscales por la misma venta. Eso no se borra: se anula con una nota de crédito, y las dos cosas quedan en tu historia y en la de ARCA.

Con la misma clave, en cambio, el reintento es inofensivo:

reintento con la MISMA clave: HTTP 201 Idempotent-Replay=true numero=2

Por eso la Idempotency-Key se deriva de la intención de facturar y no del intento — ver cómo se numera una serie.

Lo que sí hay que hacer: reconciliar

curl -X POST https://api.emissa.com.ar/v1/invoices/{id}/reconcile \
  -H "X-API-Key: $EMISSA_API_KEY"

reconcile le pregunta a ARCA qué pasó de verdad con ese comprobante y resuelve el estado. Los dos desenlaces posibles:

  • ARCA lo tenía autorizado → el comprobante pasa a AUTHORIZED con su CAE. No hay nada más que hacer, y no hay que emitir de nuevo.
  • ARCA no lo tiene → pasa a REJECTED, su número se libera, y recién entonces podés volver a emitir.

Ejecutado sobre un irresuelto:

reconcile: HTTP 200 status=REJECTED cae=null

Si el comprobante ya tenía un estado definitivo, reconcile lo dice en vez de hacer nada:

{
  "statusCode": 409,
  "errorCode": "INVOICE_NOTHING_TO_RECONCILE",
  "message": "El comprobante ya tiene un estado definitivo"
}

Un 500 también puede dejar un comprobante sin resolver

Y esto es lo menos evidente de toda la guía, así que va con la respuesta textual. Cuando el servicio de ARCA devuelve un error HTTP que no es SOAP, la respuesta que recibís es genérica:

{
  "statusCode": 500,
  "errorCode": "INTERNAL_ERROR",
  "message": "Error interno del servidor"
}

Ese mensaje no te dice lo que necesitás saber, que es que quedó un comprobante tomando número:

filas: [{"number":1,"status":"PENDING"}]

La buena noticia: el camino de recuperación es el mismo y funciona. El comprobante aparece en unresolved y se destraba con reconcile —las dos cosas ejecutadas—:

unresolved tras el 500: HTTP 200 · 1 comprobante(s) · [{"comprobante":"0001-00000001","status":"PENDING"}]
reconcile tras el 500:  HTTP 200 status=REJECTED cae=null

La regla práctica, entonces, es más amplia que "ojo con el 409": ante cualquier fallo de authorize que no sea un 4xx de validación, consultá unresolved antes de reintentar. Un 400 por un CUIT mal tipeado no deja nada colgado; un 409, un 500 o un 502 sí pueden.

El árbol de decisión, corto

  1. 201 → listo. Si trae observations, leelas y seguí.
  2. 400 de validación → corregí el pedido. No dejó nada colgado.
  3. 422 ARCA_WSFEV1_REJECTED → corregí lo que dice details y volvé a emitir. El número se liberó solo.
  4. 409 ARCA_CAE_UNKNOWNreconciliá. No reintentes.
  5. 500 o 502 → mirá unresolved. Si hay algo, reconciliá; si no, reintentá con la misma Idempotency-Key.
  6. En cualquier duda: reintentar con la misma clave nunca duplica. Es la red de seguridad, y es gratis.

Qué sigue