Skip to main content
Didit Raises $7.5M to Build the Infrastructure for Identity and Fraud
Didit
Developers

The best way to integrate
identity and fraud.

Open the sandbox, paste one curl, and ship in 5 minutes. Public docs, five Software Development Kits (SDKs), and a Model Context Protocol (MCP) server so an Artificial Intelligence (AI) coding agent can integrate Didit for you. $0.33 per full KYC check, 500 free every month.

Backed by
Y CombinatorRobinhood Ventures
GBTC Finance
Bondex
Crnogorski Telekom
UCSF Neuroscape
Shiply
Adelantos

Trusted by 2,000+ organizations worldwide.

Quickstart

Zero to verified in five minutes.

Five steps from signup to first verified user. Each step pairs a Business Console path with a programmatic Application Programming Interface (API) path. Or skip every step, paste the integration prompt at docs.didit.me/integration/integration-prompt into your AI coding agent.
01 · Sign up

Create your Didit account.

  • In the Business Console: sign up at business.didit.me in under sixty seconds, no card, no sales gate.
  • By Application Programming Interface (API): call POST https://apx.didit.me/auth/v2/programmatic/register/, then POST .../verify-email/.

Either path leaves you with a sandbox API key, same shape as production, every module unlocked.

Programmatic Registration API
Production API key
Live
didit_sk_live_8f4c2a…9bf3

Issued just now, no card, no contract, no call.

  • No minimum
  • No contract
  • 500 free / mo
  • Open sandbox
02 · Build the workflow

Pick the modules. Compose the workflow.

  • In the Business Console: drag-and-drop the modules into the Workflow Builder, Identity Document Verification, Passive Liveness, Face Match, Anti-Money Laundering (AML), Wallet Screening, Internet Protocol (IP) Analysis, and 19 more.
  • By API: call POST /v3/workflows/ on verification.didit.me with the modules you want.

Either path returns a workflow_id you will pass on every session.

Create Workflow API
Workflowkyc-onboarding-v3
220+ countries
  • ID Verification
  • Passive Liveness
  • Face Match 1:1
  • AML Screening
  • Device & IP Analysis
  • Proof of Address
  • NFC Reading
  • Phone Verification
  • Wallet Screening
  • Custom Questionnaire
+ 15 more modules · 1,000+ data sources$0.33/session
03 · Register the webhook

Configure one webhook destination for every verdict.

  • In the Business Console: add your webhook Uniform Resource Locator (URL), pick the events, and copy the signing secret Didit generates.
  • By API: call POST /v3/webhook/destinations/ with label, url, and subscribed_events. The response returns the secret_shared_key Didit uses to sign every delivery.
Create Webhook Destination API
REST · OpenAPI 3
docs.didit.me
  • POST/v3/session/
  • GET/v3/session/{id}/decision/
  • PATCH/v3/session/{id}/update-status/
  • GET/v3/session/{id}/generate-pdf
  • POST/v3/lists/{id}/entries/face-upload/
  • POST/v3/transactions/

Every endpoint open · every webhook HMAC-signed.

04 · Integrate in your app

Create a session, Software Development Kit (SDK) or direct API.

  • With a Software Development Kit (SDK): drop in the native SDK for Web, iOS, Android, React Native, or Flutter, same /v3/ contract underneath.
  • By API: call POST /v3/session/ with the workflow_id and a vendor_data value (your user identifier).

The response gives you a verification URL to redirect or embed in your app.

See the SDKs
POSThttps://verification.didit.me/v3/session/
curl
$ curl -X POST /v3/session/ \
  -H "x-api-key: $DIDIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_id": "3daf4c64-...",
    "vendor_data": "u_42",
    "callback": "https://acme.com/webhook"
  }'
201Created
{ "session_id": "4c5c7f3a-...", "url": "verify.didit.me/..." }
05 · Receive the verdict

Listen on the webhook, or poll.

  • Real-time webhook: your endpoint fires on every state change. Read the status ("Approved", "Declined", "In Review", "Resubmitted", …), update your database, ship.
  • By polling: call GET /v3/session/:session_id/decision/ for the same payload, useful when your stack cannot accept inbound traffic.

Status strings are exact and case-sensitive. Full state machine at docs.didit.me/integration/verification-statuses.

Verification Statuses
Events
live
  • session.verified2.4s ago200 OK
  • session.review_started12s ago200 OK
  • session.aml_hit1m ago200 OK
  • session.declined3m ago200 OK
Build with Didit

Every surface, public. Zero sales calls.

Read the docs, call the Application Programming Interface (API), plug into a Model Context Protocol (MCP) server, paste an integration prompt, or ship a pre-built agent skill, all public, all free.
Documentation

Find every module, endpoint, and webhook.

Quickstart

Ship a KYC flow in 5 minutes.

API reference

Read the OpenAPI 3.1 spec.

SDKs

Embed on Web, iOS, Android, React Native, or Flutter.

Webhooks

Receive HMAC-signed events on every state change.

Verification statuses

Read the full session state machine.

Integration prompt

Paste one prompt. Ship the KYC integration.

MCP server

Plug Didit into any MCP client.

Agent Skills

Pre-built verification, AML, and KYB skills.

Five-minute integration

One curl. Five SDKs.

Start a verification session with one curl, or embed the flow on Web, iOS, Android, React Native, or Flutter, same /v3/ contract underneath.
POSThttps://verification.didit.me/v3/session/
curl
$ curl -X POST /v3/session/ \
  -H "x-api-key: $DIDIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_id": "3daf4c64-...",
    "vendor_data": "u_42",
    "callback": "https://acme.com/webhook"
  }'
201Created
{ "session_id": "4c5c7f3a-...", "url": "verify.didit.me/..." }
Webv1.4.0iOSv3.0.1Androidv2.6.2
React Nativev1.8.0Flutterv1.3.4
For developers · For AI agents · Open by design

Built for developers and AI agents.

Integrate Didit identity and fraud checks with one Application Programming Interface (API). Open the sandbox, read the public docs, plug into a Model Context Protocol (MCP) server, or pull a Software Development Kit (SDK) for any stack. Developers ship in an afternoon; AI coding agents ship in one prompt, no UI, no human in the loop, no sales call, no minimums.
01 · One API

One API for identity and fraud.

One Application Programming Interface (API) covers every identity and fraud check, Know Your Customer (KYC), Know Your Business (KYB), Anti-Money Laundering (AML), transaction monitoring, biometric matching. Same key, same workflow engine, chainable in a single session, no extra integration work between products.
Read the API docs
POSThttps://verification.didit.me/v3/session/
curl
$ curl -X POST /v3/session/ \
  -H "x-api-key: $DIDIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_id": "3daf4c64-...",
    "vendor_data": "u_42",
    "callback": "https://acme.com/webhook"
  }'
201Created
{ "session_id": "4c5c7f3a-...", "url": "verify.didit.me/..." }
02 · Agent-native

Integrate in a single prompt.

Our Model Context Protocol (MCP) server is live and the agent skills are published. Ask Claude Code, Codex, or Cursor to integrate Didit, the agent creates the workspace, configures the workflow, and ships the first API call on its own. No dashboard, no human, no support ticket.
Read the integration prompt
promptdidit-integration.md
# Integrate Didit into my application

You are integrating Didit — infrastructure for identity and fraud — into my application end-to-end. Didit ships KYC, KYB, AML screening, biometric verification, transaction monitoring, and wallet screening behind one API. 220+ countries, 14,000+ document types, 48+ languages. Pay-per-call from $0.33, 500 free verifications per core feature per month, no minimums, no contract.

## My application context

<my_stack>
Stack: [framework + language — e.g. Next.js 15 + TypeScript, Django, Rails, Go]
Surface: [web | iOS | Android | React Native | Flutter | backend-only]
Use case: [KYC at signup | KYB at business onboarding | age gate | re-auth | transaction monitoring | other]
Database: [Postgres | MySQL | Mongo | other]
</my_stack>

## Step 1 — Create the Didit account programmatically

Two API calls. No browser. No 2FA. Returns an `api_key` you use for every subsequent request.

```bash
# 1) Register — creates org + app + emails a 6-character code
curl -X POST https://apx.didit.me/auth/v2/programmatic/register/   -H "Content-Type: application/json"   -d '{"email": "dev@example.com", "password": "StrongP@ss1"}'

# 2) Verify email with the code from the inbox — returns api_key
curl -X POST https://apx.didit.me/auth/v2/programmatic/verify-email/   -H "Content-Type: application/json"   -d '{"email": "dev@example.com", "code": "A3K9F2"}'
# Response.application.api_key — save this
```

Persist the returned `api_key` as the env var `DIDIT_API_KEY`. Auth header for every Didit call:
`x-api-key: $DIDIT_API_KEY`

## Base URLs

| Surface | Base URL |
|---|---|
| Every `/v3/...` endpoint (sessions, workflows, lists, billing, webhook destinations, entities, transactions, standalone APIs) | `https://verification.didit.me` |
| Auth / programmatic registration (`/auth/v2/programmatic/...`) | `https://apx.didit.me` |
| Console (human UI) | `https://business.didit.me` |
| Hosted verification URL handed to end users | `https://verify.didit.me` |
| Docs (cross-check anything) | `https://docs.didit.me` |
| OpenAPI spec (machine-readable, server is `https://verification.didit.me`) | `https://docs.didit.me/openapi-25.json` |

## Step 2 — Choose the integration approach

Pick exactly one, based on my use case:

- **Approach A — Sessions API + SDK (recommended for any end-user verification flow).** My backend creates a Didit session → my frontend opens the Didit-hosted verification UI (via SDK / iframe / redirect) → user completes verification → my backend receives a webhook with the decision. Best for KYC at signup, KYB at business onboarding, age verification, re-auth. Didit-hosted flows are A/B-tested and convert higher than custom UIs.
- **Approach B — Standalone APIs (server-to-server only).** My backend calls individual modules directly (`/v3/id-verification/`, `/v3/aml/`, `/v3/face-match/`, etc.) for batch jobs or fully custom UI. Best for back-office verification pipelines.

If unsure, default to Approach A.

## Step 3 — Create or reuse a workflow

A workflow defines which modules run during a session. Create one via API (or `https://business.didit.me` → Workflows → Create).

```bash
# List existing workflows
curl https://verification.didit.me/v3/workflows/   -H "x-api-key: $DIDIT_API_KEY"

# Create a new KYC workflow — features are UPPERCASE enum values, each an object with optional `config`
curl -X POST https://verification.didit.me/v3/workflows/   -H "x-api-key: $DIDIT_API_KEY"   -H "Content-Type: application/json"   -d '{
    "workflow_label": "Standard KYC",
    "features": [
      { "feature": "OCR" },
      { "feature": "LIVENESS", "config": { "face_liveness_method": "PASSIVE" } },
      { "feature": "FACE_MATCH" },
      { "feature": "IP_ANALYSIS" }
    ]
  }'
# Response.uuid — save as DIDIT_WORKFLOW_ID
```

Feature enum values (UPPERCASE, source: `management-api/workflows/feature-configs.mdx`):
- **KYC features:** `OCR`, `NFC`, `LIVENESS`, `FACE_MATCH`, `AGE_ESTIMATION`, `PHONE_VERIFICATION`, `EMAIL_VERIFICATION`, `DATABASE_VALIDATION`, `AML`, `IP_ANALYSIS`, `PROOF_OF_ADDRESS`, `QUESTIONNAIRE`.
- **KYB features:** `KYB_REGISTRY`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE` (each plus AML / DATABASE_VALIDATION as needed).

For a KYB workflow set `"workflow_type": "kyb"` (default is KYC). A workflow is locked to its type at creation; create separate workflows per kind.

## Step 4 — Install the SDK that matches my stack

| Stack | Package | Install |
|---|---|---|
| Web (React, Vue, Next.js, Nuxt, Svelte, vanilla JS) | `@didit-protocol/sdk-web` | `npm install @didit-protocol/sdk-web` |
| iOS (Swift / SwiftUI) | `didit-sdk-ios` | SPM: `https://github.com/didit-protocol/didit-sdk-ios` |
| Android (Kotlin / Jetpack Compose) | `me.didit:didit-sdk` | Maven |
| React Native (Expo or bare) | `@didit-protocol/sdk-react-native` | `npm install @didit-protocol/sdk-react-native` |
| Flutter | `didit_sdk` | `flutter pub add didit_sdk` |
| Backend-only / batch / custom UI | none — call REST directly | — |

Always prefer native iOS / Android SDKs over WebView on mobile (NFC + camera + biometrics work natively).

## Step 5 — Create a session and present it to the user

**Backend creates the session:**

```bash
curl -X POST https://verification.didit.me/v3/session/   -H "x-api-key: $DIDIT_API_KEY"   -H "Content-Type: application/json"   -d '{
    "workflow_id": "'"$DIDIT_WORKFLOW_ID"'",
    "vendor_data": "internal-user-id",
    "callback": "https://myapp.com/done"
  }'
```

Response (201 Created):
```json
{
  "session_id": "4c5c7f3a-...",
  "session_token": "eyJ...",
  "url": "https://verify.didit.me/session/...",
  "status": "Not Started",
  "session_kind": "user",
  "workflow_id": "...",
  "vendor_data": "internal-user-id"
}
```

`vendor_data` is **my internal user ID** — Didit links the session to a User entity (auto-created if new). For KYB workflows it links to a Business entity.

Optional create-session field: `callback_method` (`"initiator"` | `"completer"` | `"both"`, default `"initiator"`) — controls which side of a cross-device flow receives the `callback` redirect. Useful when the verification opens on a phone after a desktop start.

**Frontend presents the verification (pick one):**

| Pattern | Code |
|---|---|
| Web JS SDK (modal) | `import { DiditSdk } from "@didit-protocol/sdk-web"; DiditSdk.shared.startVerification({ url })` |
| Iframe (embedded) | `<iframe src={url} allow="camera; microphone; fullscreen; autoplay; encrypted-media" />` |
| Redirect (cross-device) | `window.location.href = url` |
| iOS / Android / RN / Flutter | `DiditSdk.startVerification(token: session_token)` |

## Step 6 — Set up the webhook to receive results

Build `POST /api/webhooks/didit` in my backend.

**Register the webhook destination once:**

```bash
curl -X POST https://verification.didit.me/v3/webhook/destinations/   -H "x-api-key: $DIDIT_API_KEY"   -H "Content-Type: application/json"   -d '{
    "url": "https://myapp.com/api/webhooks/didit",
    "label": "production",
    "subscribed_events": ["status.updated", "data.updated"]
  }'
```

Response includes `secret_shared_key` — save as `DIDIT_WEBHOOK_SECRET`.

**Cloudflare / restrictive firewall users:** allowlist `18.203.201.92` — Didit webhooks egress from this single IP.

**Three signature headers** ship on every webhook. Verify **one** — `X-Signature-V2` is recommended because it survives JSON middleware re-encoding:

| Header | What it signs | When to use |
|---|---|---|
| `X-Signature-V2` ★ recommended | `JSON.stringify(sortKeys(shortenFloats(parsed_body)))` with unescaped Unicode | Default — works through Express / Django / FastAPI / Next.js body parsers |
| `X-Signature` | The raw request bytes verbatim | Only if you can guarantee no middleware re-encodes the body |
| `X-Signature-Simple` | `"{timestamp}:{session_id}:{status}:{webhook_type}"` | Fallback when nothing else works — does NOT verify the `decision` payload, so only use as a hint |

**Endpoint requirements (in order):**

1. Parse JSON (V2 is parser-tolerant; you can use any framework's default body parser).
2. Read headers: `X-Signature-V2` (HMAC-SHA256 hex), `X-Timestamp` (Unix seconds).
3. Reject if `abs(now - X-Timestamp) > 300` (replay protection).
4. Apply `shortenFloats` (whole-number floats → integers), then `sortKeys` (recursive lexicographic), then `JSON.stringify` (unescaped Unicode — default).
5. Compute `expected = HMAC-SHA256(DIDIT_WEBHOOK_SECRET, canonical_json, "utf8")`.
6. Compare with `X-Signature-V2` using constant-time comparison (`hmac.compare_digest` in Python, `crypto.timingSafeEqual` in Node).
7. Dispatch on `webhook_type`. Return `200` immediately even if processing is async — Didit retries 5xx/404 twice (~1 min, ~4 min).

**Node.js / Next.js App Router example (canonical V2):**

```ts
import crypto from "node:crypto";

// Server-side normalisation: convert whole-number floats to integers.
function shortenFloats(v: unknown): unknown {
  if (Array.isArray(v)) return v.map(shortenFloats);
  if (v && typeof v === "object") {
    return Object.fromEntries(
      Object.entries(v as Record<string, unknown>).map(([k, x]) => [k, shortenFloats(x)])
    );
  }
  if (typeof v === "number" && !Number.isInteger(v) && v % 1 === 0) return Math.trunc(v);
  return v;
}

// Recursively sort object keys (arrays preserved in order).
function sortKeys(v: unknown): unknown {
  if (Array.isArray(v)) return v.map(sortKeys);
  if (v && typeof v === "object") {
    return Object.keys(v as object)
      .sort()
      .reduce<Record<string, unknown>>((acc, k) => {
        acc[k] = sortKeys((v as Record<string, unknown>)[k]);
        return acc;
      }, {});
  }
  return v;
}

export async function POST(req: Request) {
  const raw = await req.text();
  const sig = req.headers.get("x-signature-v2") ?? "";
  const ts = Number(req.headers.get("x-timestamp"));
  if (!ts || Math.abs(Date.now() / 1000 - ts) > 300)
    return new Response("stale", { status: 401 });

  const parsed = JSON.parse(raw);
  const canonical = JSON.stringify(sortKeys(shortenFloats(parsed)));
  const expected = crypto
    .createHmac("sha256", process.env.DIDIT_WEBHOOK_SECRET!)
    .update(canonical, "utf8")
    .digest("hex");
  if (
    sig.length !== expected.length ||
    !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig))
  )
    return new Response("bad sig", { status: 401 });

  // parsed.webhook_type → dispatch …
  return new Response("ok");
}
```

**Webhook event types:** `status.updated`, `data.updated`, `user.status.updated`, `user.data.updated`, `business.status.updated`, `business.data.updated`, `activity.created`, `transaction.created`, `transaction.status.updated`.

**Webhook body shape:**
```json
{
  "session_id": "uuid",
  "status": "Not Started | In Progress | Awaiting User | In Review | Approved | Declined | Resubmitted | Abandoned | Expired | Kyc Expired",
  "webhook_type": "status.updated",
  "timestamp": 1627680000,
  "workflow_id": "uuid",
  "vendor_data": "internal-user-id",
  "metadata": { "any": "json" },
  "decision": { /* present when Approved / Declined / In Review; absent on Expired / Abandoned / Not Started */ }
}
```

The `decision` object holds per-module **plural arrays** (V3 schema — each entry keyed by its `node_id` in the workflow):
- `id_verifications[]`: first_name, last_name, document_type, document_number, date_of_birth, nationality, expiration_date, issuing_state, address, parsed_address, mrz, front_image_quality_score, back_image_quality_score, warnings[]
- `nfc_verifications[]`: status, document_type, mrz, signature_status, chip_data
- `liveness_checks[]`: status, score (0–1), method ("passive" | "active"), reference_image
- `face_matches[]`: status, score (0–100), source_image, target_image, warnings[]
- `phone_verifications[]`: status, phone_number, carrier, is_disposable, is_virtual
- `email_verifications[]`: status, email, is_breached, is_disposable, is_undeliverable, breaches[]
- `poa_verifications[]`: status, document_type, issuer, poa_address, poa_parsed_address, issue_date, expiration_date
- `aml_screenings[]`: status, total_hits, hits[] (pep_matches, sanction_matches, warning_matches, adverse_media_matches), entity_type ("person" | "company")
- `ip_analyses[]`: status, ip_address, country, vpn, proxy, tor, hosting, risk_score
- `database_validations[]`: status, provider, match_type, fields_matched
- `questionnaire_responses`: nullable object keyed by question_id → answer

V2 → V3 migration note: V2 used singular keys (`aml`, `phone`, `email`, `poa`). V3 renamed them to plural arrays so a single workflow can run the same module multiple times on different nodes — index by `node_id`.

## Step 7 — Apply the decision to my database

```ts
switch (event.status) {
  case "Approved":       user.verified = true; user.verifiedAt = new Date(); storeDecision(event.decision); break;
  case "Declined":       user.verificationStatus = "declined"; logWarnings(event.decision); break;
  case "In Review":      user.verificationStatus = "pending_review"; break;
  case "In Progress":    user.verificationStatus = "in_progress"; break;
  case "Awaiting User":  user.verificationStatus = "awaiting_user"; break; // KYB only — waiting for a UBO / officer KYC sub-session
  case "Resubmitted":    user.verificationStatus = "resubmitted"; break; // reviewer asked the user to retry
  case "Abandoned":      scheduleReminderEmail(user); break;
  case "Expired":        break; // session URL aged out before the user finished
  case "Kyc Expired":    user.verified = false; createNewSession(user); break; // verified user's KYC has aged out per retention policy
  case "Not Started":    break;
}
```

Idempotency:
- Session webhooks: dedupe on `session_id + webhook_type + timestamp`.
- Transaction webhooks (`transaction.created`, `transaction.status.updated`): dedupe on the `event_id` field — multiple events can target the same transaction.

Didit retries 5xx/404 twice (~1 min, ~4 min after the prior failure). Return 200 even if processing is async.

## Module catalogue (use whichever ones match my use case)

| Module | Endpoint | Price | Free tier |
|---|---|---|---|
| Core KYC bundle (ID + Liveness + Face Match + IP) | session w/ workflow | **$0.33** | 500/mo (per feature) |
| ID Verification (standalone) | `POST /v3/id-verification/` | $0.20 | 500/mo |
| Passive Liveness (standalone) | `POST /v3/passive-liveness/` | $0.05 | 500/mo |
| Active Liveness | session-only | $0.15 | — |
| Face Match 1:1 | `POST /v3/face-match/` | $0.05 | 500/mo |
| Face Search 1:N | `POST /v3/face-search/` | $0.05 | — |
| Age Estimation | `POST /v3/age-estimation/` | $0.10 | — |
| AML Screening | `POST /v3/aml/` | $0.20 | — |
| Ongoing AML Monitoring | org-level continuous (per active user/yr) | $0.07 / user / year | — |
| Database Validation (gov registries) | `POST /v3/database-validation/` | variable | — |
| Proof of Address | `POST /v3/poa/` | $0.20 | — |
| Email Verification | `POST /v3/email/send/` + `POST /v3/email/check/` | $0.03 | — |
| Phone Verification (SMS / WhatsApp / voice / RCS / Telegram) | `POST /v3/phone/send/` + `POST /v3/phone/check/` | $0.04 + carrier | — |
| NFC Verification (native SDKs only) | session module | $0.15 | — |
| Biometric Authentication (re-auth) | session module | $0.10 | — |
| Device & IP Analysis | session module | $0.03 | — |
| Custom Questionnaire | session module | $0.10 | — |
| Business Verification (KYB) | `POST /v3/session/` w/ KYB workflow | $2.00 | — |
| Company AML Screening | KYB module | $0.20 | — |
| Person AML (per UBO / officer) | KYB module | $0.20 | — |
| Transaction Screening (rule engine) | `POST /v3/transactions/` | $0.02 / tx | — |
| AML Transaction Screening (counterparty sanctions + on-chain wallet risk) | inside `/v3/transactions/` | $0.15 / tx | — |
| Reusable KYC (share verified user across partners) | session feature | Free | — |
| White Label | workflow option | $0.20 | — |

## Operational APIs your code should know

| Action | Endpoint |
|---|---|
| Read full decision JSON | `GET /v3/session/{id}/decision/` |
| List sessions (filter by status, workflow, vendor_data, date) | `GET /v3/sessions` |
| Manually approve / decline / request review | `PATCH /v3/session/{id}/update-status/` |
| Patch metadata or extracted data | `PATCH /v3/session/{id}/update-data/` |
| Download compliance PDF | `GET /v3/session/{id}/generate-pdf` |
| Delete a session (GDPR / cleanup) | `DELETE /v3/session/{id}/delete/` |
| Share session with a partner (Reusable KYC) | `POST /v3/session/{id}/share/` |
| Submit a transaction for monitoring | `POST /v3/transactions/` |
| List / create lists (blocklist, allowlist, custom) | `GET/POST /v3/lists/` |
| Add entry to a list | `POST /v3/lists/{id}/entries/` |
| Upload a face image to a blocklist | `POST /v3/lists/{id}/entries/face-upload/` |
| Check credit balance | `GET /v3/billing/balance/` |
| Top up credits (returns Stripe checkout URL) | `POST /v3/billing/top-up/` |
| List / update / delete vendor users | `GET/PATCH /v3/users/`, `/v3/users/{vendor_data}/` |
| List / update / delete vendor businesses | `GET/PATCH /v3/businesses/` |

Every `/v3/...` endpoint above is served from `https://verification.didit.me` (the canonical OpenAPI server) and authenticates with `x-api-key`. Auth/registration is the only surface on `https://apx.didit.me`.

## Best-practice checklist before you mark this done

- [ ] `DIDIT_API_KEY`, `DIDIT_WORKFLOW_ID`, `DIDIT_WEBHOOK_SECRET` in env. Never committed.
- [ ] Backend route that creates a session for a given user, returns `url` (the hosted verification URL on `verify.didit.me`) and the `session_id`.
- [ ] Frontend that opens the session `url` via the right SDK / iframe / redirect for my stack.
- [ ] Webhook endpoint with: `X-Timestamp` freshness check (≤ 300s), canonical-V2 JSON re-serialisation (`shortenFloats` → `sortKeys` → unescaped `JSON.stringify`) HMAC-SHA256, constant-time compare against `X-Signature-V2`, dispatch on `webhook_type`, return 200.
- [ ] DB schema + update logic for `status in (Not Started, In Progress, Awaiting User, In Review, Approved, Declined, Resubmitted, Abandoned, Expired, Kyc Expired)`.
- [ ] Idempotent webhook handler (dedupe on `session_id + webhook_type`).
- [ ] No API key shipped to the browser. The session creation is server-side only.
- [ ] User-facing consent / disclosure shown BEFORE the session `url` opens (Didit handles biometric consent inside its flow but the legal layer outside is the integrator's responsibility).
- [ ] (Optional) `/v3/session/{id}/generate-pdf` surfaced in compliance UI.

## When you need more detail

- API root: `https://verification.didit.me/v3/` (everything `/v3/`). Auth only: `https://apx.didit.me/auth/v2/programmatic/register/`.
- Sessions overview: `https://docs.didit.me/sessions-api/overview`
- Standalone APIs index: `https://docs.didit.me/standalone-apis/id-verification`
- Programmatic registration: `https://docs.didit.me/integration/programmatic-registration`
- AI agent / MCP integration: `https://docs.didit.me/integration/ai-agent-integration`
- Webhooks reference: `https://docs.didit.me/integration/webhooks`
- SDKs overview: `https://docs.didit.me/integration/sdks`
- Full OpenAPI 3 spec: `https://docs.didit.me/openapi-25.json`
- MCP server config (drop into `.cursor/mcp.json`, `claude_desktop_config.json`, or equivalent):

```json
{
  "mcpServers": {
    "didit": {
      "command": "npx",
      "args": ["@didit-protocol/mcp-server"],
      "env": { "DIDIT_API_KEY": "your_api_key" }
    }
  }
}
```

The MCP server exposes 40+ tools spanning auth, sessions, workflows, questionnaires, users, billing, blocklist, and every standalone API — see `https://docs.didit.me/integration/ai-agent-integration` for the full tool catalogue.

Now build the integration. If anything in `## My application context` is missing, ask once at the top of your reply, then ship the complete change set: env vars wired, backend route, frontend SDK call, webhook endpoint with signature verification, decision-handling DB logic, and idempotent dedupe. Use my stack's idioms (`fetch` / `axios` / `requests` / `okhttp`), keep the API key server-side only, and follow the verification status state machine above.
Paste in Claude Code, Codex, or Cursor · ships the full integration
03 · Modular

Any flow. Any country. Any use case.

Compose any flow from 25+ modules, 1,000+ government data sources, 220+ countries, 14,000+ document types, and 48+ languages. The same orchestrator runs biometric auth, KYC for a neobank, KYB for a B2B fintech, Travel Rule for a crypto exchange, or ongoing AML for a marketplace, you pick the checks and the order.
See every module
Workflowkyc-onboarding-v3
220+ countries
  • ID Verification
  • Passive Liveness
  • Face Match 1:1
  • AML Screening
  • Device & IP Analysis
  • Proof of Address
  • NFC Reading
  • Phone Verification
  • Wallet Screening
  • Custom Questionnaire
+ 15 more modules · 1,000+ data sources$0.33/session
04 · Self-serve

No paywall. No sales call. Go play with it.

The sandbox is open from minute one. Docs and API are public, with no demo gate between you and the code. Sign up, grab a key, ship the same day. Our sales team is around when you want them, never as a gate.
Try the sandbox
Production API key
Live
didit_sk_live_8f4c2a…9bf3

Issued just now, no card, no contract, no call.

  • No minimum
  • No contract
  • 500 free / mo
  • Open sandbox
05 · Usage-based

Pay for what you use. That's it.

Didit is 3–5× cheaper than incumbent KYC vendors, with every price public on /pricing, $0.33 full KYC bundle, $0.15 wallet screening, $0.03 Device & IP analysis, 500 verifications free every month. No minimums, no annual contracts, no overage surprises, the price on the page is the price on the invoice.
See every price
Public price list
/pricing
  • ID Verification$0.15
  • Passive Liveness$0.10
  • Face Match 1:1$0.05
  • AML Screening$0.20
  • Device & IP Analysis$0.03
  • Wallet Screening (KYT)$0.15
Full KYC bundle$0.33

500 free / month · no minimum · no annual contract.

06 · Open infra

Open API. Build on top.

Every endpoint is open and documented, change a session's status, blocklist a face, download a decision PDF, edit a workflow, or query the event log. Webhooks are signed with Hash-based Message Authentication Code (HMAC), so you can prove every event came from us. Didit is infrastructure, not a closed app.
Browse the API
REST · OpenAPI 3
docs.didit.me
  • POST/v3/session/
  • GET/v3/session/{id}/decision/
  • PATCH/v3/session/{id}/update-status/
  • GET/v3/session/{id}/generate-pdf
  • POST/v3/lists/{id}/entries/face-upload/
  • POST/v3/transactions/

Every endpoint open · every webhook HMAC-signed.

07 · SDKs

SDKs for every platform.

A Software Development Kit (SDK) for every stack, Web, iOS, Android, React Native, Flutter. On the backend, a REST API, signed webhooks, an OpenAPI 3 spec, and ready-made Zapier, Shopify, and Salesforce integrations. Every surface ships with samples, types, and a 5-minute getting-started.
Browse the SDKs
Webv1.4.0iOSv3.0.1Androidv2.6.2
React Nativev1.8.0Flutterv1.3.4
08 · Scale-optimized infra

The fastest verifications on the market.

99% of verifications finish in under 2 seconds, end-to-end, measured in production, not claimed in a deck. We target a 99.99% Service-Level Agreement (SLA), held 100% uptime over the last 12 months, and have never been breached. Tuned for every device and network, iPhone, Android, desktop, tablet, 5G or 2G, and already running millions of verifications a month.
See live status
End-to-end latency · 30d
99.99% SLA
  • p500.82s
  • p951.42s
  • p991.89s

Fastest verifications in market · iPhone, Android, desktop, tablet, 5G or 2G.

Three tiers, one price list

Start free. Pay per usage. Scale to Enterprise.

500 free verifications every month, forever. Pay-as-you-go for production. Custom contracts, data residency, and SLAs (Service Level Agreements) on Enterprise.
Free

Free

$0 / month. No credit card required.

  • Free KYC bundle (ID Verification + Passive Liveness + Face Match + Device & IP Analysis), 500 / month, every month
  • Blocklisted Users
  • Duplicate Detection
  • 200+ fraud signals on every session
  • Reusable KYC across the Didit network
  • Case Management Platform
  • Workflow Builder
  • Public docs, sandbox, SDKs, MCP (Model Context Protocol) server
  • Community support
Most popular
Pay per usage

Usage Based

Pay only for what you use. 25+ modules. Public per-module pricing, no monthly minimum fee.

  • Full KYC at $0.33 (ID + Biometric + IP / Device)
  • 10,000+ AML datasets, sanctions, PEPs, adverse media
  • 1,000+ government data sources for Database Validation
  • Transaction Monitoring at $0.02 per transaction
  • Live KYB at $2.00 per business
  • Wallet Screening at $0.15 per check
  • Whitelabel verification flow, your brand, our infrastructure
Enterprise

Enterprise

Custom MSA & SLA. For large volumes and regulated programs.

  • Annual contracts
  • Custom MSA, DPA, and SLA
  • Dedicated Slack and WhatsApp channel
  • Manual reviewers on demand
  • Reseller and white-label terms
  • Exclusive features and partner integrations
  • Named CSM, security review, compliance support

Start free → pay only when a check runs → unlock Enterprise for a custom contract, SLA, or data residency.

FAQ

Developer questions, answered.

The same answers we send to engineering teams during an integration call. Anything else, support@didit.me.
How do I integrate Didit?

Five steps from signup to first verdict.

  • Create your account at business.didit.me, or call POST https://apx.didit.me/auth/v2/programmatic/register/.
  • Build a workflow in the Business Console, or call POST /v3/workflows/.
  • Register a webhook destination via the console, or call POST /v3/webhook/destinations/ (Didit returns the signing secret in the response).
  • Create a session with POST /v3/session/, passing workflow_id and vendor_data (your user identifier). Redirect the user to the returned URL, or drop in a native Software Development Kit (SDK) on the same /v3/ contract.
  • Receive the verdict on the signed webhook, or poll GET /v3/session/:session_id/decision/.

One /v3/ Application Programming Interface (API) covers Know Your Customer (KYC), Know Your Business (KYB), Transaction Monitoring, and Wallet Screening (KYT, know your transaction). 500 verifications free every month, forever, no credit card.

Is there a sandbox I can play with right now?

Yes, under sixty seconds, no credit card. Sign up at business.didit.me (or register programmatically with POST https://apx.didit.me/auth/v2/programmatic/register/) and you land in a sandbox workspace with a real Application Programming Interface (API) key.

  • Same shape as production, deterministic decisions, every module unlocked.
  • Real /v3/ endpoints, real webhooks, real document samples.
  • Switch to live whenever you are ready, same keys, same Uniform Resource Locators (URLs), same contract.
Which Software Development Kits (SDKs) do you ship?

Five first-party SDKs, all open-source, all on public docs:

  • Web, JavaScript / TypeScript, framework-agnostic, iframe embed or hosted-flow redirect.
  • iOS, Swift, distributed as XCFramework.
  • Android, Kotlin, via Maven Central.
  • React Native, TypeScript bindings on top of native modules (TurboModules).
  • Flutter, Dart wrapper around the same native SDKs.

Every SDK calls the same /v3/ contract under the hood, so you can mix and match, Web on your site, native on mobile. Reference at docs.didit.me/integration/web-sdks/overview.

How do webhooks work?

Register one destination; Didit signs every delivery.

  • Configure your endpoint via the Business Console, or call POST /v3/webhook/destinations/ with label, url, and subscribed_events.
  • Didit returns a secret_shared_key in the response. Use it to verify the Hash-based Message Authentication Code (HMAC)-SHA256 signature on every incoming webhook (header: X-Signature-V2).
  • Each payload carries an exact, case-sensitive status, "Approved", "Declined", "In Review", "Resubmitted", and more. Full state machine at docs.didit.me/integration/verification-statuses.
  • Retries use exponential backoff until you return 2xx; every delivery is logged and replayable on demand from the console.

Full reference at docs.didit.me/integration/webhooks.

What are the rate limits, and what happens at scale?

Generous defaults on every plan, tuned upward per account.

  • Free tier, sandbox plus 500 production checks every month, forever.
  • Pay-per-usage, burst limits scale automatically with sustained volume. You will not hit a wall mid-launch.
  • Enterprise, custom rate limits, dedicated capacity, and uptime commitments in the Master Services Agreement (MSA). Talk to us at support@didit.me.

Target capacity per region at status.didit.me. 100% real uptime over the last 6 months across millions of verifications a month.

Can I integrate with Claude Code, Cursor, or other AI coding tools?

Yes, paste one prompt and ship. Drop the canonical integration prompt at docs.didit.me/integration/integration-prompt into Claude Code, Cursor, Codex, Devin, Aider, or Replit Agent. The agent provisions the workflow, wires the webhook, and runs a smoke test end-to-end.

Agent-initiated sessions pay the same public price as direct API calls, $0.33 per full Know Your Customer (KYC), $0.15 per standalone Identity Document Verification, $0.15 per wallet screen. Free, no extra setup, works with any Model Context Protocol (MCP)-aware client.

Where is the changelog, and how do you version the API?

Monthly release notes at `docs.didit.me/changelog`, every shipped module, every webhook event added, every breaking change called out.

  • The OpenAPI 3.1 specification at docs.didit.me/openapi-25.json is versioned alongside the docs. Import it into Postman or generate clients in any language.
  • Versioning is additive by default. New fields, new optional parameters, and new webhook events ship without a version bump. Breaking changes get a new /v4/ namespace and a published deprecation window.
  • We never silently change a field's meaning, if a verdict shape, signature scheme, or status enum changes, it ships behind a header and is announced before cut-over.
How do I monitor uptime and what is the incident process?

`status.didit.me` publishes real-time uptime and incident history per region, verification, webhooks, console, docs. No login required.

  • Subscribe via Really Simple Syndication (RSS), email, or webhook for outage alerts.
  • Track record: 100% real uptime over the last 6 months; 99.99% availability target in the Service Level Agreement (SLA).
  • Every incident gets a public post-mortem on the same page.
  • Enterprise contracts add a named on-call engineer, a dedicated Slack or Microsoft Teams shared channel, and incident-severity Service Level Objectives in the Master Services Agreement (MSA).

Infrastructure for identity and fraud.

One API for KYC, KYB, Transaction Monitoring, and Wallet Screening. Integrate in 5 minutes.

Ask an AI to summarise this page