Conceptos

Errores

Todas las respuestas de error son JSON estándar RFC 7807 (Problem Details). Mismo shape para 4xx y 5xx, con un code machine-readable.

Formato RFC 7807

402 Payment Required
{
  "type": "https://docs.fiscal-web.pe/errors/quota_exceeded",
  "title": "Cuota Free excedida",
  "status": 402,
  "code": "quota_exceeded",
  "detail": "Has usado los 100 documentos gratis de este mes. Activa Pay-as-you-go para continuar.",
  "instance": "/v1/documents",
  "trace_id": "req_01HXYZ...",
  "errors": []
}

Campos:

  • type — URI con doc del error.
  • title — descripción corta human-readable.
  • status — código HTTP.
  • code — identificador machine-readable estable.
  • detail — explicación específica del caso.
  • instance — path o recurso afectado.
  • trace_id — ID único para soporte. Inclúyelo en el ticket.
  • errors — lista de problemas por campo (validation_failed).

Esta es la lista canónica vigente. Tu cliente HTTP debería usar code (no el texto de title) para ramificar lógica:

HTTPcodeSignificado
400invalid_payloadBody inválido o JSON malformado
401auth_requiredFalta o key inválida
401auth_expiredKey revocada o expirada
403insufficient_scopeKey sin permisos suficientes
403tenant_suspendedTenant suspendido por billing
404not_foundRecurso inexistente
409idempotency_conflictMismo key, body distinto
409document_state_conflictAcción incompatible con estado actual
402quota_exceededCuota Free agotada
402payment_requiredSubscripción past_due
422validation_failedCampos inválidos (ver `errors`)
422idempotency_key_missingHeader Idempotency-Key faltante
429rate_limitedDemasiadas peticiones (ver Retry-After)
500internal_errorBug nuestro — repórtalo
503fiscal_core_unavailableFiscal-Core/SUNAT temporal

Estrategia de manejo

  • 4xx (cliente) — fija tu request (no reintentes igual). Las únicas excepciones son rate_limited (espera el Retry-After) y red flakes.
  • 5xx (servidor) — retry con backoff exponencial (200ms → 1s → 5s, máx 3 retries). fiscal_core_unavailable incluye Retry-After con segundos a esperar.
  • 402 quota_exceeded — activa Pay-as-you-go desde /app/billing. Mientras tanto, sandbox sigue funcionando.
  • 422 validation_failed — la lista errors trae field + message + code por cada campo inválido.