Claimscan
API OPERATIONALAnmeldenKostenlos testen
// WEBHOOKS

Webhook-Events

Case-Lifecycle-Events mit HMAC-SHA256-signierten Payloads abonnieren. Endpoints werden im Dashboard unter Integrations konfiguriert.

Eventkatalog

Heute feuern drei Eventtypen. Neue Events sind nicht-breaking — dein Endpoint erhält nur die Typen, die du abonniert hast, neue müssen explizit aktiviert werden.

EventWann es feuert
case.completedAnalyse-Pipeline ist für einen Case durchgelaufen (beliebiges Verdikt).
case.failedPipeline ist abgebrochen, bevor ein Verdikt feststand — neuer Versuch oder Re-Upload nötig.
case.high_fraud_riskVerdikt LIKELY_MANIPULATED oder LIKELY_AI_GENERATED mit hoher Konfidenz.

Payload-Envelope

Jedes Event landet in einer stabilen Hülle. Eventspezifische Felder liegen unter data; die Hülle selbst ändert sich nie.

{
  "id": "evt_8a1c2d3e-4f5g-6789-abcd-ef0123456789",
  "type": "case.completed",
  "created": "2026-04-25T18:42:11.482Z",
  "data": {
    "caseId": "ce_01J9XJ3K4Q9R5S6T7U8V9W0X1Y",
    "verdict": "SUSPICIOUS",
    "confidence": 62,
    "criticalFindings": 0,
    "imageCount": 3,
    "completedAt": "2026-04-25T18:42:11.391Z"
  }
}

Signaturprüfung

Jede Auslieferung trägt einen X-Claimscan-Signature-Header — damit lässt sich nachweisen, dass der Request wirklich von Claimscan stammt und unterwegs nicht verändert wurde. Requests ohne valide Signatur müssen abgelehnt werden.

Der Header packt einen Unix-Timestamp und einen hex-codierten HMAC-Digest komma-getrennt zusammen:

X-Claimscan-Signature: t=1714069331,v1=8e2c9f4b1d7a6e3c0b8f5a2d9c1e6b4f3a7d8c2e5f9a1b4c7d0e3f6a9b2c5d8e

Verifikation in vier Schritten:

  1. Header in t (Timestamp) und v1 (Signatur) zerlegen.
  2. Ablehnen, falls abs(now - t) > 300 Sekunden — Replay-Schutz.
  3. HMAC-SHA256 über `${t}.${rawBody}` mit dem Endpoint-Secret berechnen. Den Roh-Body nutzen, nicht eine neu serialisierte JSON-Variante.
  4. Mit v1 in konstanter Zeit vergleichen (timingSafeEqual in Node).

Referenzimplementierung (Node)

import { createHmac, timingSafeEqual } from "node:crypto";

/**
 * Verify a Claimscan webhook signature. Reject if:
 *   - timestamp is older than 5 minutes (replay protection)
 *   - HMAC-SHA256 over `${timestamp}.${rawBody}` does not match v1
 */
export function verifyClaimscanSignature(opts: {
  header: string;        // X-Claimscan-Signature
  rawBody: string;       // request body BEFORE JSON.parse
  secret: string;        // whsec_<base64url>
}): boolean {
  const parts = Object.fromEntries(
    opts.header.split(",").map((p) => p.split("="))
  );
  const t = Number.parseInt(parts.t ?? "", 10);
  const v1 = parts.v1;
  if (!Number.isFinite(t) || !v1) return false;

  const skew = Math.abs(Math.floor(Date.now() / 1000) - t);
  if (skew > 5 * 60) return false;

  const expected = createHmac("sha256", opts.secret)
    .update(`${t}.${opts.rawBody}`)
    .digest();
  const actual = Buffer.from(v1, "hex");
  if (actual.length !== expected.length) return false;
  return timingSafeEqual(actual, expected);
}

Retry-Policy

Fehlgeschlagene Auslieferungen (Netzwerkfehler oder HTTP 4xx/5xx ausser 410 Gone) werden bis zu vier Mal mit exponentiellem Backoff wiederholt:

VersuchWartezeit nach vorherigem Fehlschlag
1Sofort
2≈ 30 Sekunden
3≈ 5 Minuten
4≈ 30 Minuten

Nach dem vierten Fehlschlag wird die Auslieferung im Dashboard als gescheitert markiert. Im Delivery-Log lässt sich nach einem Endpoint-Fix manuell erneut zustellen.

Sicherheitshinweise

  • Webhook-URLs müssen öffentlich per HTTPS erreichbar sein. Private IP-Bereiche, Link-Local- und Metadaten-Adressen werden bei der Registrierung blockiert (SSRF-Guard).
  • HTTP-URLs werden abgewiesen. Self-signed Certificates sind in Produktion nicht unterstützt.
  • Endpoint-Secret wie einen API-Schlüssel behandeln — nur server-seitig speichern, nie im Client-Code, und im Dashboard rotieren, falls ein Leck vermutet wird.
  • Auslieferungen immer als at-least-once behandeln. Die envelope.id eignet sich als Deduplikations-Schlüssel auf deiner Seite.

Endpoints verwalten

Webhook-Endpoints konfigurieren, testen und rotieren unter Integrations → Webhooks im Dashboard.