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? |
|---|---|---|---|---|
| Autorizado | 201 | Sí | Sí | No hace falta |
| Autorizado con observaciones | 201 | Sí | Sí | No. El comprobante vale |
| ARCA rechazó | 422 ARCA_WSFEV1_REJECTED | No | No, se liberó | Sí, corrigiendo el pedido |
| No se sabe | 409 ARCA_CAE_UNKNOWN | No se sabe | Sí | NUNCA 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 sí 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
AUTHORIZEDcon 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
201→ listo. Si traeobservations, leelas y seguí.400de validación → corregí el pedido. No dejó nada colgado.422 ARCA_WSFEV1_REJECTED→ corregí lo que dicedetailsy volvé a emitir. El número se liberó solo.409 ARCA_CAE_UNKNOWN→ reconciliá. No reintentes.500o502→ miráunresolved. Si hay algo, reconciliá; si no, reintentá con la mismaIdempotency-Key.- En cualquier duda: reintentar con la misma clave nunca duplica. Es la red de seguridad, y es gratis.
Qué sigue
- Todos los errores, y qué hacer con cada uno — la tabla de consulta.
- Cómo se numera una serie — por qué el número importa.