Skip to main content
This guide walks you through the complete flow for integrating Didit identity verification via API. Follow these steps to get up and running quickly.

Step 1: Get Your Credentials

From the Didit Console

  1. Go to Didit Console
  2. Create or select your organization
  3. Navigate to SettingsAPI Keys
  4. Copy your credentials:
    • API Key – For authenticating API requests
    • Webhook Secret Key – For verifying webhook signatures

Environment Variables

Add these to your .env file:
# Required
DIDIT_API_KEY=your_api_key_here
DIDIT_WEBHOOK_SECRET=your_webhook_secret_here

# Your workflow ID (from the Console)
DIDIT_WORKFLOW_ID=your_workflow_id_here

Step 2: Create a Workflow

Before creating sessions, you need a verification workflow. Workflows define what verification steps users go through.

Create in Console

  1. Go to Didit ConsoleWorkflows
  2. Click Create Workflow
  3. Choose a base template:
TemplateBest For
KYCFull identity verification with ID document
Adaptive Age VerificationAge verification with optional ID backup
Biometric AuthenticationRe-verifying returning users
Address VerificationProof of address verification
  1. Add optional features:
FeatureDescription
NFC VerificationRead passport/ID chip data
Liveness DetectionPrevent spoofing with selfie video
Face MatchingMatch selfie to document photo
Phone VerificationVerify phone number via SMS
Email VerificationVerify email address
AML ScreeningCheck against sanctions/PEP lists
Database ValidationVerify against government databases
IP AnalysisDetect VPNs, proxies, geolocation
  1. Copy your Workflow ID
See Workflows Documentation for detailed configuration options.

Step 3: Create a Verification Session

Call the API to create a session for your user.

Request

curl -X POST https://verification.didit.me/v3/session/ \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "workflow_id": "your-workflow-id",
    "callback": "https://yourapp.com/verification-complete",
    "vendor_data": "user-123"
  }'

Request Parameters

ParameterRequiredDescription
workflow_id✅ YesYour workflow ID from the Console
callback✅ YesURL to redirect user after verification
vendor_data❌ OptionalYour internal user identifier (returned in webhooks)
metadata❌ OptionalCustom JSON data stored with the session
contact_details❌ OptionalUser’s email/phone for prefill and notifications
expected_details❌ OptionalExpected user details for cross-validation

Full Example with All Options

curl -X POST https://verification.didit.me/v3/session/ \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "workflow_id": "11111111-2222-3333-4444-555555555555",
    "callback": "https://yourapp.com/verification-complete",
    "vendor_data": "user-123",
    "metadata": {
      "plan": "premium",
      "signup_source": "mobile-app"
    },
    "contact_details": {
      "email": "[email protected]",
      "email_lang": "en",
      "send_notification_emails": true,
      "phone": "+14155552671"
    },
    "expected_details": {
      "first_name": "John",
      "last_name": "Doe",
      "date_of_birth": "1990-01-15"
    }
  }'

Response

{
  "session_id": "abc123-def456-ghi789",
  "session_number": 1234,
  "session_token": "eyJhbGciOiJIUzI1NiIs...",
  "vendor_data": "user-123",
  "metadata": {
    "plan": "premium",
    "signup_source": "mobile-app"
  },
  "status": "Not Started",
  "workflow_id": "11111111-2222-3333-4444-555555555555",
  "callback": "https://yourapp.com/verification-complete",
  "verification_url": "https://verify.didit.me/session/abc123..."
}

Key Response Fields

FieldDescription
session_idUnique identifier for this session
session_tokenToken for SDK initialization
verification_urlURL to redirect user or embed in iframe
statusCurrent status (Not Started, In Progress, etc.)
See Create Session API Reference for complete documentation.

Step 4: Present Verification to User

Choose how to present the verification flow to your user: Use the session_token with our native SDKs for the best user experience:
// iOS
DiditSdk.shared.startVerification(token: sessionToken)
iOS SDK | Android SDK | React Native | Flutter Embed the verification in your page:
<iframe
  src="{verification_url}"
  style="width: 100%; height: 700px; border: none;"
  allow="camera; microphone; fullscreen; autoplay; encrypted-media"
></iframe>
InContext Documentation

Option C: Redirect

Redirect the user to the verification URL:
window.location.href = verificationUrl;
Redirect Documentation

Option D: Mobile WebView

For mobile apps without native SDK:
// React Native
<WebView source={{ uri: verificationUrl }} />
WebView Documentation

Step 5: Receive Results

Webhooks notify your server in real-time when verification status changes. Setup:
  1. Configure your webhook URL in the Console
  2. Implement a webhook endpoint on your server
Example Webhook Payload:
{
  "session_id": "abc123-def456-ghi789",
  "status": "Approved",
  "webhook_type": "status.updated",
  "vendor_data": "user-123",
  "workflow_id": "11111111-2222-3333-4444-555555555555",
  "decision": {
    "status": "Approved",
    "id_verifications": [...],
    "liveness_checks": [...],
    "face_matches": [...]
  }
}
Verify the Signature:
const crypto = require("crypto");

function verifyWebhook(body, signature, timestamp, secret) {
  const currentTime = Math.floor(Date.now() / 1000);
  if (Math.abs(currentTime - parseInt(timestamp)) > 300) {
    return false; // Request too old
  }

  const expectedSignature = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(signature),
  );
}
Full Webhooks Documentation

Via API (Optional)

You can also fetch results via API:
curl https://verification.didit.me/v3/session/{session_id}/decision/ \
  -H "x-api-key: YOUR_API_KEY"
Retrieve Session API Reference

Complete Code Examples

Node.js / Express

const express = require("express");
const crypto = require("crypto");
const app = express();

// Create verification session
app.post("/api/verify", async (req, res) => {
  const { userId } = req.body;

  const response = await fetch("https://verification.didit.me/v3/session/", {
    method: "POST",
    headers: {
      "x-api-key": process.env.DIDIT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      workflow_id: process.env.DIDIT_WORKFLOW_ID,
      callback: `${process.env.APP_URL}/verification-complete`,
      vendor_data: userId,
    }),
  });

  const session = await response.json();

  // Store session_id associated with user
  await db.users.update({
    where: { id: userId },
    data: { verificationSessionId: session.session_id },
  });

  res.json({
    verificationUrl: session.verification_url,
    sessionToken: session.session_token,
  });
});

// Handle webhook
app.post(
  "/api/webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const signature = req.headers["x-signature-v2"];
    const timestamp = req.headers["x-timestamp"];

    if (
      !verifyWebhook(
        req.body,
        signature,
        timestamp,
        process.env.DIDIT_WEBHOOK_SECRET,
      )
    ) {
      return res.status(401).json({ error: "Invalid signature" });
    }

    const payload = JSON.parse(req.body);
    const { session_id, status, vendor_data } = payload;

    // Update user's verification status
    if (status === "Approved") {
      db.users.update({
        where: { id: vendor_data },
        data: { isVerified: true, verifiedAt: new Date() },
      });
    }

    res.json({ received: true });
  },
);

app.listen(3000);

Python / FastAPI

from fastapi import FastAPI, Request, HTTPException
import httpx
import hmac
import hashlib
import os
import time

app = FastAPI()

@app.post("/api/verify")
async def create_verification(user_id: str):
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "https://verification.didit.me/v3/session/",
            headers={
                "x-api-key": os.environ["DIDIT_API_KEY"],
                "Content-Type": "application/json"
            },
            json={
                "workflow_id": os.environ["DIDIT_WORKFLOW_ID"],
                "callback": f"{os.environ['APP_URL']}/verification-complete",
                "vendor_data": user_id
            }
        )

    session = response.json()
    return {
        "verification_url": session["verification_url"],
        "session_token": session["session_token"]
    }

@app.post("/api/webhook")
async def handle_webhook(request: Request):
    body = await request.body()
    signature = request.headers.get("x-signature-v2")
    timestamp = request.headers.get("x-timestamp")

    # Verify timestamp freshness
    if abs(int(time.time()) - int(timestamp)) > 300:
        raise HTTPException(status_code=401, detail="Request too old")

    # Verify signature
    expected = hmac.new(
        os.environ["DIDIT_WEBHOOK_SECRET"].encode(),
        body,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        raise HTTPException(status_code=401, detail="Invalid signature")

    payload = await request.json()

    if payload["status"] == "Approved":
        # Update user in database
        pass

    return {"received": True}

Session Statuses

StatusDescription
Not StartedSession created but user hasn’t begun
In ProgressUser is currently completing verification
In ReviewVerification needs manual review
ApprovedVerification successful
DeclinedVerification failed
AbandonedUser left without completing
ExpiredSession expired (default: 7 days)

Next Steps

  1. Choose your integration method:
  2. Configure webhooks: Webhooks Guide
  3. Customize your workflow: Workflows Documentation
  4. Test in sandbox: Use test credentials before going live

Need Help?