API für Live-Verifizierung

Planen Sie eine Live-ID-Verifizierungssitzung für Ihren Kunden aus Ihrem eigenen System, verfolgen, sagen Sie sie ab oder verschieben Sie sie und erhalten Sie die Entscheidung des Moderators per Webhook — alles über Ihren eigenen Referenzcode.

Eine Live-ID-Verifizierung ist eine von einer Person moderierte Live-Videositzung: Eines Ihrer Teammitglieder (der Moderator) trifft den Antragsteller vor der Kamera, prüft dessen Ausweis live und hält eine Entscheidung fest. Bisher konnten diese Sitzungen nur über das Dashboard geplant werden. Die folgenden Endpunkte ermöglichen es Ihrem System, eine Sitzung für einen Ihrer Kunden zu planen, sie zu verfolgen und das Ergebnis zurückzuerhalten — per API und per Webhook — zugeordnet über Ihren eigenen Referenzcode (externalRef).

Jeder Endpunkt liegt unter /api/v1/kyc/conferences und wird mit einem API-Schlüssel authentifiziert (Authorization: Bearer ck_live_…). Siehe Authentifizierung.

Die Live-ID-Verifizierung (diese Seite — eine Live-Videositzung mit einem menschlichen Moderator) ist eine andere Funktion als die Live-ID-Validierung (biometrische Anmeldung für einen wiederkehrenden Nutzer, siehe Live ID Validation).

So funktioniert es

sequenceDiagram
  participant You as Your system
  participant C as Certivant
  participant A as Applicant
  participant H as Host (your team)
  You->>C: POST /conferences (externalRef, host, scheduledFor)
  C-->>You: 201 conference + applicantJoinUrl
  C->>A: Invitation email / SMS (join link)
  C-->>You: webhook conference.scheduled
  H->>C: Joins from the dashboard
  C-->>You: webhook conference.started
  A->>C: Consents + joins the session
  H->>C: Records the decision
  C-->>You: webhook conference.completed (decision, externalRef)
  1. Sie planen die Sitzung für eine bestehende Verifizierungsanfrage oder legen den Antragsteller direkt mit an. Sie benennen den Moderator — ein Mitglied Ihrer Organisation, das die Sitzung über das Dashboard durchführt.
  2. Certivant lädt den Antragsteller ein (per E-Mail und/oder SMS, in seiner Sprache) und gibt Ihnen ebenfalls den Beitrittslink zurück.
  3. Bevor er die Sitzung betritt, beantwortet der Antragsteller das Einwilligungsfenster. Die Einwilligung zur Videoaufzeichnung wird immer eingeholt; der restliche Teil des Fensters kann mit consentScreen: false übersprungen werden, wenn Sie diese Einwilligungen bereits in Ihrer eigenen App eingeholt haben.
  4. Sobald der Moderator die Entscheidung festhält, erhalten Sie conference.completed mit der Entscheidung, ihrer Wirkung auf die Verifizierung und Ihrem externalRef.

Bevor Sie beginnen

VoraussetzungWo
API-Schlüssel mit kyc:write (planen / ändern) und kyc:read (lesen)KYC → Entwickler
Ihr Tarif umfasst Web-KonferenzenIhr Abonnement. Andernfalls 402
Live-ID-Verifizierung in Ihren Einstellungen aktiviertKYC → Einstellungen → Live-ID-Verifizierung. Andernfalls 403
Ihr Konto ist von Certivant verifiziertOnboarding. Andernfalls 403
Der Moderator hat die Berechtigung zur manuellen GenehmigungDer Inhaber oder eine Rolle / ein Nutzer, der in Ihren Einstellungen zur manuellen Genehmigung aufgeführt ist. Andernfalls 403
Eine Webhook-URL (optional, für Ergebnisse)KYC → Einstellungen → Webhooks — siehe Webhooks → Einrichtung

Alle Zeitpunkte sind ISO-8601 mit Zeitzone — 2026-10-06T14:00:00Z oder 2026-10-06T10:00:00-04:00. Ein Zeitpunkt ohne Zeitzone wird abgelehnt, sodass eine Sitzung nie wegen der lokalen Zeitzone eines Servers zur falschen Uhrzeit stattfinden kann. Antworten sind immer in UTC (…Z).


Eine Live-Verifizierung planen

POST /api/v1/kyc/conferences    Berechtigungsbereich: kyc:write

Anfrage-Body

{
  "kycRequestId": "req_01J…",
  "host": { "email": "compliance@yourcompany.com" },
  "externalRef": "order-10042",
  "title": "Account opening — video check",
  "scheduledFor": "2026-10-06T10:00:00-04:00",
  "language": "fr",
  "consentScreen": true,
  "applicantFileUploadEnabled": false,
  "channels": { "email": true, "sms": true }
}
FeldTypPflichtfeldHinweise
kycRequestIdstringeines davonEine bestehende Verifizierungsanfrage in Ihrer Organisation.
applicantobjecteines davonStattdessen Antragsteller und Verifizierung direkt anlegen (siehe unten). Ein Antragsteller mit derselben E-Mail-Adresse in Ihrer Organisation wird wiederverwendet.
host.userId / host.emailstringja (eines davon)Das Mitglied, das die Sitzung durchführt. Muss die Berechtigung zur manuellen Genehmigung besitzen.
externalRefstringneinIhr Referenzcode (Bestell- oder Vorgangsnummer). Wird bei jeder Antwort und jedem Webhook zurückgegeben. Maximal 200.
titlestringneinWird dem Moderator angezeigt. Maximal 200.
scheduledForISO-Zeitpunkteines davonWann die Sitzung stattfindet. Muss in der Zukunft liegen.
startNowbooleaneines davontrue = sofort planen (der Antragsteller wird sofort eingeladen).
expiresAtISO-ZeitpunktneinEnde des Beitrittsfensters. Standard: scheduledFor + 24 h.
languageAufzählungneinen, fr, es, de, it, pt, nl, pl, ro, tr, ar, zh, ja, ko, hi, vi, id, ru, uk, sv. Sprache der Einladung; sie wird als bevorzugte Sprache des Antragstellers gespeichert (Texte ohne Übersetzung in dieser Sprache werden auf Englisch gesendet). Standard: die gespeicherte Sprache des Antragstellers, sonst die Standardsprache Ihrer Organisation.
consentScreenbooleanneinStandard true — der Antragsteller bestätigt die Weitergabe persönlicher Daten, die Fotoaufnahme und die Videoaufzeichnung. false = das Fenster fragt nur nach der Einwilligung zur Videoaufzeichnung, die niemals deaktiviert werden kann.
faceCheckSkippablebooleanneinWeggelassen: die Einstellung des Formulars der Anfrage, sonst die Ihrer Organisation (die Gesichtsprüfung ist erforderlich, sofern Sie das nicht geändert haben). false erzwingt, dass die Gesichtsprüfung im Einwilligungsfenster erforderlich ist. true bietet die nicht biometrische Alternative an, nur dort, wo das Gesetz sie verlangt (z. B. Québec): Der Antragsteller kann die Gesichtsprüfung ablehnen, es laufen weder Selfie noch Liveness-Prüfung, und der Host vergleicht im Anruf das Gesicht visuell mit dem Ausweis. Das Fenster enthält die Gesichtsprüfung nicht, wenn consentScreen den Wert false hat.
applicantFileUploadEnabledbooleanneinStandard false — während der Sitzung kann der Antragsteller nur mit seiner Kamera Fotos aufnehmen. true erlaubt außerdem das Senden von Dateien von seinem Gerät. Der Moderator kann dies während der Sitzung ändern.
channels.email / channels.smsbooleanneinWie die Einladung zugestellt wird. Standard: E-Mail; SMS an die Telefonnummer eines neu angelegten Antragstellers. Bei einem bestehenden Antragsteller wird seine hinterlegte Telefonnummer nur bei sms: true per SMS angeschrieben. Beide false = nichts wird gesendet — übergeben Sie applicantJoinUrl selbst.

Antragsteller inline anlegen (statt kycRequestId):

{
  "applicant": {
    "fullName": "Jane Doe",
    "email": "jane@example.com",
    "phone": "+14155551234",
    "emailVerified": false,
    "phoneVerified": false,
    "externalRef": "customer-881"
  },
  "host": { "userId": "usr_01H…" },
  "externalRef": "order-10042",
  "startNow": true
}

SMS-Einladungen werden wie Einladungen im Dashboard abgerechnet (zuerst das im Tarif enthaltene SMS-Kontingent, danach Ihr Guthaben). Reicht keines von beiden aus, wird die SMS übersprungen, und die E-Mail wird trotzdem versendet.

Beispiel

curl -X POST https://app.certivant.com/api/v1/kyc/conferences \
  -H "Authorization: Bearer $CERTIVANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kycRequestId": "req_01J...",
    "host": { "email": "compliance@yourcompany.com" },
    "externalRef": "order-10042",
    "scheduledFor": "2026-10-06T10:00:00-04:00",
    "language": "en"
  }'

Antwort 201

Das Konferenzobjekt plus:

{
  "id": "cmf…",
  "kycRequestId": "req_01J…",
  "externalRef": "order-10042",
  "status": "scheduled",
  "scheduledFor": "2026-10-06T14:00:00.000Z",
  "expiresAt": "2026-10-07T14:00:00.000Z",
  "applicantJoinUrl": "https://app.certivant.com/forms/conference/3f9c…",
  "invitation": { "email": true, "sms": false }
}

applicantJoinUrl wird nur hier und bei Einladung erneut senden zurückgegeben — Certivant speichert nur einen Hash des Links, daher lässt er sich später nicht mehr auslesen. applicantWasReused wird bei einem inline angelegten Antragsteller ergänzt. invitation zeigt die Kanäle, über die die Einladung versendet wurde.

Fehler

StatusWann
400Validierung fehlgeschlagen (error.issues), sowohl oder keines von kycRequestId und applicant, sowohl oder keines von scheduledFor und startNow, ein Zeitpunkt in der Vergangenheit, expiresAt nicht nach scheduledFor, oder der Moderator ist kein Mitglied Ihrer Organisation.
402Ihr Tarif umfasst keine Live-Verifizierung.
403Dem Schlüssel fehlt kyc:write; das Konto wartet auf die Verifizierung; die Live-Verifizierung ist in den Einstellungen deaktiviert; oder dem Moderator fehlt die Berechtigung zur manuellen Genehmigung.
404Die kycRequestId existiert nicht in Ihrer Organisation.
409Die Verifizierung hat bereits eine beitretbare Konferenz. Der Body enthält deren conferenceId — verschieben oder absagen Sie sie stattdessen. Ein wiederholter POST lädt den Kunden daher nie zweimal ein.

Eine Live-Verifizierung abrufen

GET /api/v1/kyc/conferences/:id    Berechtigungsbereich: kyc:read

Liefert das Konferenzobjekt. Eine ID, die zu einer anderen Organisation gehört, ergibt 404.

curl https://app.certivant.com/api/v1/kyc/conferences/cmf… \
  -H "Authorization: Bearer $CERTIVANT_API_KEY"

Mit Ihrem Referenzcode suchen

GET /api/v1/kyc/conferences/by-external-ref/:externalRef    Berechtigungsbereich: kyc:read

Die neueste Konferenz mit diesem externalRef (URL-kodieren Sie ihn). 404, wenn keine existiert.

curl https://app.certivant.com/api/v1/kyc/conferences/by-external-ref/order-10042 \
  -H "Authorization: Bearer $CERTIVANT_API_KEY"

Live-Verifizierungen auflisten

GET /api/v1/kyc/conferences    Berechtigungsbereich: kyc:read

AbfrageHinweise
statusscheduled, in_progress, completed, cancelled oder expired (eine noch geplante Sitzung, deren Beitrittsfenster ohne Durchführung geschlossen wurde — ein Nichterscheinen). scheduled schließt abgelaufene aus.
externalRefExakte Übereinstimmung mit Ihrem Referenzcode.
kycRequestIdKonferenzen einer Verifizierung.
scheduledFrom / scheduledToISO-Zeitpunkte, einschließlich, bezogen auf scheduledFor.
createdFrom / createdToISO-Zeitpunkte, einschließlich, bezogen auf den Erstellungszeitpunkt.
page / limitStandard 1 / 20, limit maximal 100.

Die neuesten zuerst, mit einer stabilen Zweitsortierung, damit die Seitennavigation nie Zeilen überspringt oder doppelt liefert.

curl "https://app.certivant.com/api/v1/kyc/conferences?status=completed&createdFrom=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer $CERTIVANT_API_KEY"
{
  "data": [ { "id": "cmf…", "status": "completed", "externalRef": "order-10042" } ],
  "pagination": { "page": 1, "limit": 20, "total": 1, "totalPages": 1 }
}

Verschieben

POST /api/v1/kyc/conferences/:id/reschedule    Berechtigungsbereich: kyc:write

{
  "scheduledFor": "2026-10-08T15:30:00+02:00",
  "expiresAt": "2026-10-09T15:30:00+02:00",
  "title": "Rescheduled video check",
  "externalRef": "order-10042"
}

Nur eine scheduled-Konferenz kann verschoben werden (409, sobald sie begonnen, abgeschlossen oder abgesagt wurde). Der neue Zeitpunkt muss in der Zukunft und vor dem Ende des Beitrittsfensters liegen — übergeben Sie ein späteres expiresAt, um das Fenster zu verlängern. title und externalRef sind optional: Weglassen behält den Wert, null löscht ihn. Die Antwort enthält das Konferenzobjekt sowie previousScheduledFor, und es wird conference.rescheduled ausgelöst.

Das Verschieben benachrichtigt den Antragsteller nicht — rufen Sie Einladung erneut senden auf, um ihm die neue Zeit zuzustellen.

Absagen

POST /api/v1/kyc/conferences/:id/cancel    Berechtigungsbereich: kyc:write

{ "reason": "Customer cancelled the order" }

Der Body ist optional. Sagt eine scheduled-Konferenz ab: Der Link des Antragstellers funktioniert nicht mehr, und conference.cancelled wird mit Ihrem reason ausgelöst. Eine Sitzung, die bereits in_progress ist, liefert 409 — der Moderator beendet sie innerhalb der Sitzung. Die Verifizierungsanfrage selbst bleibt unverändert.

Einladung erneut senden

POST /api/v1/kyc/conferences/:id/resend-invitation    Berechtigungsbereich: kyc:write

{ "channels": { "email": true, "sms": false }, "language": "es" }

Stellt einen neuen Beitrittslink aus (der bisherige funktioniert nicht mehr) und sendet die Einladung erneut über die channels — standardmäßig E-Mail, zusätzlich SMS, wenn eine Telefonnummer hinterlegt ist. Sind beide Kanäle false, wird nichts gesendet: Verwenden Sie stattdessen die zurückgegebene applicantJoinUrl selbst (copyOnly: true). Erlaubt, solange die Konferenz scheduled oder in_progress ist und ihr Beitrittsfenster offen ist, andernfalls 409.


Das Konferenzobjekt

{
  "id": "cmf…",
  "kycRequestId": "req_01J…",
  "applicantId": "cma…",
  "organizationId": "org_01H…",
  "externalRef": "order-10042",
  "title": "Account opening — video check",
  "status": "completed",
  "expired": false,
  "scheduledFor": "2026-10-06T14:00:00.000Z",
  "expiresAt": "2026-10-07T14:00:00.000Z",
  "startedAt": "2026-10-06T14:01:12.000Z",
  "endedAt": "2026-10-06T14:14:40.000Z",
  "durationSeconds": 808,
  "createdAt": "2026-10-01T09:00:00.000Z",
  "updatedAt": "2026-10-06T14:14:40.000Z",
  "host": { "userId": "usr_01H…", "name": "Sam Reviewer", "email": "compliance@yourcompany.com" },
  "applicant": {
    "id": "cma…",
    "fullName": "Jane Doe",
    "email": "jane@example.com",
    "externalRef": "customer-881",
    "joinedAt": "2026-10-06T14:02:03.000Z"
  },
  "additionalApplicants": [],
  "additionalKycRequestIds": [],
  "consent": {
    "screenEnabled": true,
    "requiredPurposes": ["share_information", "photo_capture", "video_recording"],
    "given": true,
    "at": "2026-10-06T14:01:58.000Z",
    "version": "2026-10-04"
  },
  "decision": {
    "decision": "verified",
    "outcome": "approved",
    "requestStatus": "APPROVED",
    "notes": "ID checked on camera, matches the applicant.",
    "decidedByUserId": "usr_01H…",
    "documentDecisions": { "verified": 2, "rejected": 0, "needsResubmission": 0 }
  },
  "recording": { "available": true, "deliveryStatus": "delivered", "durationSeconds": 790, "sha256": "9b1f…" },
  "certificate": null
}
FeldHinweise
statusscheduled → in_progress (der Moderator ist beigetreten) → completed (Entscheidung festgehalten oder Sitzung beendet), oder cancelled.
expiredtrue, wenn das Beitrittsfenster einer scheduled-Sitzung ohne Durchführung geschlossen wurde (Nichterscheinen). Filtern Sie mit status=expired.
consent.givenDie Antwort des Hauptantragstellers: null, bis er antwortet, false, wenn er abgelehnt hat (die Sitzung wird dann abgesagt). requiredPurposes enthält immer video_recording.
decision.decisionDas Urteil des Moderators: verified, rejected, needs_more_info oder inconclusive. null, bis entschieden wurde.
decision.outcomeWas es mit der Verifizierung macht: approved, rejected oder escalated (needs_more_info / inconclusive legen sie zur Prüfung zurück). requestStatus ist der Status der Verifizierung.
recording.availabletrue, sobald die Aufzeichnung zusammengestellt und in Ihrem Speicher abgelegt oder dorthin zugestellt wurde. Die Medien selbst stellt diese API nie bereit.
certificateDas Verifizierungszertifikat der Verifizierung, sofern eines ausgestellt wurde: id, certificateNumber, verificationUrl.

Webhooks

Live-Verifizierungen senden fünf Ereignisse an Ihre Webhook-URL (die formularspezifische Überschreibungs-URL, wenn die Verifizierung aus einem Formular mit einer solchen stammt, andernfalls die Standard-URL Ihrer Organisation). Sie werden für jede Konferenz ausgelöst — ob im Dashboard oder über die API geplant — und werden genau wie jeder andere Certivant-Webhook signiert und bei Fehlern wiederholt.

EreignisWird ausgelöst, wenn
conference.scheduledEine Konferenz wird angelegt (für später geplant oder sofort).
conference.rescheduledEine geplante Konferenz wird auf einen neuen Zeitpunkt verschoben. Enthält previousScheduledFor.
conference.cancelledEine Konferenz wird abgesagt — durch Ihren API-Aufruf oder weil der Antragsteller die Einwilligung verweigert hat. Enthält cancellation.
conference.startedDer Moderator startet die Sitzung (erster Beitritt). Einmal pro Start — erneute Verbindungen des Moderators wiederholen es nicht.
conference.completedDer Moderator hält die endgültige Entscheidung fest. Enthält decision.

Eine erneute Einladung ist kein neues conference.scheduled.

Es gibt noch kein Ereignis no_show. Eine Sitzung, die nie stattfindet, bleibt scheduled und wird mit expired: true gemeldet, sobald ihr Beitrittsfenster schließt — fragen Sie GET /conferences?status=expired ab, um Nichterscheinen zu finden.

Nutzlast

Anders als die Ereignisse kyc.request.* verwenden Konferenzereignisse einen auf Konferenzen zugeschnittenen Body. Jedes Ereignis enthält die IDs, Ihren externalRef, den Status und die Zeitstempel:

{
  "event": "conference.completed",
  "conferenceId": "cmf…",
  "kycRequestId": "req_01J…",
  "applicantId": "cma…",
  "organizationId": "org_01H…",
  "externalRef": "order-10042",
  "title": "Account opening — video check",
  "status": "completed",
  "scheduledFor": "2026-10-06T14:00:00.000Z",
  "expiresAt": "2026-10-07T14:00:00.000Z",
  "startedAt": "2026-10-06T14:01:12.000Z",
  "endedAt": null,
  "durationSeconds": null,
  "createdAt": "2026-10-01T09:00:00.000Z",
  "updatedAt": "2026-10-06T14:13:55.000Z",
  "host": { "userId": "usr_01H…", "name": "Sam Reviewer", "email": "compliance@yourcompany.com" },
  "consent": {
    "screenEnabled": true,
    "requiredPurposes": ["share_information", "photo_capture", "video_recording"],
    "given": true,
    "at": "2026-10-06T14:01:58.000Z"
  },
  "decision": {
    "decision": "rejected",
    "outcome": "rejected",
    "requestStatus": "REJECTED",
    "notes": "Face does not match the ID photo.",
    "decidedByUserId": "usr_01H…",
    "documentDecisions": { "verified": 0, "rejected": 1, "needsResubmission": 0 }
  },
  "recording": { "available": false, "deliveryStatus": "pending", "durationSeconds": null, "sha256": null },
  "certificate": null,
  "timestamp": "2026-10-06T14:13:55.000Z"
}

Ereignisspezifische Felder:

  • conference.rescheduled — previousScheduledFor.
  • conference.cancelled — cancellation.reason und cancellation.cancelledBy (api, host, applicant, system). Eine verweigerte Einwilligung kommt als cancelledBy: "applicant", reason: "applicant_refused_consent" an.
  • conference.completed — decision (wie im Konferenzobjekt). Die Sitzung kann noch laufen, wenn die Entscheidung festgehalten wird, daher kann endedAt null sein, und die Aufzeichnung wird meist noch zusammengestellt (recording.available: false) — lesen Sie später GET /conferences/:id für den endgültigen Stand der Aufzeichnung.

Nutzlasten enthalten niemals Medien, Links zu Aufzeichnungen oder Beitrittstoken.

Signatur prüfen

Jede Zustellung wird mit Ihrem Signaturgeheimnis des Webhooks signiert. Der empfohlene Header ist X-Certivant-Signature-V2: t=<unix>,v1=<hex>, wobei v1 der HMAC-SHA256 von `${t}.${rawBody}` ist. Lehnen Sie Zeitstempel ab, die mehr als 300 Sekunden abweichen, und entfernen Sie Duplikate anhand von X-Certivant-Event-Id. (Die älteren Header X-KYC-Signature / X-KYC-Timestamp / X-KYC-Event-Id werden weiterhin gesendet.)

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

export function verifyCertivantWebhook(rawBody: string, headers: Headers, secret: string) {
  const parts = (headers.get("X-Certivant-Signature-V2") ?? "").split(",").map((p) => p.split("="));
  const t = parts.find(([k]) => k === "t")?.[1] ?? "";
  if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return parts.some(
    ([k, v]) => k === "v1" && v?.length === expected.length && timingSafeEqual(Buffer.from(v), Buffer.from(expected)),
  );
}

// In your handler:
const event = JSON.parse(rawBody);
if (event.event === "conference.completed") {
  await orders.markIdentityChecked(event.externalRef, event.decision.outcome);
}

Vollständige Details und Beispiele in weiteren Sprachen: Signaturprüfung.


Ratenlimits

Diese Endpunkte teilen sich das API-Ratenlimit Ihrer Organisation mit der übrigen v1-API — siehe Ratenlimits.