Todos los errores, y qué hacer con cada uno
La referencia declara qué errorCode devuelve cada operación. Esto es lo otro: de
quién es el problema y si se reintenta.
Todos los errores tienen la misma forma, y requestId es el dato que conviene
loguear: identifica el pedido exacto si hay que reportar algo.
{
"statusCode": 403,
"errorCode": "API_KEY_INSUFFICIENT_SCOPE",
"message": "La API key no tiene el scope necesario para esta operación",
"details": "La API key no declara invoice:cancel (taxpayer cms6n9hxh0008urbk44g07f66)",
"requestId": "736e2fff-1d9f-4765-af94-59ee6de84acb",
"timestamp": "2026-07-29T22:25:10.972Z",
"path": "/v1/invoices/cms6nk3i2000sur8kk9l20yw6/cancel"
}
message es estable y apto para mostrar; details es el que dice la causa
concreta y puede cambiar. No parsees details; parseá errorCode.
Qué está medido y qué no. Los códigos marcados con ✅ en las tablas se provocaron contra la API y la respuesta publicada es la que devolvió. El resto sale del catálogo de errores del código —el
statusCodey elmessageson los declarados— pero no se ejecutaron: varios necesitan que ARCA se caiga o que venza un certificado, y no se pueden forzar a voluntad. La columna "qué hacer" es, en esos casos, la conducta que el propio código documenta.
La regla de oro, en una línea
Un 4xx de validación nunca deja nada colgado. Un 409, un 500 o un 502 al
emitir, sí. Ante los segundos, consultá
unresolved antes de reintentar.
Y la red de seguridad que sirve siempre: reintentar con la misma
Idempotency-Key no puede duplicar nada.
Credenciales y permisos
Son todos tuyos, y ninguno se arregla reintentando.
errorCode | HTTP | Qué pasa | Qué hacer |
|---|---|---|---|
INVALID_API_KEY ✅ | 401 | La clave no existe o fue revocada | Revisá que sea la clave entera y que siga activa |
API_KEY_WRONG_HEADER ✅ | 401 | La mandaste en Authorization | Va en X-API-Key |
API_KEY_INSUFFICIENT_SCOPE ✅ | 403 | Le falta un scope | details dice cuál. Se corrige creando otra clave |
API_KEY_WRONG_MODE ✅ | 403 | Clave test contra contribuyente PRODUCCION, o al revés | Usá la clave del ambiente correcto |
API_KEY_NOT_ALLOWED_HERE ✅ | 403 | La operación exige sesión de usuario | Se hace desde el panel. Ver el reparto |
RATE_LIMIT_EXCEEDED ✅ | 429 | Demasiados pedidos | Éste sí se reintenta: esperá lo que dice Retry-After |
El rate limit, medido
Es el único límite duro que vas a encontrar operando normalmente. Sobre
GET /v1/invoices/search, con 135 pedidos seguidos:
120 respuestas 200
15 respuestas 429
Y el 429 trae todo lo que hace falta para reintentar bien:
{
"statusCode": 429,
"errorCode": "RATE_LIMIT_EXCEEDED",
"message": "Demasiadas peticiones. Reintentá más tarde.",
"details": { "limite": 120, "reintentarEnSegundos": 60 }
}
Retry-After: 60
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 60
Usá Retry-After, no un backoff inventado. Y las tres cabeceras X-RateLimit-*
vienen en todas las respuestas, no sólo en el 429: mirando X-RateLimit-Remaining
podés bajar el ritmo antes de chocar.
(El límite exacto depende de la operación: las de emisión tienen el suyo. El valor de
X-RateLimit-Limit es el que rige para el pedido que acabás de hacer.)
Antes de llegar a ARCA: lo que Emissa rechaza
Todos 4xx, y todos tienen la misma virtud: no consumen número de comprobante.
Es más barato equivocarse acá que en ARCA.
errorCode | HTTP | Qué pasa | Qué hacer |
|---|---|---|---|
IDEMPOTENCY_KEY_REQUIRED ✅ | 400 | Falta el header al emitir | Mandalo. Ver numeración |
IDEMPOTENCY_KEY_REUSED | 409 | Esa clave se usó para un pedido distinto | Clave nueva. Y revisá cómo la derivás |
INVALID_INPUT ✅ | 400 | El cuerpo no valida | details trae la lista de campos |
INCOMPATIBLE_INVOICE_TYPE ✅ | 400 | La letra no corresponde al emisor o al receptor | Ver A, B y C |
INVALID_RECEIVER_DOCUMENT ✅ | 400 | El documento no es válido para su tipo | Revisá el dígito verificador del CUIT |
MISSING_RECEIVER_BUSINESS_NAME ✅ | 400 | Falta la razón social en una A, o es un marcador | Poné el nombre real |
INVOICE_DATE_OUT_OF_WINDOW | 400 | La fecha está fuera de la ventana que ARCA acepta | Emití con fecha de hoy |
INVOICE_DATE_NOT_MONOTONIC | 400 | La fecha es anterior a la del comprobante previo de la serie | La serie no puede ir hacia atrás |
CREDENTIALS_REQUIRED ✅ | 400 | El contribuyente no tiene certificado cargado | Cargalo desde el panel |
ARCA_SALE_POINT_NOT_ENABLED | 400 | El punto de venta no está dado de alta para webservice | Es un alta en ARCA, no un cambio de código. Ver punto de venta |
TAXPAYER_NOT_FOUND | 404 | El taxpayerId no existe o no es tuyo | Revisá el id |
INVOICE_NOT_FOUND | 404 | El comprobante no existe o no es tuyo | Revisá el id |
Estado del comprobante
errorCode | HTTP | Qué pasa | Qué hacer |
|---|---|---|---|
INVOICE_ALREADY_CANCELLED | 400 | Ya se anuló | Nada. Es idempotente en la práctica |
INVOICE_NOTHING_TO_RECONCILE ✅ | 409 | Ya tiene estado definitivo | Nada. No había nada que resolver |
INVOICE_NOT_AUTHORIZED | 422 | Se pidió el PDF de un comprobante sin CAE | Reconciliá primero: sin CAE no hay comprobante que imprimir |
ARCA
Acá está el que importa. La tabla completa y ejecutada está en qué hacer cuando el CAE viene rechazado; ésta es la versión corta.
errorCode | HTTP | ¿De quién? | ¿Reintentar? |
|---|---|---|---|
ARCA_WSFEV1_REJECTED ✅ | 422 | Tuyo, casi siempre | Sí, corrigiendo. El número se liberó |
ARCA_CAE_UNKNOWN ✅ | 409 | De nadie: se perdió la respuesta | NO. Reconciliá primero |
ARCA_WSAA_UNAVAILABLE | 502 | De ARCA o de la red | Sí, con la misma clave |
ARCA_WSFEV1_UNAVAILABLE | 502 | De ARCA o de la red | Sí, con la misma clave |
ARCA_WSAA_REJECTED | 502 | Del certificado o de la delegación | No sin revisar. details trae el faultcode |
ARCA_TICKET_ALREADY_ISSUED | 409 | De ARCA | Sí, esperando unos minutos. No hay forma de forzarlo |
ARCA_INVALID_RESPONSE | 502 | De ARCA | Mirá unresolved antes |
ARCA_CATALOG_MISMATCH | 500 | Nuestro, y es fatal a propósito | Reportalo. No se emite hasta resolverlo |
ARCA_CAE_UNKNOWN en dos frases
La respuesta de ARCA se perdió y no se sabe si el comprobante quedó autorizado. Reintentar con una clave nueva puede emitir un segundo comprobante fiscal por la misma venta — está demostrado, con la serie resultante, en la guía del CAE rechazado.
La salida es POST /v1/invoices/{id}/reconcile, que le pregunta al organismo.
Y el que no dice lo que pasa
Un 500 INTERNAL_ERROR al emitir puede dejar un comprobante tomando número, y el
mensaje no lo menciona:
{
"statusCode": 500,
"errorCode": "INTERNAL_ERROR",
"message": "Error interno del servidor"
}
Medido: el comprobante quedó en PENDING, apareció en unresolved y se destrabó con
reconcile. Así que ante un 500 al emitir, mirá unresolved en vez de
reintentar. Es la misma precaución que el 409, con un mensaje que no la sugiere.
Qué sigue
- Qué hacer cuando el CAE viene rechazado — los cuatro desenlaces, ejecutados.
- La referencia — qué
errorCodedeclara cada operación.