Errores
Todos los errores tienen el mismo formato:
{ "error": { "type": "validation_error", "code": "customer_document_required", "message": "Una boleta mayor a S/ 700.00 requiere identificar al cliente con un documento admitido.", "param": "customer.document_number", "request_id": "req_0192f1a27c3e7d4b9a8f2b6c1d0e4f5a" }, "errors": [ { "code": "customer_document_required", "message": "...", "param": "customer.document_number" }, { "code": "issue_date_out_of_window", "message": "...", "param": "issue_date" } ]}Programa contra error.code, no contra el texto en español de error.message, que es apto para mostrar a un operador. param aparece cuando el error apunta a un campo, con su ruta en el JSON (items[2].unit_price), y errors cuando hay varios problemas. Conserva error.request_id o la cabecera X-Request-Id para soporte. Un error HTTP al emitir es distinto de un rechazo fiscal posterior: el rechazo llega en el documento y por webhook, nunca como un error de POST /v1/documents.
| Resultado | Qué hacer |
|---|---|
Red, tiempo de espera, 500, 503 |
Consultar por identidad; reintentar la misma operación con los mismos bytes y la misma clave, con espera exponencial y variación aleatoria, de 1 s hasta 1 min (reintentos) |
409 idempotency_in_progress |
Esperar y repetir igual |
429 rate_limited |
Esperar los segundos de Retry-After; vigilar RateLimit-Limit, RateLimit-Remaining y RateLimit-Reset |
409 external_id_conflict |
Consultar error.document_id, sin cambiar la identidad para forzar la emisión |
422 idempotency_key_reused |
Recuperar los bytes de la solicitud original y conciliarla; la clave ya tiene una respuesta confirmada |
401 |
Revisar la clave completa, su rotación, revocación o vencimiento |
403 forbidden |
El message nombra el scope que falta. En Configuración → API keys se ven los permisos de cada clave; si falta un scope, un owner o admin crea otra clave, porque rotar conserva los mismos permisos |
403 tenant_suspended |
Resolver la suspensión con Boletura |
403 plan_without_api |
El plan de la cuenta no incluye la API: pedir a Boletura un plan con API |
403 account_not_activated |
La cuenta todavía no emite en live: Boletura la activa al confirmar el plan. En test sigue emitiendo |
404 not_found |
Comprobar el UUID, la cuenta y el ambiente; un documento de otra cuenta también responde 404 |
400, 413, 415, 422 y los demás 409 |
Corregir la causa antes de reintentar; no repetir a ciegas |
Errores frecuentes: company_required, series_not_found, company_not_ready, customer_ruc_required, unit_amount_ambiguous e invalid_json. Si recibes certificate_required en test, falta el certificado de prueba de la plataforma: escribe a soporte@boletura.com. Los números entre comillas, las fechas con hora y los UUID mal escritos son errores de formato. Los errores no se guardan en la respuesta idempotente: tras un 422 de validación, corrige y envía con la misma clave, salvo idempotency_key_reused, porque esa clave ya tiene una respuesta exitosa guardada. Tras una respuesta perdida no cambies el cuerpo.
La referencia lista en cada operación sus respuestas de error y, en la descripción de cada campo, el código que responde un valor no válido.
Límites
Sección titulada «Límites»600 solicitudes por minuto por clave y 1200 por IP, en ventanas fijas de un minuto. Toda respuesta de /v1 lleva RateLimit-Limit, RateLimit-Remaining y RateLimit-Reset; el exceso responde 429 rate_limited con Retry-After.
Las emisiones de una misma serie se numeran de a una: mandarlas en paralelo no las acelera, y cientos a la vez sobre una serie tardan varios segundos en responder. Conviene tener pocas solicitudes en curso por serie y repartirlas en el minuto.