Ir al contenido principal

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 exponen details: la información va entonces en message.
  • request_id: identificador CaptainDNS de la petición, útil para abrir un ticket de soporte. Presente solo si la cabecera X-Request-Id se 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-Key malformada (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 message precisa el subsistema.
  • 503: la API pública no está configurada o el grupo /public/v1/* está explícitamente desactivado del lado plataforma (pepper ausente, flag PUBLICAPI_ENABLED=false). No existe un código SERVICE_UNAVAILABLE distinto: la indisponibilidad comparte el código INTERNAL_ERROR con 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

StatusCodeDescripciónAcción
400VariableError de validación de endpointCorregir el body de la petición
400INVALID_REQUESTIdempotency-Key o body ilegibleCorregir la cabecera o el body
401INVALID_API_KEYClave ausente, malformada o desconocidaVerificar la cabecera Authorization
401EXPIRED_API_KEYClave expiradaCrear una nueva clave
401REVOKED_API_KEYClave revocadaUsar una clave activa
403INSUFFICIENT_SCOPEScope faltante en la claveCrear una clave con el scope correcto
403IP_NOT_ALLOWEDIP fuera de la allowlistAñadir la IP o pasar por un egress autorizado
403QUOTA_EXCEEDEDCupo mensual alcanzado (hard cap)Esperar o subir de plan
403OVERAGE_BUDGET_EXCEEDEDTope de overage alcanzadoSubir el tope o cambiar de plan
409IDEMPOTENCY_CONFLICTMisma clave con body distintoGenerar una nueva clave
429RATE_LIMITEDRate limit por IP o por clave superadoEsperar Retry-After
500INTERNAL_ERRORError de servidor transitorioReintentar y abrir ticket si persiste
503INTERNAL_ERRORAPI pública no configuradaVerificar 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_SCOPE o de IP_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.