Entender y tratar los errores de la API
La API pública de CaptainDNS devuelve todos los errores en una envoltura JSON estandarizada. Esta página lista los códigos canónicos, su significado y la acción correctiva recomendada.
Envoltura estándar
Toda respuesta de error sigue este formato:
{
"code": "QUOTA_EXCEEDED",
"message": "Monthly credits quota exceeded for plan 'starter'.",
"details": {
"tier": "starter",
"credits_used": 50000,
"credits_limit": 50000
},
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
code: cadena estable documentada aquí. Úsala para ramificar tu lógica de manejo de errores.message: descripción legible en inglés. No la parsees; puede evolucionar.details: objeto opcional con contexto específico al código. Su esquema varía según el código. La mayoría de los códigos no exponendetails: la información va entonces enmessage.request_id: identificador CaptainDNS de la petición, útil para abrir un ticket de soporte. Presente solo si la cabeceraX-Request-Idse propagó.documentation_url: enlace a esta página.
El status HTTP acompaña siempre al código. Un cliente robusto ramifica sobre el par (status, code) y trata code como prioritario.
Códigos de autenticación (401)
INVALID_API_KEY
Status: 401.
Causa: cabecera Authorization ausente, prefijo ausente, clave malformada, secreto alterado o clave desconocida del lado CaptainDNS. Un HMAC mismatch y una "clave desconocida" devuelven el mismo código para que un atacante no pueda distinguir ambos casos.
Acción: verifica que la cabecera sea Authorization: Bearer cdns_live_.... Un espacio parásito, un salto de línea o una clave truncada son las causas más frecuentes.
{
"code": "INVALID_API_KEY",
"message": "Invalid API key.",
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Sin campo details; la información va únicamente en message.
EXPIRED_API_KEY
Status: 401.
Causa: la clave superó su expires_at.
{
"code": "EXPIRED_API_KEY",
"message": "This API key has expired.",
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Sin campo details.
Acción: crea una nueva clave con una fecha de expiración más lejana o sin expiración. Las claves sin expires_at son válidas mientras no se revoquen.
REVOKED_API_KEY
Status: 401.
Causa: la clave fue revocada manualmente o automáticamente (fin del grace period de rotación).
{
"code": "REVOKED_API_KEY",
"message": "This API key has been revoked.",
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Sin campo details.
Acción: usa la clave activa. Si no tienes ninguna, crea una desde el dashboard.
Códigos de autorización (403)
INSUFFICIENT_SCOPE
Status: 403.
Causa: la clave no tiene el scope requerido por el endpoint. El scope faltante va concatenado en message.
{
"code": "INSUFFICIENT_SCOPE",
"message": "This API key does not have the required scope: web:read",
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Sin campo details; el scope requerido se lee desde message.
Acción: crea una nueva clave con el scope faltante o usa una clave que ya lo lleve. Los scopes no son modificables después de la creación.
IP_NOT_ALLOWED
Status: 403.
Causa: la clave tiene una allowlist de IP y la IP de la petición no está en ella. La IP cliente se deriva de r.RemoteAddr del lado backend (nunca de un X-Forwarded-For enviado por el cliente), tras una posible reescritura por la capa TrustedProxyRealIP si el hop inmediato es un proxy de confianza configurado del lado CaptainDNS.
{
"code": "IP_NOT_ALLOWED",
"message": "Your IP is not in this key's allowlist.",
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Sin campo details; la IP detectada y la lista CIDR no se devuelven al cliente (se registran del lado servidor).
Acción: añade tu IP a la allowlist de la clave, o enruta tu tráfico por un egress autorizado (proxy, NAT).
QUOTA_EXCEEDED
Status: 403.
Causa: el cupo mensual de créditos se alcanzó y el plan no autoriza overage (plan Free, hard cap).
{
"code": "QUOTA_EXCEEDED",
"message": "Monthly credits quota exceeded for plan 'free'.",
"details": {
"tier": "free",
"credits_used": 30,
"credits_limit": 30
},
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Acción: espera al siguiente período o cambia a un plan superior. El dashboard CaptainDNS permite cambiar de plan en un clic.
OVERAGE_BUDGET_EXCEEDED
Status: 403.
Causa: el perfil activó el overage pero alcanzó el tope presupuestario mensual configurado en el dashboard. Las llamadas siguientes se rechazan hasta el cierre del período o la subida del tope.
{
"code": "OVERAGE_BUDGET_EXCEEDED",
"message": "Overage budget cap reached for plan 'starter'.",
"details": {
"tier": "starter",
"credits_used": 68000,
"credits_limit": 50000
},
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Acción: sube el presupuesto máximo (un importe en euros, no un número de créditos) desde Perfil > Suscripción > Excedente API, pasa a un plan con cupo mayor, o espera al siguiente período mensual.
Códigos de petición (400)
INVALID_REQUEST
Status: 400.
Causa: un componente de la petición no es utilizable. La API pública emite dos casos:
- Cabecera
Idempotency-Keymalformada (caracteres no ASCII, espacios, longitud fuera de rango, valor vacío tras trim). - Body de petición ilegible o que supera el límite de idempotencia (11 MiB).
{
"code": "INVALID_REQUEST",
"message": "Invalid Idempotency-Key header.",
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Sin campo details; el motivo preciso va en message.
Acción: corrige la cabecera o el body y reintenta. Para los errores de validación específicos a un endpoint (dominio inválido, selector desconocido, etc.), consulta la sección Códigos de validación (400).
Códigos de conflicto (409)
IDEMPOTENCY_CONFLICT
Status: 409.
Causa: una clave Idempotency-Key se reutiliza con un body distinto al de la petición original. La comparación se hace sobre el hash SHA-256 del body bruto.
{
"code": "IDEMPOTENCY_CONFLICT",
"message": "Idempotency-Key reused with a different request body.",
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Sin campo details; la clave en conflicto es la que acabas de enviar.
Acción: genera una nueva clave para la nueva petición, o corrige el cliente que modifica el body entre reintentos.
Códigos de rate limit (429)
RATE_LIMITED
Status: 429.
Causa: el token bucket por clave está vacío o se superó el rate limit por IP. Dos variantes de message según la capa alcanzada:
- Bucket IP pre-auth:
"Too many requests from this IP. Slow down.". - Bucket por clave:
"Rate limit exceeded for this API key.".
{
"code": "RATE_LIMITED",
"message": "Rate limit exceeded for this API key.",
"request_id": "req_a1b2c3d4",
"documentation_url": "https://www.captaindns.com/en/docs/api/errors"
}
Sin campo details. La cabecera Retry-After acompaña siempre este código, expresada en segundos. Espera al menos esa duración antes de reintentar. Consulta la guía de rate limiting para las estrategias de backoff.
Códigos de servidor (5xx)
INTERNAL_ERROR
Status: 500 o 503.
Causa: error inesperado del lado CaptainDNS. Dos variantes:
- 500: error aplicativo transitorio (panic de handler, dependencia DB no disponible, error de lookup de tier, etc.). El
messageprecisa el subsistema. - 503: la API pública no está configurada o el grupo
/public/v1/*está explícitamente desactivado del lado plataforma (pepper ausente, flagPUBLICAPI_ENABLED=false). No existe un códigoSERVICE_UNAVAILABLEdistinto: la indisponibilidad comparte el códigoINTERNAL_ERRORcon un status 503.
{
"code": "INTERNAL_ERROR",
"message": "public api is not configured",
"request_id": "req_a1b2c3d4"
}
Sin campo details.
Acción: anota el request_id y abre un ticket de soporte. Los 503 suelen estar ligados a un mantenimiento planificado o a un incidente: consulta el canal de estado oficial antes de reintentar. Reintenta tras unos minutos los 500 transitorios; si la tasa supera el 1 % en una ventana de cinco minutos, alerta al equipo CaptainDNS.
Códigos de validación (400)
La API también devuelve 400 BAD_REQUEST para los errores de validación específicos de cada endpoint. Estos errores no están cubiertos por la envoltura estandarizada anterior porque su estructura varía según el endpoint.
Ejemplo con un DNS resolve con dominio inválido:
{
"error": "invalid domain: must be a valid FQDN",
"field": "domain"
}
Para los endpoints que devuelven errores de validación, consulta la referencia OpenAPI que documenta los esquemas exactos.
Tabla sintética
| Status | Code | Descripción | Acción |
|---|---|---|---|
| 400 | Variable | Error de validación de endpoint | Corregir el body de la petición |
| 400 | INVALID_REQUEST | Idempotency-Key o body ilegible | Corregir la cabecera o el body |
| 401 | INVALID_API_KEY | Clave ausente, malformada o desconocida | Verificar la cabecera Authorization |
| 401 | EXPIRED_API_KEY | Clave expirada | Crear una nueva clave |
| 401 | REVOKED_API_KEY | Clave revocada | Usar una clave activa |
| 403 | INSUFFICIENT_SCOPE | Scope faltante en la clave | Crear una clave con el scope correcto |
| 403 | IP_NOT_ALLOWED | IP fuera de la allowlist | Añadir la IP o pasar por un egress autorizado |
| 403 | QUOTA_EXCEEDED | Cupo mensual alcanzado (hard cap) | Esperar o subir de plan |
| 403 | OVERAGE_BUDGET_EXCEEDED | Tope de overage alcanzado | Subir el tope o cambiar de plan |
| 409 | IDEMPOTENCY_CONFLICT | Misma clave con body distinto | Generar una nueva clave |
| 429 | RATE_LIMITED | Rate limit por IP o por clave superado | Esperar Retry-After |
| 500 | INTERNAL_ERROR | Error de servidor transitorio | Reintentar y abrir ticket si persiste |
| 503 | INTERNAL_ERROR | API pública no configurada | Verificar el estado, reintentar |
Buenas prácticas de manejo
- Ramifica sobre el par (status, code). El status por sí solo no basta: dos 403 pueden venir de
INSUFFICIENT_SCOPEo deIP_NOT_ALLOWED, que merecen acciones distintas. - Registra el
request_id. Es el identificador único de la petición del lado CaptainDNS y es imprescindible para toda investigación de soporte. - No reintentes a ciegas. Los 4xx salvo 429 indican un problema del cliente: reintentar sin cambios no funcionará.
- Respeta
Retry-After. Los 429 y 503 lo incluyen siempre. No lo cortocircuites. - Alerta sobre las tasas de error. 1 % de 5xx en una ventana de 5 minutos es una señal de incidente. Escálalo a tu observabilidad.
Sigue con la referencia OpenAPI para explorar los esquemas endpoint por endpoint, o vuelve al quickstart si quieres retomar desde el principio.