Toda la API REST de Isaak devuelve errores con el mismo envelope. Los códigos HTTP indican la familia; el campo error.code identifica el motivo exacto.
Cuando ok = false, la respuesta sigue siempre este shape. El campo requestId permite correlacionar con nuestros logs si abres un ticket.
{
"ok": false,
"error": {
"code": "scope_insufficient",
"message": "El token no tiene scope 'isaak.invoices.write'."
},
"requestId": "req_2026_01_15_abc123"
}El status HTTP indica la familia del error. Usa error.code para discriminar dentro de cada familia.
| Status | error.code | Cuándo | Acción recomendada |
|---|---|---|---|
| 400 | bad_request | Body o query string mal formado (JSON inválido, parámetros incompatibles). | Validar el payload contra el OpenAPI spec antes de enviar. |
| 401 | unauthorized | Token ausente, mal formado, expirado o revocado. | Comprobar el header Authorization. Renovar la API key desde el dashboard. |
| 403 | scope_insufficient | El token es válido pero no tiene el scope requerido para esa ruta. | Crear una nueva API key con el scope correcto (ej. isaak.invoices.write). |
| 404 | not_found | El recurso solicitado (factura, contacto, etc.) no existe o no pertenece a tu tenant. | Verificar el ID. Recursos de otros tenants devuelven 404 (no 403) por seguridad. |
| 409 | conflict | Estado del recurso incompatible con la acción (ej. emitir factura ya emitida). | Releer el estado actual con GET antes de reintentar. |
| 422 | validation_error | Datos válidos sintácticamente pero no semánticamente (NIF inválido, fecha futura, etc.). | El campo `error.message` indica qué falla. Corregir y reintentar. |
| 428 | confirmation_required | La acción es irreversible (emisión AEAT). Se requiere un segundo POST con el confirmationToken. | Mostrar el `preview` al usuario, capturar consentimiento, reenviar con el token. |
| 429 | rate_limit_exceeded | Has superado el límite de peticiones por minuto. | Respetar el header Retry-After. Implementar backoff exponencial. |
| 500 | internal_error | Error inesperado en Isaak. Si persiste, reportar el `requestId`. | Reintentar con backoff. Si pasa varias veces, escribir a soporte@verifactu.business. |
| 502 | aeat_unavailable | AEAT no responde o devuelve error temporal en el SOAP. | Reintentar a los 30s. Isaak no marca la factura como fallida hasta varios intentos. |
| 503 | maintenance | Mantenimiento programado. Verifactu publica avisos en status.verifactu.business. | Reintentar pasada la ventana. Esperar el header Retry-After si lo hay. |
Valores específicos del campo error.code que conviene tratar de forma explícita en el cliente.
aeat_rejectedAEAT rechazó el registro VeriFactu por validación oficial.
aeat_duplicateHash VeriFactu ya presente. Implica reenvío de factura emitida.
confirmation_token_expiredEl token de confirmación caducó (TTL 5 min).
plan_requiredLa ruta requiere un plan superior (típicamente Business).
tenant_blockedEl tenant está suspendido. Contactar a soporte.
key_revokedLa API key fue revocada manualmente desde el dashboard.
certificate_missingNo hay certificado mTLS configurado para emitir a AEAT.
idempotency_replayIdempotency-Key ya usada con un payload distinto.
Idempotency-Key único por intento lógico.Retry-After en 429 y 503.