Errores
Cada error trae un código estable que tu código lee y, cuando es un dato, el campo. El formato es el estándar RFC 9457.
Los errores responden con Content-Type: application/problem+json (RFC 9457):
{
"type": "invalid_request",
"title": "The request is not valid",
"status": 422,
"errors": [
{
"path": "lines.0.quantity",
"code": "decimal_format",
"message": "Use a non-negative decimal with at most 6 decimals.",
"fraction": 6
}
]
}- Los códigos son el contrato.
typedice qué clase de respuesta es; cada entrada deerrorstrae sucode, y un error que no es de un campo trae el suyo en el propio problema ("code": "entity_not_found"). Son identificadores en inglés que no cambian: úsalos en tu código. - Los textos están en inglés.
title,detaily cadamessageson para quien lee la respuesta mientras integra y pueden cambiar. Para mostrarle algo a tu cliente, escribe tu propia frase a partir del código, en su idioma: así lo hace nuestra consola, que habla español. - Los datos de cada código van junto a él. Un
too_smalltraeminimum,origineinclusive; uninvalid_type,expected; uninvalid_format,format; uninvalid_value,values; untax_id_mismatch,certificate_tax_idyentity_tax_id. Con ellos escribes la frase sin leer elmessage. - En los errores de validación,
errorslista cada problema con la ruta del campo tal como la enviaste:lines.0.quantityes la cantidad de la primera línea. Las reglas de forma traen un código genérico (invalid_type,too_small,too_big,invalid_format,invalid_value); las del SRI y las nuestras, uno propio (consumidor_final_limit_exceeded). Pueden aparecer códigos nuevos: trata uno que no conoces por sutype.
Un campo desconocido nunca se ignora
Si envías un campo que no existe, no lo pasamos por alto: respondemos 422 con un error por cada campo desconocido, en su ruta.
{
"type": "invalid_request",
"title": "The request is not valid",
"status": 422,
"errors": [
{
"path": "metdata",
"code": "unrecognized_keys",
"message": "Unknown field"
},
{
"path": "lines.0.auxiliary_cod",
"code": "unrecognized_keys",
"message": "Unknown field"
}
]
}Ignorarlo sería peor: creerías que aceptamos un dato que nunca llegó al comprobante. Lo mismo con un campo que no te corresponde decidir, como environment (lo decide tu API key) o establishment al corregir (el número ya está tomado).
Tipos
type | Estado | Qué significa | Qué hacer |
|---|---|---|---|
invalid_request | 422 | Un dato no es válido o rompe una regla del SRI. Es 400 si el cuerpo no es JSON o su Content-Type no es el que la ruta lee | Corrige el campo de errors y reintenta |
unauthorized | 401 | Falta la API key, no es válida o fue revocada | Revisa el encabezado Authorization |
key_not_permitted | 403 | El permiso de tu API key no alcanza para esta operación: el detalle dice cuál hace falta | Usa una API key con ese permiso |
forbidden | 403 | Solo una persona con sesión en la plataforma, y con rol owner o admin cuando se trata de gestionar, puede hacerlo, como crear API keys. Una API key que intenta registrar un negocio recibe el código person_required | Hazlo desde la plataforma |
feature_unavailable | 403 | Esa función no está abierta para tu organización: por ejemplo, un dominio propio del portal en un plan sin el adicional | Mira el code y el plan |
not_found | 404 | No existe en el negocio y el ambiente de tu API key; lo de otro negocio de tu organización responde igual | Revisa el id y la API key que usas |
conflict | 409 | El Idempotency-Key ya se usó con otra venta, o el estado no permite la acción | Usa otra clave o revisa el estado |
not_ready | 409 | Aún no puedes hacerlo: falta entidad, numeración o certificado, o el comprobante no está autorizado (el code dice qué) | Completa lo que dice detail |
plan_limit | 402 | Un negocio en vivo no puede emitir: el comprobante de Producción pasaría el tope de gasto que pusiste (overage_cap_reached), no tiene plan (o lo canceló), no ha completado su primer pago o un cobro está vencido. También rechaza corregir o renumerar un comprobante de Pruebas o Producción. No se numeró nada | Sube el tope, elige un plan y paga, o paga el cobro vencido, y reintenta con la misma Idempotency-Key |
rate_limited | 429 | Enviaste demasiadas solicitudes con la misma API key, o preguntaste por el mismo comprobante otra vez antes de 10 segundos. El encabezado Retry-After dice cuántos segundos esperar | Espera esos segundos y reintenta. Un 429 no hizo nada, reintentarlo es seguro |
payload_too_large | 413 | El cuerpo pasa el límite: 1 MiB en cualquier JSON, en el certificado y en el logo; 50 MB en una importación | Envía menos por solicitud |
payment_unavailable | 503 | La pasarela de pago no responde ahora; no se cobró nada | Reintenta en unos minutos |
authority_unavailable | 503 | El SRI no responde y no tenemos una respuesta guardada | Reintenta en unos minutos |
internal | 500 | Un error nuestro; queda registrado | Reintenta con la misma Idempotency-Key |
El portal de clientes tiene tres más, para su código de acceso: invalid_code (401, con attempts_left), code_expired (401) y too_many_attempts (429).
Códigos de negocio y ambiente
Una API key ya sabe su negocio y su ambiente, así que ninguna petición los dice. Si envías los encabezados Fiscalbase-Entity o Fiscalbase-Environment y no coinciden con los de tu API key, respondemos 422 con el código entity_mismatch o environment_mismatch. Una persona en la plataforma sí los envía: sin Fiscalbase-Entity, una petición sobre un negocio recibe entity_required en el campo fiscalbase-entity. Un Idempotency-Key repetido por otro negocio recibe 409 con idempotency_key_reused, nunca el comprobante del primero.
Las reglas del SRI son errores de validación
Muchas reglas no son de formato sino del SRI, y las revisamos antes de numerar, para que el SRI no te devuelva el comprobante después:
- Una factura de más de USD 50 no puede ir a consumidor final: el comprador debe identificarse.
- Cada línea lleva exactamente un IVA.
- La información adicional cabe en los 15 campos que permite el comprobante.
- En una guía de remisión, el traslado no puede empezar antes de emitirla.
Un comprobante rechazado por estas reglas no consume número.