API-Referenz
Endpunkte, Antwortfelder, Statuscodes, Rate-Limits und unsere Zusagen zur Stabilität.
Auf dieser Seite
API-Referenz (V2)
Basis-URL: https://api.captchacore.eu — alle Endpunkte antworten mit JSON. Wer das mitgelieferte Widget einsetzt, ruft /challenge nie selbst auf; das übernimmt das Widget. Für ein eigenes Plugin ist nur /verify Pflicht.
Authentifizierung
| Endpunkt | Schlüssel | Wo verwendet |
|---|---|---|
| GET /api/v2/challenge | cc_pub_… | im Browser — darf öffentlich sein |
| POST /api/v2/verify | cc_sec_… | nur auf dem Server — niemals ausliefern |
| GET /api/v2/status | cc_sec_… | nur auf dem Server |
Der Schlüssel gehört immer in den Header X-CaptchaCore-Key, nie in die URL.
GET /api/v2/challenge
Fordert eine Rechenaufgabe samt Policy an. Optionaler Query-Parameter: form_type (siehe Form-Policies). Antwortet mit HTTP 200.
{
"challenge_id": "ch_a45cd15b0d6d2dc6",
"nonce": "a45cd15b…1d50", // einmalig, 5 Minuten gültig
"expires_at": 1788860066,
"policy": {
"mode": "adaptive",
"challenge_type": "sha256_pow", // oder argon2id_pow, interaction_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"
}
Wichtig für eigene Clients: bindings und bindings_signature müssen unverändert in den Token zurückwandern. Fehlen sie oder wurden sie verändert, antwortet /verify mit block.
POST /api/v2/verify
Prüft den Token aus dem Formular. Antwortet im Regelfall mit HTTP 200 — auch bei einer Ablehnung. Werten Sie den Body aus, nicht den Statuscode.
// Request { "token": "<Wert des Feldes captchacore_token>", "form_type": "contact", // optional, steuert die Policy "page_url": "https://…" // optional, nur für Auswertungen } // Response { "valid": true, // false bei block UND bei step_up "decision": "allow", // allow | challenge | step_up | block "action": "allow", // identisch zu decision, für V1-Kompatibilität "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 }
Wie Sie decision behandeln
| decision | valid | Empfohlenes Verhalten |
|---|---|---|
| allow | true | Formular normal verarbeiten. |
| challenge | true | Durchlassen, aber protokollieren. Optional eine zusätzliche eigene Prüfung, etwa eine Bestätigungsmail. |
| step_up | false | NICHT hart ablehnen. Das Widget führt die Zusatzprüfung selbst durch; geben Sie dem Nutzer das Formular mit einer freundlichen Meldung zurück. |
| block | false | Ablehnen. Fehlermeldung ohne Details anzeigen, damit Angreifer nichts lernen. |
GET /api/v2/status
Erreichbarkeit und aktuelle Under-Attack-Stufe der Site. Eignet sich für einen Health-Check im Plugin.
{ "status": "ok", "under_attack": false, "version": "2.x" }
HTTP-Statuscodes
| Code | Body | Ursache und Reaktion |
|---|---|---|
| 200 | {"valid": …} | Normalfall, auch bei Ablehnung. Body auswerten. |
| 401 | {"error":"Missing API key"} | Header X-CaptchaCore-Key fehlt. |
| 401 | {"error":"Invalid API key"} | Schlüssel falsch, widerrufen oder für die falsche Site. Auch der Fall, wenn der öffentliche Schlüssel auf /verify verwendet wird. |
| 403 | {"error": …} | Origin gehört nicht zu den erlaubten Domains der Site. |
| 422 | {"message": …} | Pflichtfeld fehlt, meist token. |
| 429 | — | Rate-Limit erreicht. Wie einen Ausfall behandeln, siehe Fehlerbehandlung. |
| 5xx | — | Störung auf unserer Seite. Fail-Open- oder Fail-Closed-Regel greift. |
Rate-Limits
| Endpunkt | Grenze | Gezählt nach |
|---|---|---|
| GET /api/v2/challenge | 60 / min | IP des Besuchers |
| POST /api/v2/verify | 600 / min | Site-Key des Kunden |
Verify wird pro Site gezählt, nicht pro IP. Ihr Server darf also so viele Formulare prüfen, wie Ihre Site an Verkehr hat, ohne sich selbst auszusperren.
Webhooks
CaptchaCore benachrichtigt Ihre eigenen Systeme, wenn etwas passiert, auf das Sie reagieren wollen: erreichtes Kontingent, ausgelöster Under-Attack-Mode, gesperrtes oder freigeschaltetes Konto. Eingerichtet wird das im Kundenbereich unter Sites → Webhooks (ab Tarif Professional).
Ereignisse
| Ereignis | Wann |
|---|---|
| usage.warning | Monatskontingent zu 80 % bzw. 90 % ausgeschöpft |
| usage.limit_reached | Monatskontingent erreicht — weitere Verifikationen werden abgewiesen |
| site.under_attack.activated | Under-Attack-Mode einer Site aktiviert (manuell oder automatisch) |
| site.under_attack.deactivated | Under-Attack-Mode einer Site beendet |
| organisation.blocked | Konto gesperrt (z. B. offene Rechnung) — API-Aufrufe werden abgewiesen |
| organisation.unblocked | Konto wieder freigeschaltet |
| webhook.test | Testereignis aus dem Kundenbereich |
Was ankommt
Ein POST mit JSON-Body. Drei Header helfen beim Zuordnen und Prüfen:
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" }
}Signatur prüfen
Die Signatur ist ein HMAC-SHA256 über „Timestamp.Body" mit dem Schlüssel aus dem Kundenbereich. Vergleichen Sie zeitkonstant und lehnen Sie Zeitstempel ab, die älter als fünf Minuten sind — das verhindert Wiederholungen abgefangener Anfragen.
$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);
Zustellung und Wiederholung
- Antworten Sie innerhalb von 5 Sekunden mit einem 2xx-Status — verarbeiten Sie aufwendige Dinge asynchron.
- Bei Fehlern oder Timeout wird bis zu dreimal zugestellt (nach 30 Sekunden und nach 5 Minuten), mit derselben Delivery-ID — machen Sie Ihre Verarbeitung damit idempotent.
- Nach zehn Fehlschlägen in Folge wird der Webhook abgeschaltet; im Kundenbereich sehen Sie den Grund und können ihn wieder einschalten.
- Jede Zustellung mit Antwortcode, Dauer und Antwortauszug steht unter „Zustellungen" — auch für die Fehlersuche auf Ihrer Seite.
Versionierung und Stabilität
Wer ein Plugin pflegt, muss wissen, worauf er sich verlassen kann. Das sind unsere Zusagen.
Die Pfad-Version bleibt stabil
Innerhalb von /api/v2 entfernen und benennen wir keine Antwortfelder um. Neue Felder können jederzeit hinzukommen — lesen Sie Antworten deshalb tolerant und brechen Sie nicht bei unbekannten Schlüsseln ab.
V1 bleibt vorerst erreichbar
Die alte Schnittstelle unter /api/v1 wird weiter bedient, erhält aber keine neuen Signale mehr. Neue Integrationen sollten ausschließlich V2 verwenden.
Das Widget aktualisiert sich selbst
Über den CDN-Pfad captchacore-v2.min.js erhalten Sie immer die gepflegte Fassung. Binden Sie keine eigene Kopie ein, sonst verpassen Sie Verbesserungen an der Bot-Erkennung.
Änderungen kündigen wir an
Alles, was bestehende Integrationen betreffen könnte, sagen wir vorher über den öffentlichen Systemstatus und per E-Mail an die hinterlegte technische Adresse an.