Saltearse al contenido

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:

CampoTipoDescripción
typeURIURL canónica del tipo de error (siempre resuelve a esta docs)
titlestringDescripción corta, idioma según Accept-Language
statusintegerCódigo HTTP de la respuesta
detailstringDescripción larga con contexto específico de la petición
instancestringPath del endpoint que generó el error
request_idstringID único de la petición, útil para soporte
codestringIdentificador de máquina del error
docs_urlstringEnlace 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: en

Catá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 Authorization tiene el formato incorrecto (debe ser Bearer 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_transactions y ledger_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}`);
}