Errores
Celestín usa el formato RFC 7807 Problem+JSON para todos los errores. Cada respuesta de error tiene Content-Type: application/problem+json y un cuerpo estructurado con extensiones propias.
Formato de error
{ "type": "https://docs.celestin.es/errors/invalid_api_key", "title": "API key inválida", "status": 401, "detail": "La API key proporcionada no existe o ha sido revocada.", "instance": "/v1/reconciliations", "request_id": "req_01HXYZ789GHI", "code": "invalid_api_key", "docs_url": "https://docs.celestin.es/errors/#invalid_api_key"}Campos:
| Campo | Tipo | Descripción |
|---|---|---|
type | URI | URL canónica del tipo de error (siempre resuelve a esta docs) |
title | string | Descripción corta, idioma según Accept-Language |
status | integer | Código HTTP de la respuesta |
detail | string | Descripción larga con contexto específico de la petición |
instance | string | Path del endpoint que generó el error |
request_id | string | ID único de la petición, útil para soporte |
code | string | Identificador de máquina del error |
docs_url | string | Enlace directo a esta sección |
Idioma
El campo title y detail se devuelven en el idioma indicado por el header Accept-Language. Valores soportados: es (defecto), en. Si el idioma no está soportado, se usa es.
Accept-Language: enCatálogo de errores
invalid_api_key 401
La API key no existe, ha sido revocada o el formato es incorrecto.
Causas comunes:
- La key fue rotada y el sistema antiguo aún usa la versión revocada.
- Se usa una key de test (
sk_test_) contra el endpoint de producción o viceversa. - El header
Authorizationtiene el formato incorrecto (debe serBearer sk_...).
Resolución: Verifica en el panel que la key existe y tiene estado active. Genera una nueva key si es necesario.
validation_failed 422
El payload no cumple el schema esperado. El cuerpo incluye un array errors con los campos que fallan:
{ "code": "validation_failed", "errors": [ { "field": "bank_transactions[0].amount", "message": "El importe no puede ser cero.", "code": "amount_zero" } ]}Causas comunes:
- Fechas en formato incorrecto (se esperan
YYYY-MM-DD). - Importes en cero o con más de 2 decimales.
- Arrays vacíos — mínimo 1 elemento en
bank_transactionsyledger_entries.
monthly_job_cap_exceeded 429
El tenant ha consumido toda su cuota mensual de conciliaciones.
{ "code": "monthly_job_cap_exceeded", "detail": "Has usado 100/100 jobs este mes. El contador se reinicia el 1 de mayo.", "reset_at": "2026-05-01T00:00:00Z", "quota": 100, "used": 100}Resolución: Espera al primer día del mes o solicita un aumento de cuota via PATCH /v1/tenants/{id}.
rate_limited 429
Se han enviado demasiadas peticiones en poco tiempo. Diferente de monthly_job_cap_exceeded — este es un límite por segundo/minuto, no mensual.
{ "code": "rate_limited", "detail": "Límite de 10 peticiones por segundo superado.", "retry_after": 2}El header Retry-After (en segundos) indica cuánto esperar. El SDK aplica backoff exponencial automáticamente.
unauthorized_pii_in_payload 400
El servidor detectó posible PII en el payload que debería haber sido anonimizado por el SDK. La petición es rechazada sin procesarse.
{ "code": "unauthorized_pii_in_payload", "detail": "Se detectó un posible IBAN en bank_transactions[3].description. Activa la anonimización del SDK.", "field": "bank_transactions[3].description", "pattern_type": "IBAN_ES"}Resolución: Activa anonymization: { enabled: true } en la configuración del SDK o asegúrate de llamar a redact() manualmente antes de enviar el payload.
reconciliation_not_found 404
No existe ninguna conciliación con el ID indicado en el tenant actual.
{ "code": "reconciliation_not_found", "detail": "No existe la conciliación rec_01HXYZ123ABC en el tenant sociedad-a-sl."}Causas comunes:
- ID incorrecto o typo.
- La conciliación pertenece a otro tenant (comprueba el header
X-Celestin-Tenant). - El TTL de 24 h ha expirado — ver
reconciliation_expired.
reconciliation_expired 404
La conciliación existía pero su TTL de 24 h ha vencido y los datos han sido eliminados.
{ "code": "reconciliation_expired", "detail": "La conciliación rec_01HXYZ123ABC expiró el 2026-03-16T09:12:34Z.", "expired_at": "2026-03-16T09:12:34Z"}Resolución: Suscríbete al webhook reconciliation.completed para capturar el resultado inmediatamente o reduce el tiempo entre la creación y la lectura.
missing_tenant_header 400
El endpoint requiere el header X-Celestin-Tenant pero no estaba presente.
tenant_suspended 403
El tenant está en estado suspended y no puede crear nuevos recursos.
tenant_not_found 404
El tenant indicado en X-Celestin-Tenant no existe en este partner.
Manejo de errores — ejemplos
Node.js con el SDK:
import { CelestinClient, CelestinError } from "@celestin/sdk";
try { const result = await client.reconciliations.create({ ... });} catch (err) { if (err instanceof CelestinError) { console.error(`[${err.code}] ${err.detail}`); console.error(`request_id: ${err.requestId}`);
if (err.code === "monthly_job_cap_exceeded") { console.error(`Reinicio de cuota: ${err.data.reset_at}`); } }}Python con el SDK:
from celestin import CelestinClient, CelestinError
try: result = client.reconciliations.create(...)except CelestinError as e: print(f"[{e.code}] {e.detail}") print(f"request_id: {e.request_id}")
if e.code == "monthly_job_cap_exceeded": print(f"Reinicio de cuota: {e.data['reset_at']}")HTTP directo (sin SDK):
const response = await fetch("https://api.celestin.es/v1/reconciliations", { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }, body: JSON.stringify(payload),});
if (!response.ok) { const error = await response.json(); // error.code, error.detail, error.request_id throw new Error(`Celestín API error: ${error.code} — ${error.detail}`);}