Referencia de la API

Endpoints, campos de respuesta, códigos de estado, límites y nuestros compromisos de estabilidad.

Referencia de la API (V2)

URL base: https://api.captchacore.eu: todos los endpoints responden con JSON. Si usa el widget suministrado, nunca llamará usted a /challenge; de eso se encarga el widget. Para un complemento propio solo /verify es obligatorio.

Autenticación

Endpoint Clave Dónde se usa
GET /api/v2/challenge cc_pub_… en el navegador: puede ser pública
POST /api/v2/verify cc_sec_… solo en el servidor: nunca la entregue
GET /api/v2/status cc_sec_… solo en el servidor

La clave va siempre en la cabecera X-CaptchaCore-Key, nunca en la URL.

GET /api/v2/challenge

Solicita un cálculo junto con su política. Parámetro de consulta opcional: form_type (véanse las políticas de formulario). Responde con HTTP 200.

{
  "challenge_id": "ch_a45cd15b0d6d2dc6",
  "nonce": "a45cd15b…1d50",          // einmalig, 5 Minuten gültig
  "expires_at": 1788860066,
  "policy": {
    "mode": "adaptive",
    "challenge_type": "sha256_pow",     // Zusatzprüfung steht ggf. unter "step_up"
    "challenge_types": ["sha256_pow"],
    "difficulty": 4,                  // führende Nullen im Hash
    "algorithm": "sha256",
    "time_budget_ms": 500,
    "requires_interaction": false,
    "requires_stepup_on_submit": false,
    "memory_hard_enabled": false,
    "form_type": "contact",
    "site_profile": "balanced",
    "uam_level": 0              // 0–3, Under-Attack-Stufe
  },
  "bindings": {                       // bindet den Token an Site, Origin und Formular
    "site_id": 2,
    "origin": "https://example.com",
    "form_type": "contact",
    "issued_at": 1788859766,
    "expires_at": 1788860066,
    "token_ttl_sec": 300
  },
  "bindings_signature": "CBkATjVc…RDg==",  // Ed25519, unveränderlich mitschicken
  "signing_key_id": "k_397d99d39156c5f5",
  "widget": { /* im Admin gepflegtes Erscheinungsbild */ },
  "widget_version": "3.0.0"
}

Importante para clientes propios: bindings y bindings_signature deben volver al token sin modificar. Si faltan o se alteran, /verify responde con block.

POST /api/v2/verify

Comprueba el token del formulario. Por regla general responde con HTTP 200, también en caso de rechazo. Evalúe el cuerpo, no el código de estado.

// Request
{
  "token": "<Wert des Feldes captchacore_token>",
  "form_type": "contact",      // optional, steuert die Policy
  "page_url": "https://…",      // optional, nur für Auswertungen
  "client_ip": "203.0.113.42"  // empfohlen: IP des Besuchers
}

// Response
{
  "valid": true,               // false bei block UND bei step_up
  "decision": "allow",        // allow | challenge | step_up | block
  "action": "allow",          // identisch zu decision (älterer Feldname)
  "request_id": "…",          // für Rückfragen an den Support
  "risk_score": 8,             // 0–100, höher = riskanter
  "confidence": 0.94,          // 0.0–1.0 Signalabdeckung
  "reasons": ["pow_valid", "behavior_human_like"],
  "step_up": null             // bei decision=step_up: Daten für die Zusatzprüfung
}

Cómo tratar decision

decision valid Comportamiento recomendado
allow true Procese el formulario con normalidad.
challenge true Déjelo pasar pero regístrelo. Opcionalmente añada una comprobación propia, como un correo de confirmación.
step_up false NO rechace de plano. El widget realiza la comprobación adicional por sí mismo; devuelva el formulario al usuario con un mensaje amable.
block false Rechace. Muestre un error sin detalles para que los atacantes no aprendan nada.

GET /api/v2/status

Disponibilidad y nivel actual de ataque del sitio. Adecuado para una comprobación de estado en su complemento.

{ "status": "ok", "under_attack": false, "version": "2.x" }

Códigos de estado HTTP

Código Cuerpo Causa y reacción
200 {"valid": …} Caso normal, también en caso de rechazo. Evalúe el cuerpo.
401 {"error":"Missing API key"} Falta la cabecera X-CaptchaCore-Key.
401 {"error":"Invalid API key"} Clave incorrecta, revocada o de otro sitio. También ocurre si se usa la clave pública en /verify.
403 {"error": …} El origen no está entre los dominios permitidos del sitio.
200 {"valid": false, "reasons": ["invalid_request"]} Falta el campo obligatorio token o no se puede usar.
200 {"valid": false, "reasons": ["rate_limited"]} Se ha alcanzado el límite de verificación del sitio. Rechace la solicitud, no la deje pasar.
429 — Solo en /challenge (límite por IP del visitante). Por encima del límite, verify responde con 200 y «rechazado».
401 {"error":"Invalid API key"} También si la organización se ha eliminado o desactivado: sus claves dejan de ser válidas.
503 {"error":"Account suspended"} Cuenta bloqueada por un pago pendiente. Solo /verify y /status; los challenges siguen funcionando. La protección queda suspendida y su integración aplica su regla de fail-open para que usted pueda seguir iniciando sesión.
5xx — Una avería por nuestra parte. Se aplica su regla fail-open o fail-closed.

Límites de peticiones

Endpoint Límite Contado por
GET /api/v2/challenge300 / minRed del visitante y sitio (IPv6 por /64); 1200 / min por red en todos los sitios
POST /api/v2/verify600 / minclave de sitio del cliente
POST /api/v2/verify30 / minClave del sitio e IP del visitante (client_ip, IPv6 por /64)

Verify se cuenta por sitio, no por IP. Su servidor puede así comprobar tantos formularios como tráfico tenga su sitio, sin bloquearse a sí mismo.

En el límite por sitio solo cuentan los tokens de un challenge realmente emitido. Las solicitudes basura de un atacante chocan con el límite por IP del visitante y no agotan el contingente de sus visitantes reales. Para ello, envíe client_ip, como hacen todas las integraciones oficiales.

Webhooks

CaptchaCore avisa a sus propios sistemas cuando ocurre algo a lo que quiera reaccionar: cuota alcanzada, modo under-attack activado, cuenta bloqueada o desbloqueada. Se configura en el área de cliente en Sitios → Webhooks (a partir del plan Professional).

Eventos

EventoCuándo
usage.warningCuota mensual al 80 % o 90 %
usage.limit_reachedCuota mensual alcanzada: se rechazan más verificaciones
site.under_attack.activatedModo under-attack de un sitio activado (manual o automáticamente)
site.under_attack.deactivatedModo under-attack de un sitio finalizado
organisation.blockedCuenta bloqueada (p. ej. factura pendiente): se rechazan las llamadas a la API
organisation.unblockedCuenta desbloqueada de nuevo
webhook.testEvento de prueba desde el área de cliente

Qué llega

Un POST con cuerpo JSON. Tres cabeceras ayudan a identificarlo y verificarlo:

POST /ihr-endpunkt HTTP/1.1
Content-Type: application/json
X-CaptchaCore-Event: usage.limit_reached
X-CaptchaCore-Delivery: 5f1c2c1e-…            // eindeutig je Zustellung, gleich bei Wiederholungen
X-CaptchaCore-Timestamp: 1758196800
X-CaptchaCore-Signature: sha256=3b2a…

{
  "event": "usage.limit_reached",
  "occurred_at": "2026-09-18T14:00:00+02:00",
  "organisation_id": 42,
  "data": { "threshold_percent": 100, "used": 10000, "limit": 10000, "plan": "pro", "period": "2026-09" }
}

Verificar la firma

La firma es un HMAC-SHA256 sobre «timestamp.body» con la clave del área de cliente. Compare en tiempo constante y rechace marcas de tiempo de más de cinco minutos: así evita repeticiones de solicitudes interceptadas.

$secret    = getenv('CAPTCHACORE_WEBHOOK_SECRET');
$body      = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_CAPTCHACORE_TIMESTAMP'] ?? '';
$expected  = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret);

if (abs(time() - (int) $timestamp) > 300
    || ! hash_equals($expected, $_SERVER['HTTP_X_CAPTCHACORE_SIGNATURE'] ?? '')) {
    http_response_code(401); exit;
}

$event = json_decode($body, true);
// … verarbeiten, dann schnell mit 2xx antworten
http_response_code(204);

Entrega y reintentos

  • Responda con un estado 2xx en menos de 5 segundos; procese lo costoso de forma asíncrona.
  • Ante errores o tiempo de espera se reintenta hasta tres veces (a los 30 segundos y a los 5 minutos) con el mismo ID de entrega; haga su procesamiento idempotente con él.
  • Tras diez fallos consecutivos el webhook se desactiva; en el área de cliente verá el motivo y podrá reactivarlo.
  • Cada entrega, con código de respuesta, duración y extracto de la respuesta, figura en «Entregas», también para depurar en su lado.

Versionado y estabilidad

Quien mantiene un complemento necesita saber con qué puede contar. Estos son nuestros compromisos.

La versión de la ruta se mantiene estable

Dentro de /api/v2 no eliminamos ni renombramos campos de respuesta. Pueden aparecer campos nuevos en cualquier momento: lea las respuestas con tolerancia y no falle ante claves desconocidas.

V1 está obsoleta

La antigua interfaz de verificación en /api/v1 y el widget captchacore.min.js solo siguen funcionando para integraciones antiguas; el widget muestra a los visitantes un aviso de actualización. Cambie a V2: anunciaremos la fecha de desactivación con antelación.

El widget se actualiza solo

A través de la ruta del CDN captchacore-v2.min.js siempre obtiene la versión mantenida. No incluya una copia propia o se perderá las mejoras en la detección de bots.

Anunciamos los cambios

Todo lo que pueda afectar a integraciones existentes se anuncia con antelación en el estado público del sistema y por correo a la dirección técnica registrada.

← Atrás Widget Siguiente → Detección