Referencia
Errores
Formato de los errores de la API, catálogo de códigos y los rechazos de Hacienda que Aster detecta antes de enviar.
Todos los errores de la API usan el mismo formato y un error.code estable. Programá contra error.code, no contra el texto de error.message, que puede cambiar.
Formato
Sección titulada «Formato»{ "success": false, "error": { "code": "validation_error", "message": "Validation failed", "errors": { "items": ["At least one item is required"] } }, "timestamp": "2026-03-06T12:00:00Z", "api_version": "1.0"}| Campo | Descripción |
|---|---|
success |
Siempre false en un error |
error.code |
Código estable, en inglés y snake_case |
error.message |
Descripción legible para personas |
error.errors |
Solo en validation_error: un objeto con la ruta de cada campo y la lista de problemas |
timestamp |
Momento de la respuesta, UTC |
api_version |
Versión de la API |
Los errores de autenticación, permisos, límites e idempotencia repiten el mensaje también en un campo message de primer nivel, por compatibilidad con clientes anteriores.
error.message y los mensajes de error.errors salen en español o en inglés según el encabezado Accept-Language de la solicitud. Con Accept-Language: es recibís:
{ "success": false, "error": { "code": "validation_error", "message": "El código CABYS 4292199990299 no existe en el Catálogo de Bienes y Servicios (error de Hacienda -400).", "errors": { "items.0.cabys_code": [ "El código CABYS 4292199990299 no existe en el Catálogo de Bienes y Servicios (error de Hacienda -400)." ] } }, "timestamp": "2026-10-08T16:20:11Z", "api_version": "1.0"}Las rutas de error.errors siguen la estructura del JSON enviado: items.0.cabys_code es el cabys_code de la primera línea (se cuenta desde 0) y receiver.id es la identificación del receptor.
hacienda_message, en cambio, trae el texto de Hacienda tal cual lo devolvió Hacienda, sin traducir ni resumir.
Códigos de error
Sección titulada «Códigos de error»| HTTP | error.code |
Cuándo ocurre | Qué hacer |
|---|---|---|---|
| 400 | invalid_request |
El cuerpo no es JSON válido o falta | Revisá el cuerpo y el Content-Type |
| 400 | invalid_idempotency_key |
X-Idempotency-Key tiene más de 255 caracteres |
Usá una llave más corta |
| 401 | unauthenticated |
Falta la llave, está mal formada o no existe | Revisá el encabezado Authorization |
| 401 | token_expired |
La llave pasó su fecha de vencimiento | Creá una llave nueva |
| 401 | key_revoked |
La llave fue revocada | Usá una llave vigente |
| 401 | tenant_unresolved |
No se pudo cargar la organización de la llave | Revisá que la organización exista |
| 402 | plan_required |
Se usó o se quiso crear una llave aster_live_ sin plan pagado |
Elegí un plan en el portal |
| 402 | quota_exceeded |
Se alcanzó el límite del plan más los paquetes del mes. Se responde antes de firmar | Mejorá de plan o agregá un paquete en cualquier momento; ver abajo |
| 402 | subscription_inactive |
La suscripción no está al día (por ejemplo, un cobro rechazado). Las llaves de prueba siguen funcionando | Actualizá el medio de pago en el portal |
| 402 | subscription_expired |
Terminaron el período de prueba y la suscripción | Renová el plan en el portal |
| 403 | forbidden |
La llave no tiene el permiso que pide el endpoint | Creá una llave con ese permiso |
| 403 | account_key_required |
El endpoint administra la cuenta y se llamó con una llave de organización | Usá una llave de cuenta (creada sin organización) |
| 403 | organization_limit_reached |
El plan no admite más organizaciones | Mejorá de plan |
| 403 | no_tenant, tenant_inactive, tenant_deleted |
La organización no está disponible | Contactá a soporte |
| 404 | not_found |
El recurso no existe o no pertenece a tu organización | Revisá la clave o el identificador |
| 409 | duplicate_clave |
La clave ya se usó | No reintentés con la misma clave; ver consecutivo |
| 409 | duplicate_consecutive |
El consecutivo ya se usó en ese ambiente | El número está gastado; usá uno nuevo |
| 409 | organization_exists |
Ya existe una organización con esa cédula en la cuenta | Usá la existente |
| 409 | idempotency_in_progress |
Otra solicitud con la misma X-Idempotency-Key se sigue procesando |
Esperá y reintentá con la misma llave |
| 422 | validation_error |
Uno o más campos no pasan la validación. Detalle en error.errors |
Corregí los campos indicados |
| 422 | idempotency_key_reused |
Se reusó una X-Idempotency-Key con otro cuerpo u otra ruta |
Usá una llave nueva para cada solicitud distinta |
| 422 | organization_mismatch |
El emisor del comprobante no es la organización de la llave | Usá la llave de la organización que emite |
| 422 | invalid_clave_consecutive |
Se envió clave sin consecutive_number o al revés |
Enviá los dos o ninguno |
| 422 | invalid_clave_format, invalid_consecutive_format |
La clave no tiene 50 caracteres o el consecutivo no tiene 20 dígitos | Ver clave |
| 422 | clave_date_mismatch |
La fecha de la clave no coincide con document.date |
Generá la clave con la fecha de emisión |
| 422 | fec_clave_id_mismatch |
En una FEC, la clave no lleva la cédula del receptor | Usá la cédula del comprador en la clave |
| 422 | missing_certificate, missing_credentials |
Falta el certificado o las credenciales de Hacienda de ese ambiente | Subilos en el portal |
| 422 | certificate_expired |
El certificado de firma de ese ambiente está vencido | Subí un certificado vigente |
| 422 | cannot_revoke_current_key |
Una llave intentó revocarse a sí misma | Revocala con otra llave de cuenta |
| 429 | rate_limited |
Se superó el límite de solicitudes por minuto o por día | Esperá los segundos de Retry-After |
| 500 | internal_error |
Error inesperado de Aster | Reintentá con la misma X-Idempotency-Key |
Ninguno de estos errores registra el comprobante ni gasta el consecutivo, salvo duplicate_clave y duplicate_consecutive, que justamente indican que ya estaba gastado. Los errores de facturación (402) se devuelven antes de firmar, así que podés liberar el número en tu sistema sin riesgo.
Límite del plan alcanzado
Sección titulada «Límite del plan alcanzado»{ "success": false, "error": { "code": "quota_exceeded", "message": "Llegaste al límite de comprobantes de tu plan para este mes.", "upgrade_url": "https://aster.astranexo.com/app/billing/plan", "pack_url": "https://aster.astranexo.com/app/billing/packs" }, "message": "Llegaste al límite de comprobantes de tu plan para este mes.", "timestamp": "2026-10-08T16:20:11Z", "api_version": "1.0"}Mejorá de plan o agregá un paquete en cualquier momento con los enlaces de error.upgrade_url y error.pack_url (usá siempre los que vienen en la respuesta). El cambio se cobra al medio de pago guardado y la facturación se reanuda en menos de un minuto. El modo de prueba no tiene límite de uso. Ver qué cuenta para el uso.
Límite de solicitudes
Sección titulada «Límite de solicitudes»Cada respuesta autenticada trae los encabezados del límite que aplica:
X-RateLimit-Limit: 300X-RateLimit-Remaining: 298X-RateLimit-Reset: 1791476460Al superarlo, la respuesta es 429 rate_limited con Retry-After en segundos. Las solicitudes rechazadas no cuentan para el límite. Ver límites.
Rechazos de Hacienda que Aster detecta antes de enviar
Sección titulada «Rechazos de Hacienda que Aster detecta antes de enviar»Un rechazo de Hacienda gasta el consecutivo y obliga a emitir un comprobante de reemplazo. Por eso Aster revisa antes de firmar las causas de rechazo más frecuentes y responde 422 validation_error con el código de Hacienda en el mensaje, sin enviar nada.
| Código de Hacienda | Qué revisa Aster |
|---|---|
-107, -109, -111, -190, -290, -476, -487 |
Cálculos: montos de línea, subtotales, impuesto, exoneración, impuesto neto, impuesto asumido por el emisor, desglose de impuestos, clasificación de servicios y mercancías y totales del resumen. Se comparan con 5 decimales y la tolerancia de Hacienda |
-38 |
La cédula del emisor y la del receptor están inscritas en Hacienda |
-400 |
El CABYS de cada línea existe en el Catálogo de Bienes y Servicios |
-483, -485 |
Un CABYS exento se factura con la tarifa 10 (Tarifa Exenta) y no con otra tarifa del 0 % |
-491 |
El código de referencia 99 (Otros) lleva reference.code_other_description |
-505 |
El código de tarifa (rate_code) corresponde al porcentaje (rate) |
-509 |
Cada CABYS de una nota de crédito o débito aparece en el comprobante original |
-512 |
El total de una nota de crédito no supera el total del comprobante original |
-17 |
El receptor de una nota de crédito o débito es el mismo del comprobante original |
-29 |
El comprobante referenciado existe y fue aceptado por Hacienda |
-99 |
La clave no se usó antes (responde 409 duplicate_clave) |
Aster también valida la estructura completa de la versión 4.4: campos obligatorios por tipo de comprobante, largos, formatos de cédula (incluidas las cédulas jurídicas alfanuméricas), unidades de medida contra el capítulo del CABYS, códigos de referencia vigentes y las reglas de IVA devuelto.
Las revisiones de notas (-509, -512, -17, -29) usan el comprobante original guardado en Aster. Si el original no está en Aster, esas revisiones de contenido se omiten y el veredicto queda en manos de Hacienda.
Advertencias que no son rechazos
Sección titulada «Advertencias que no son rechazos»Los códigos -37 y -410 son advertencias: Hacienda acepta el comprobante con observaciones menores. Aster lo marca accepted y deja el texto en hacienda_message. Ver ciclo de vida.
Rechazos que llegan de Hacienda
Sección titulada «Rechazos que llegan de Hacienda»Si Hacienda rechaza un comprobante por una regla que Aster no puede verificar antes, el comprobante queda en rejected, recibís el evento document.rejected y el detalle de Hacienda está en hacienda_message. Para corregirlo, emití un comprobante nuevo que reemplace al rechazado (ver consecutivo).