Saltar al contenido
Krezkadev

Errores

Formato de errores, códigos de estado y los errores propios de SUNAT.

La API usa códigos de estado HTTP convencionales y devuelve un cuerpo de error consistente para que puedas manejarlo de forma programática.

Formato del error

JSON
JSON
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "El campo customer.document_number es obligatorio.",
    "param": "customer.document_number"
  }
}
CampoDescripción
typeCategoría del error (ver abajo).
codeCódigo estable y legible por máquina.
messageMensaje descriptivo para humanos.
paramCampo que causó el error, si aplica.

Códigos de estado

CódigoSignificadoCuándo ocurre
200 / 201OKLa solicitud tuvo éxito.
202AcceptedEl comprobante quedó en cola para SUNAT. El resultado llega por webhook.
400Bad RequestLa solicitud está mal formada.
401UnauthorizedAPI key ausente o inválida.
402Payment RequiredTu cuenta superó el tope de crédito del mes.
403ForbiddenLa key no puede usar ese emisor.
404Not FoundEl recurso no existe.
409ConflictConflicto de estado o de idempotencia.
422UnprocessableUn campo no cumple una regla, nuestra o de SUNAT.
429Too Many RequestsSuperaste el límite de tasa.
5xxServer ErrorFalla nuestra. Reintenta con la misma Idempotency-Key.

Conflictos (409)

error.codeQué pasó
idempotency_key_reusedUsaste una Idempotency-Key con un cuerpo distinto al original.
invoice_not_voidableSolo se anulan comprobantes accepted u observed.
void_window_expiredPasaron más de 7 días; emite una nota de crédito en su lugar.
cdr_not_availableSUNAT aún no respondió. Espera el webhook.

Rechazos de SUNAT

Un comprobante aceptado por nosotros (202) todavía puede ser rechazado por SUNAT. No es un error HTTP: es un cambio de estado a rejected, con el código y el mensaje de SUNAT en status_history. Lo recibes en el webhook invoice.rejected.

JSON
JSON
{
  "status": "rejected",
  "status_history": [
    { "status": "pending", "at": "2026-11-02T15:04:05Z" },
    { "status": "sent", "at": "2026-11-02T15:04:06Z" },
    { "status": "rejected", "at": "2026-11-02T15:04:09Z", "sunat_code": "2017", "message": "El RUC del receptor no existe" }
  ]
}

Un comprobante rechazado no se corrige: emite uno nuevo con los datos correctos. El correlativo rechazado queda registrado así ante SUNAT y no se reutiliza.

Dar de alta un emisor no es inmediato

Registrar un RUC nuevo dispara un alta ante SUNAT que suele completarse al día siguiente. No es instantáneo y no depende de nosotros: lo ejecuta el proveedor de firma y lo aprueba SUNAT, que a veces tiene intermitencias.

Mientras tanto el emisor está en status: "pending" y cualquier emisión devuelve 409:

JSON
JSON
{
  "error": {
    "type": "invalid_request_error",
    "code": "issuer_not_ready",
    "message": "El alta de este RUC ante SUNAT todavía está en curso. Suele estar listo al día siguiente.",
    "param": "issuer_id"
  },
  "available_at": "2026-11-03T14:20:00Z"
}

Esto es deliberado y te ahorra plata. El correlativo se asigna al crear el comprobante, antes de que SUNAT opine, así que un intento contra un RUC que todavía no está habilitado gasta un número de serie que no se recupera. Preferimos devolverte un 409 barato.

CódigoQué pasóQué hacer
issuer_not_readyEl alta sigue en curso.Espera a available_at y reintenta.
issuer_not_authorizedSUNAT rechazó el RUC (0111 o 0154).Lee status_detail: tu cliente debe resolverlo en SUNAT.
issuer_not_configuredLa empresa sigue en prueba.Pásala a producción desde la consola (Mis empresas).

Si el emisor queda not_authorized

Son dos causas, las dos del lado del contribuyente y ninguna se arregla reintentando:

  • 0111 — el RUC no está habilitado como emisor electrónico. Se habilita desde SUNAT con la clave SOL.
  • 0154 — el RUC no autorizó al proveedor de firma (PSE). También se hace desde la clave SOL del contribuyente.

Bloqueamos al emisor en cuanto SUNAT responde alguno de los dos. No es una limitación: es lo que evita que tu integración siga gastando correlativos contra un problema que sólo puede resolver tu cliente.