Mit Zoi ID entwickeln
Zwei APIs auf einem Host, typisierte Clients in sechs Sprachen, ein gehosteter Ablauf und eine Sandbox. Der vollständige Leitfaden ist frei lesbar, Sandbox-Schlüssel gibt es mit dem Frühzugang.
Basis-URLhttps://kyc.zoi.network
Schnellstart
- 1
Sitzung erstellen
Ihr Backend ruft
POST /v1/partner/sessionsmit Ihrem Partnerschlüssel auf. - 2
Ablauf ausführen
Geben Sie das Client-Token an das SDK oder öffnen Sie
verificationUrlin einem Browser. - 3
Ergebnis empfangen
Prüfen Sie die Webhook-Signatur und speichern Sie dann die Identitäts-ID und ihren Status.
curl https://kyc.zoi.network/v1/partner/sessions \
-H "Authorization: Bearer $ZOI_ID_PARTNER_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: signup-user_42" \
-d '{ "externalUserId": "user_42", "level": "standard", "appId": "com.example.app" }'Zwei APIs
Partner-API
Server zu Server, unter /v1/partner. Senden Sie Ihren Partnerschlüssel als Bearer-Token. Legen Sie ihn nie in eine App.
Client-API
Wird vom SDK genutzt, unter /v1/client. Es sendet ein Client-Token, das für eine Sitzung 60 Minuten gilt.
Konventionen
- Zeiten sind Epoch-Millisekunden, in Feldern, deren Name auf
Atendet. - Daten haben das Format
YYYY-MM-DD. Unbekannte Teile sindXX, zum Beispiel1990-XX-XX. - POST-Anfragen, die etwas anlegen oder entscheiden, akzeptieren einen
Idempotency-Key-Header. Schlüssel werden 24 Stunden gespeichert. - Änderungen an einer Sitzung senden die erwartete Revision. Hat sie sich geändert, bekommen Sie
revision_conflict.
Sitzungsablauf
Ihr Backend erstellt die Sitzung. Das SDK führt die Schritte aus. Der Server prüft die Reihenfolge und antwortet mit step_not_allowed, wenn ein Schritt zu früh kommt.
1. Sitzung im Backend erstellen
Ein erneuter Aufruf für denselben Nutzer setzt die offene Sitzung fort und gibt ein neues Client-Token.
POST /v1/partner/sessions
Authorization: Bearer <partner key>
Content-Type: application/json
Idempotency-Key: 6f1c2a9e-signup-42
{
"externalUserId": "user_42",
"level": "standard",
"locale": "en",
"appId": "com.example.app"
}
200 OK
{
"sessionId": "ses_...",
"clientToken": "...",
"clientTokenExpiresAt": 1767225600000,
"status": "created",
"apiBaseUrl": "https://kyc.zoi.network",
"resumed": false
}2. Schritte, die das SDK ausführt
- 01
Sitzung und die noch nötigen Schritte lesen.
GET /v1/client/session
- 02
Einwilligung speichern, mit der eigenen, freiwilligen Wahl zum Gesichtsvergleich.
POST /v1/client/consent
- 03
App und Gerät prüfen. Das Ergebnis fließt in die Entscheidung ein.
POST /v1/client/attestation/challenge, POST /v1/client/attestation
- 04
Dokument senden: Chip nach einem MRZ-Scan lesen oder Fotos senden.
POST /v1/client/document/mrz-scan, POST /v1/client/document/chip/challenge, POST /v1/client/document/chip or POST /v1/client/document/photos
- 05
Ein kurzes Video mit der Frontkamera aufnehmen, während die App die Kopfbewegungen zeigt.
POST /v1/client/liveness/challenge, POST /v1/client/liveness
- 06
Wohnsitzland senden, auf der erweiterten Stufe auch die Adresse.
POST /v1/client/profile
- 07
Nur mit der Anforderung Adresse: ein Dokument hochladen, dann die Adresse bestätigen. Entfällt, wenn das Ausweisdokument sie schon geliefert hat.
POST /v1/client/address/document, POST /v1/client/address/confirm
- 08
Nur mit einer Anforderung zur Mittelherkunft: Antworten speichern, Dokumente hinzufügen, wenn die Policy sie verlangt, dann den Schritt abschließen.
POST /v1/client/funds/answers, POST /v1/client/funds/document, POST /v1/client/funds/remove, POST /v1/client/funds/complete
- 09
Zwei Fragen beantworten: politisch exponierte Person und Handeln im eigenen Namen.
POST /v1/client/declarations
- 10
Mit der aktuellen Revision absenden.
POST /v1/client/submit
Der Nutzer kann auch eine menschliche Prüfung eines automatischen Ergebnisses verlangen (POST /review-request) oder die Einwilligung widerrufen; das bricht die Sitzung ab und löscht ihre Dateien sofort (POST /withdraw).
Adressnachweis und Mittelherkunft
Fügen Sie requirements zu POST /v1/partner/sessions hinzu, um mehr als die Identität zu prüfen. address fordert einen Adressnachweis an. source_of_funds fragt, woher das Geld stammt, und source_of_wealth fragt zusätzlich nach dem Gesamtvermögen und wie es entstanden ist. Beide Werte zur Herkunft bilden zusammen einen Schritt, und beide lassen sich mit address kombinieren.
POST /v1/partner/sessions
Authorization: Bearer <partner key>
Content-Type: application/json
{
"externalUserId": "user_42",
"level": "standard",
"appId": "com.example.app",
"requirements": ["address", "source_of_funds"],
// Optional. Without them your partner default applies, else ours.
"addressPolicy": { "maxAgeDays": 90, "signedOnly": false },
"fundsPolicy": { "evidence": "optional", "currency": "EUR" }
}Optionale Policies
Ohne Policy gilt Ihr Partner-Standard, sonst unserer. Die Policy wird beim Erstellen in die Sitzung kopiert.
addressPolicy:maxAgeDays(Standard 90, 1 bis 366),acceptedTypes(Standard: Versorger-, Telekom- und Bankdokumente, Steuerdokumente, Behördenschreiben und Wohnsitzbescheinigungen) undsignedOnly(Standard false).fundsPolicy:questions,evidence(none,optionaloderrequired, Standardnone),acceptedTypes,maxAgeDays(Standard 180),currency(ISO 4217, Standard USD) undbracketsfür die Spannen.- Eine offene, noch nicht abgesendete Sitzung mit anderen Anforderungen wird abgebrochen, und eine neue startet, wie bei einem Stufenwechsel.
- Testen Sie jedes Ergebnis mit Sandbox-Szenarien wie
address_signed_pdf,address_document_review,funds_signed_documentsundfunds_review.
Folgesitzungen
Prüfen Sie nur die Anforderungen für einen Nutzer, dessen Identität bei Ihnen bereits aktiv ist. Senden Sie reuseIdentity: true zusammen mit requirements.
- Der Nutzer willigt ein und erledigt nur die neuen Schritte. Dokument, Selfie und Erklärungen werden nicht erneut abgefragt.
- Bei Genehmigung behält die Identität ihre ID, ihr Verifizierungsdatum und ihre Gültigkeit und erhält das neue Ergebnis. Sie bekommen
session.approvedundidentity.updated. - Ohne aktive Identität antwortet der Aufruf mit 409
step_not_allowed. - Starten Sie sie aus Ihren eigenen Risikoregeln heraus, etwa bei einer hohen Einzahlung, einem PEP-Treffer oder einem Risikoland. Ihre Regeln bleiben in Ihrem Backend, an einem Ort.
POST /v1/partner/sessions
Authorization: Bearer <partner key>
Content-Type: application/json
Idempotency-Key: edd-user_42-2026-11
{
"externalUserId": "user_42",
"appId": "com.example.app",
"requirements": ["source_of_funds", "source_of_wealth"],
"reuseIdentity": true,
"fundsPolicy": { "evidence": "required" }
}
// No active identity for user_42:
409 { "error": { "code": "step_not_allowed", ... } }Ergebnisse und Scopes
Genehmigte Sitzungen enthalten address und funds, und die Identität behält jeweils das neueste Ergebnis. Die Zusammenfassungsfelder kommen mit jedem Scope. Für die Details braucht es einen Scope.
- Scope
address: die Adresszeilen. Ohne ihn erhalten Sieverified,method,evidenceLevel,documentType,documentDate,verifiedAtundcountry. - Scope
financial_data:answers,documentsundfindings. Ohne ihn erhalten Siekinds,evidenceLevel,reviewed,documentCountundverifiedAt. Er ist nie Teil voneligibility. evidenceLevelisthigh,medium,lowodernone. Adressmethoden, die stärkste zuerst:wallet,id_document,signed_pdf,official_code,document_reviewunddeclared.- Dokumente werden nicht über die API gesendet. Mitglieder mit der Compliance-Rolle können Dokumentseiten zur Mittelherkunft im Dashboard ansehen, wenn die Umgebung den Scope
financial_datahat. Jede Ansicht wird protokolliert.
"session": {
"id": "ses_...",
"status": "approved",
"requirements": ["address", "source_of_funds"],
"reusesIdentity": false,
"address": {
"verified": true,
"method": "signed_pdf",
"evidenceLevel": "high",
"documentType": "bank_statement",
"documentDate": "2026-10-14",
"verifiedAt": 1767225600000,
"country": "DE",
// scope "address"
"address": { "line1": "Musterstrasse 12", "city": "Berlin", "postalCode": "10115", "country": "DE" }
},
"funds": {
"kinds": ["source_of_funds"],
"evidenceLevel": "medium",
"reviewed": true,
"documentCount": 2,
"verifiedAt": 1767225600000,
// scope "financial_data"
"answers": {
"employmentStatus": "employed",
"income": { "min": 50000, "max": 100000, "currency": "EUR" },
"sources": ["salary", "savings"],
...
},
"documents": [
{ "documentType": "payslip", "documentDate": "2026-10-31", "amount": 5200, "currency": "EUR",
"signature": "valid", "signedByKnownIssuer": true, "nameMatch": "match", "findings": [], ... },
...
],
"findings": []
}
}Web-Ablauf
Kein SDK? Schicken Sie den Nutzer auf unsere gehostete Seite. Sie nutzt dieselbe API, dieselben Prüfungen und dieselbe Prüfwarteschlange.
1. Den Link holen
POST /v1/partner/sessions gibt verificationUrl zurück. Geben Sie redirectUrl mit, um den Nutzer am Ende zurückzuschicken. Die URL muss mit einem Ihrer registrierten Redirect-Origins beginnen.
POST /v1/partner/sessions
Authorization: Bearer <partner key>
Content-Type: application/json
{
"externalUserId": "user_42",
"level": "standard",
"locale": "en",
"appId": "com.example.app",
"redirectUrl": "https://example.com/kyc/done"
}
200 OK
{
"sessionId": "ses_...",
"clientToken": "...",
"verificationUrl": "https://kyc.zoi.network/verify/#token=...&lang=en",
...
}- Das Client-Token steht im Fragment der URL, nach
#. Browser senden das Fragment nie an einen Server, daher steht das Token nicht in Logs oder imReferer-Header. Die Seite liest es, entfernt es aus der Adressleiste und hält es nur im Speicher. - Fügen Sie
langzum Fragment hinzu, um eine der 19 Sprachen zu wählen. Ohne den Wert nutzt die Seite die Sprache des Browsers. - Beim Neuladen geht das Token verloren. Erstellen Sie in Ihrem Backend einen neuen Link für dieselbe Sitzung.
- Die Seite sendet
channel: "web"mit der Einwilligung. Browser können keine Ausweischips lesen, daher nutzen Web-Sitzungen Dokumentfotos oder eine digitale Ausweis-Wallet. Sie überspringen die Geräteprüfung, und über Dokumentfotos aus dem Web entscheidet immer ein geschulter Prüfer. - Auf einem Computer zeigt die Seite einen QR-Code, damit der Nutzer auf dem Handy weitermachen kann.
2. Wenn der Nutzer fertig ist
Wenn der Ablauf endet (gesendet, abgebrochen oder ein Endstatus), sendet die Seite diese Nachricht an jedes dieser Objekte, das existiert: window.ReactNativeWebView, window.webkit.messageHandlers.zoiId, window.ZoiIdAndroid und window.opener. Danach öffnet sie redirectUrl mit den Parametern zoiIdSession und zoiIdStatus.
Vertrauen Sie nie der Nachricht oder den Redirect-Parametern. Vertrauen Sie nur Ihrem Webhook oder GET /v1/partner/sessions/:id.
// Sent to each bridge that exists:
// window.ReactNativeWebView.postMessage(JSON string)
// window.webkit.messageHandlers.zoiId.postMessage(object)
// window.ZoiIdAndroid.postMessage(JSON string)
// window.opener.postMessage(object, "<origin of your redirectUrl>")
// (popups only, and only when the session has a redirectUrl)
{
"source": "zoi-id",
"type": "finished", // or "cancelled"
"sessionId": "ses_...",
"status": "processing" // the session status at that moment
}
// Then, if redirectUrl was set (the page uses the one stored with the
// session, never one from the address bar):
https://example.com/kyc/done?zoiIdSession=ses_...&zoiIdStatus=processing3. Webview-Einstellungen
Android WebView
Schalten Sie javaScriptEnabled und domStorageEnabled ein und setzen Sie mediaPlaybackRequiresUserGesture auf false. Erlauben Sie in einem WebChromeClient bei onPermissionRequest die Ressource RESOURCE_VIDEO_CAPTURE, nachdem Ihre App die CAMERA-Berechtigung hat. Fügen Sie eine Dateiauswahl für den Foto-Ersatzweg hinzu.
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.settings.mediaPlaybackRequiresUserGesture = false
webView.webChromeClient = object : WebChromeClient() {
override fun onPermissionRequest(request: PermissionRequest) {
// Only after your app holds Manifest.permission.CAMERA.
if (request.resources.contains(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(arrayOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE))
} else {
request.deny()
}
}
override fun onShowFileChooser(
view: WebView, callback: ValueCallback<Array<Uri>>, params: FileChooserParams,
): Boolean {
// Open a picker and pass the result to callback (photo fallback).
return true
}
}iOS WKWebView
iOS 14.3 oder neuer. Setzen Sie allowsInlineMediaPlayback auf true und tragen Sie NSCameraUsageDescription in Ihrer App ein. Ab iOS 15 können Sie die Kamera-Berechtigung im UI-Delegate entscheiden.
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: config)
webView.uiDelegate = self // iOS 15+: decide camera access below
func webView(_ webView: WKWebView,
requestMediaCapturePermissionFor origin: WKSecurityOrigin,
initiatedByFrame frame: WKFrameInfo,
type: WKMediaCaptureType,
decisionHandler: @escaping (WKPermissionDecision) -> Void) {
decisionHandler(origin.host == "kyc.zoi.network" ? .grant : .deny)
}
// Info.plist: NSCameraUsageDescriptionReact Native WebView
Setzen Sie mediaCapturePermissionGrantType="grant", allowsInlineMediaPlayback und javaScriptEnabled. Ihre App braucht die Kamera-Berechtigung.
<WebView
source={{ uri: verificationUrl }}
javaScriptEnabled
allowsInlineMediaPlayback
mediaCapturePermissionGrantType="grant"
onMessage={(event) => {
const message = JSON.parse(event.nativeEvent.data);
if (message.source === "zoi-id") {
// Close the webview, then ask your backend for the real status.
}
}}
/>iframes werden nicht unterstützt, wegen der Kamera-Berechtigungen und wegen Clickjacking. Nutzen Sie einen Browser-Tab, ein Popup oder eine Webview.
Status
Sitzung
created- Die Sitzung existiert, noch nichts hochgeladen.
in_progress- Einwilligung gegeben, Schritte werden hochgeladen.
processing- Abgesendet, Prüfungen laufen.
review- Wartet auf eine geschulte Prüferin oder einen Prüfer.
approved- Endgültig. Die Identität ist verifiziert.
rejected- Endgültig. Siehe die Grundcodes.
resubmit- Der Nutzer muss die Schritte in requiredSteps wiederholen.
expired- Keine endgültige Entscheidung rechtzeitig.
cancelled- Abgebrochen durch den Partner, den Nutzer oder eine Löschung.
Identität
active- Nutzbar.
suspended- Gesperrt, zum Beispiel nach einem neuen Sanktionstreffer.
expired- Das Dokument oder der Prüfzeitraum ist abgelaufen. Eine neue Sitzung prüft erneut.
revoked- Endgültig.
SDK
Das React Native (Expo) SDK bietet Ihnen einen typisierten API-Client, NFC-Chiplesen und Geräteprüfungen. Es ist headless, Ihre App behält also die volle Kontrolle über ihre Bildschirme und ihre Kamera. Für Ihre Server nutzen Sie die typisierten Clients für TypeScript, Python, Go, PHP, Java und Ruby.
import { ZoiIdClient, nextStep } from "@zoi/id-sdk";
// clientToken and apiBaseUrl come from your backend (POST /v1/partner/sessions).
const client = new ZoiIdClient({ baseUrl: apiBaseUrl, clientToken });
const session = await client.getSession();
switch (nextStep(session)) {
case "consent": /* show the notice and the biometric choice */ break;
case "document": /* chip read or photos */ break;
case "liveness": /* record the video */ break;
case "address": /* upload a document, then confirm the address */ break;
case "funds": /* answers, then documents when the policy asks */ break;
case "submit": await client.submit(session.revision); break;
case "done": /* wait for your backend to get the webhook */ break;
}Webhooks
Wir senden einen Webhook, wenn sich eine Sitzung oder Identität ändert. Prüfen Sie immer die Signatur, bevor Sie dem Inhalt trauen.
- Jeder Webhook hat einen
Zoi-Id-Signature-Header:t=unix seconds,v1=hex. v1ist der HMAC-SHA256 des Textest.raw bodymit Ihrem Webhook-Secret. Nutzen Sie den rohen Body, vor jedem JSON-Parsing.- Während ein Secret gewechselt wird, enthält der Header ein
v1pro aktivem Secret. Akzeptieren Sie den Webhook, wenn eines davon passt. - Lehnen Sie ihn ab, wenn
tmehr als 300 Sekunden von jetzt abweicht. - Fehlgeschlagene Zustellungen werden 72 Stunden lang wiederholt. Jeder Versuch wird mit einem neuen
tneu signiert. - Identitäten haben eine
revision. Wenden Sie ein Event nur an, wenn seine Revision neuer ist als die gespeicherte.
POST <your webhook URL>
Zoi-Id-Signature: t=1767225600,v1=5f2b...e9
{
"v": 1,
"eventId": "evt_...",
"type": "identity.suspended",
"createdAt": 1767225600000,
"object": "identity",
"externalUserId": "user_42",
"identity": {
"identityId": "idn_...",
"revision": 7,
"status": "suspended",
"level": "standard",
"verifiedAt": 1764547200000,
"validUntil": 1859155200000,
"ageOver18": true,
"captureMethod": "nfc"
}
}Event-Typen
session.processingsession.reviewsession.approvedsession.rejectedsession.resubmitsession.expiredsession.cancelledidentity.updatedidentity.suspendedidentity.reinstatedidentity.expiredidentity.revoked
Signatur in TypeScript prüfen
import { createHmac, timingSafeEqual } from "node:crypto";
const TOLERANCE_SECONDS = 300;
export function verifyZoiIdSignature(
rawBody: string,
header: string | null,
secret: string,
nowSeconds = Math.floor(Date.now() / 1000),
): boolean {
if (!header) return false;
let t: string | undefined;
const signatures: Buffer[] = [];
for (const part of header.split(",")) {
const [key, value] = part.trim().split("=");
if (!value) continue;
if (key === "t") t = value;
if (key === "v1" && /^[0-9a-f]+$/i.test(value)) signatures.push(Buffer.from(value, "hex"));
}
if (!t || !/^\d+$/.test(t) || signatures.length === 0) return false;
if (Math.abs(nowSeconds - Number(t)) > TOLERANCE_SECONDS) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
return signatures.some((sig) => sig.length === expected.length && timingSafeEqual(sig, expected));
}
// Example handler: read the raw body first, parse JSON only after the check.
export async function POST(request: Request) {
const rawBody = await request.text();
const ok = verifyZoiIdSignature(rawBody, request.headers.get("Zoi-Id-Signature"), process.env.ZOI_ID_WEBHOOK_SECRET!);
if (!ok) return new Response("bad signature", { status: 400 });
const event = JSON.parse(rawBody);
// Store event.eventId to skip duplicates, then apply it if the revision is newer.
return new Response(null, { status: 204 });
}Signatur in Go prüfen
package zoiid
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"strconv"
"strings"
"time"
)
const toleranceSeconds = 300
// VerifySignature checks the Zoi-Id-Signature header against the raw body.
func VerifySignature(rawBody []byte, header, secret string, now time.Time) bool {
var t string
var sigs [][]byte
for _, part := range strings.Split(header, ",") {
key, value, ok := strings.Cut(strings.TrimSpace(part), "=")
if !ok || value == "" {
continue
}
switch key {
case "t":
t = value
case "v1":
if b, err := hex.DecodeString(value); err == nil {
sigs = append(sigs, b)
}
}
}
ts, err := strconv.ParseInt(t, 10, 64)
if err != nil || len(sigs) == 0 {
return false
}
if d := now.Unix() - ts; d > toleranceSeconds || d < -toleranceSeconds {
return false
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(t + "."))
mac.Write(rawBody)
expected := mac.Sum(nil)
for _, sig := range sigs {
if hmac.Equal(sig, expected) {
return true
}
}
return false
}Event-Feed
GET /v1/partner/events liefert alle Events der letzten 30 Tage, das älteste zuerst. Geben Sie after mit dem letzten nextCursor an, um die nächste Seite zu lesen. Nutzen Sie es nach einem längeren Ausfall oder um zu prüfen, dass Ihnen nichts fehlt.
GET /v1/partner/events?after=<nextCursor>&limit=100
Authorization: Bearer <partner key>
200 OK
{
"items": [ /* webhook payloads, oldest first */ ],
"nextCursor": "..." // null when there is nothing more
}Betrugsmeldungen
Sagen Sie uns, wenn sich eine entschiedene Sitzung als Betrug herausstellt, zum Beispiel nach einer Rückbuchung. Meldungen fließen in unsere Messung falscher Genehmigungen ein. Sie ändern weder die Sitzung noch die Identität noch das Ergebnis des Nutzers.
- Scope
sessions:write. Nur für entschiedene Sitzungen (genehmigt oder abgelehnt). Vor einer Entscheidung antwortet der Aufruf mit 409. - Ein leerer Body meldet
confirmed_fraudmit der Kategorieother.statuskann auchsuspected_fraudsein, odercleared, um Ihre eigene Meldung zurückzunehmen. - Kategorien:
forged_document,impostor,deepfake_or_replay,synthetic_identity,account_takeoverundother. Keine Kategorie beicleared. noteist Freitext für unsere Analysten, höchstens 1000 Zeichen. Tragen Sie dort nie Namen, Dokumentnummern oder andere personenbezogene Daten ein.- Eine neue Meldung antwortet mit 201. Dieselbe Meldung erneut liefert die gespeicherte mit 200. Senden Sie einen
Idempotency-Key, um gefahrlos zu wiederholen. Höchstens 20 Meldungen pro Sitzung. - Dieselbe Meldung ist auf der Sitzungsseite im Dashboard nur einen Klick entfernt.
POST /v1/partner/sessions/ses_.../fraud-reports
Authorization: Bearer <partner key>
Content-Type: application/json
Idempotency-Key: chargeback-8812
{
"status": "confirmed_fraud",
"category": "impostor",
"note": "Chargeback on the first deposit"
}
201 Created
{
"id": "flb_...",
"sessionId": "ses_...",
"status": "confirmed_fraud",
"category": "impostor",
"noteKept": true,
"createdAt": 1767225600000
}Löschung
DELETE /v1/partner/users/:externalUserId löscht die Daten eines Nutzers, wenn er sein Konto schließt oder die Löschung verlangt. Die Antwort zeigt, was jetzt gelöscht wurde und was behalten wird, warum und bis wann.
DELETE /v1/partner/users/user_42
Authorization: Bearer <partner key>
200 OK
{
"deleted": ["images", "chip_files", "video", "personal_data", "address"],
"retained": [
{ "category": "dedup_keys", "reason": "fraud_prevention", "until": 1924992000000 },
{ "category": "sanctions_screening_records", "reason": "legal_obligation", "until": 2082758400000 }
],
"backupsPurgedWithinDays": 30
}Fehler
Jeder Fehler hat dieselbe Form und pro Code einen festen HTTP-Status.
{
"error": {
"code": "step_not_allowed",
"message": "This step is not allowed now.",
"requestId": "req_..."
}
}| Code | HTTP | Bedeutung |
|---|---|---|
bad_request | 400 | Die Anfrage passt nicht zum Vertrag. |
unauthorized | 401 | Schlüssel oder Token fehlt oder ist falsch. |
token_expired | 401 | Das Client-Token ist abgelaufen. Erstellen Sie im Backend ein neues. |
forbidden | 403 | Der Schlüssel darf das nicht. |
not_found | 404 | Keine solche Sitzung oder kein solcher Nutzer. |
session_closed | 409 | Die Sitzung ist abgeschlossen. Keine weiteren Uploads. |
step_not_allowed | 409 | Falsche Reihenfolge, oder der Schritt wird gerade nicht gebraucht. |
revision_conflict | 409 | Die Sitzungsrevision hat sich geändert. Lesen Sie sie neu. |
idempotency_conflict | 409 | Derselbe Idempotency-Key wurde mit einer anderen Anfrage genutzt. |
challenge_expired | 410 | Die Challenge ist abgelaufen oder schon benutzt. Fordern Sie eine neue an. |
payload_too_large | 413 | Der Upload ist zu groß. |
unsupported_media_type | 415 | Der Dateityp wird nicht angenommen. |
rate_limited | 429 | Zu viele Anfragen. Versuchen Sie es später erneut. |
internal | 500 | Bei uns ist etwas schiefgelaufen. |
dependency_unavailable | 503 | Ein Dienst, den wir brauchen, ist nicht erreichbar. Versuchen Sie es später erneut. |
Grundcodes
Sitzungen enthalten reasonCodes, wenn sie erneut eingereicht werden müssen oder abgelehnt sind. Zeigen Sie für jeden Code Ihre eigene übersetzte Meldung. Zeigen Sie Nutzern nie den rohen Code.
consent_missingconsent_withdrawnattestation_faileddocument_expireddocument_unreadabledocument_not_supporteddocument_suspected_tamperingdocument_number_visiblechip_verification_failedchip_proof_missingchip_data_mismatchmrz_invalidphoto_qualityface_not_foundface_mismatchliveness_failedunderagelocation_not_supportedresidence_not_supportedsanctions_matchpep_reviewduplicate_identitypossible_duplicatedeclaration_requires_reviewuser_requested_reviewreviewer_otheraddress_unreadableaddress_document_too_oldaddress_document_not_acceptedaddress_name_mismatchaddress_signature_requiredfunds_document_unreadablefunds_document_too_oldfunds_document_not_acceptedfunds_more_evidencefunds_evidence_rejected