Skip to main content
Business Verification and Business entities emit webhook events on every meaningful state change. Subscribe to the events you care about via the webhook destinations API or the Business Console.

Event catalog

Webhook events are shared between User and Business sessions — the session_kind field on the payload tells you which kind the event refers to. Entity-level events are separate from session-level events.

Session-level events

EventWhen it fires
status.updatedA session’s status changed. For Business Verification (KYB) sessions the payload carries session_kind: "business".
data.updatedA session’s data was updated (registry refresh, key-people submission, document upload, AML rescan). Payload includes session_kind: "business" for KYB sessions.

Business entity events

EventWhen it fires
business.status.updatedThe linked Business entity’s status changed (ACTIVE / FLAGGED / BLOCKED).
business.data.updatedThe Business entity’s profile fields or aggregate counters changed.
Subscribe to any combination on your webhook destination. See entity webhooks for the full Business / User entity event reference.

Envelope

Every webhook uses the same top-level envelope. The session_kind field inside data discriminates between User Verification (KYC) and Business Verification (KYB) for session-level events.
{
  "event": "status.updated",
  "event_id": "evt_01H8X...",
  "application_id": "app_abc123",
  "timestamp": "2026-04-18T12:30:00Z",
  "data": { ... }
}

Payload shapes

status.updated — Business Verification (KYB) session

Fires when a KYB session’s status transitions.
{
  "event": "status.updated",
  "data": {
    "session_id": "bs_01H...",
    "session_kind": "business",
    "previous_status": "IN_PROGRESS",
    "status": "APPROVED",
    "vendor_data": "biz-acme-001",
    "workflow_id": "wf_kyb_standard",
    "features": ["KYB_REGISTRY", "KYB_COMPANY_AML", "KYB_DOCUMENTS", "KYB_KEY_PEOPLE"],
    "decision": { ...abbreviated KYB decision payload... },
    "changed_at": "2026-04-18T12:30:00Z"
  }
}
The decision block contains the same shape as GET /v3/session/{id}/decision/registry_checks[], key_people_checks[], document_verifications[], aml_screenings[], etc.

data.updated — Business Verification (KYB) session

Fires when session data (registry, key people, documents, AML) changed without a status transition.
{
  "event": "data.updated",
  "data": {
    "session_id": "bs_01H...",
    "session_kind": "business",
    "vendor_data": "biz-acme-001",
    "changed_fields": ["registry_checks", "key_people_checks"],
    "updated_at": "2026-04-18T14:00:00Z"
  }
}
Use changed_fields to efficiently decide what to re-fetch.

business.status.updated

Fires when the Business entity moves between ACTIVE, FLAGGED, or BLOCKED.
{
  "event": "business.status.updated",
  "data": {
    "vendor_data": "biz-acme-001",
    "uuid": "f7a9c1b2-4e6d-4f8a-9c5d-2a1b3c4d5e6f",
    "status": "FLAGGED",
    "previous_status": "ACTIVE",
    "reason": "manual",
    "actor": "compliance@yourcorp.com"
  }
}

business.data.updated

Fires when the Business entity’s profile fields or aggregate counters change.
{
  "event": "business.data.updated",
  "data": {
    "vendor_data": "biz-acme-001",
    "uuid": "...",
    "legal_name": "Acme Corporation Limited",
    "registration_number": "12345678",
    "country_code": "GBR",
    "session_count": 2,
    "approved_count": 1,
    "declined_count": 0,
    "in_review_count": 1,
    "changed_fields": ["session_count", "approved_count", "features"]
  }
}

Signature verification

All webhooks are signed HMAC-SHA256 with your destination’s shared secret, sent in the X-Didit-Signature header. Verify the raw request body before acting. Example (Node.js):
import { createHmac, timingSafeEqual } from 'crypto';

function verifyWebhook(rawBody: string, signature: string, secret: string): boolean {
  const expected = createHmac('sha256', secret).update(rawBody).digest('hex');
  const provided = Buffer.from(signature);
  const computed = Buffer.from(expected);
  return provided.length === computed.length && timingSafeEqual(provided, computed);
}
Full details in the webhooks reference.

Retry policy

  • Non-2xx responses trigger retries with exponential backoff.
  • Up to 5 retries over ~24 hours.
  • Each retry gets a new X-Didit-Delivery header but the same event_id — de-duplicate on your side.
  • Repeated failures flip the destination to disabled.

Subscribing

Subscribe to the events you care about on a webhook destination:
curl -X POST https://verification.didit.me/v3/webhook/destinations/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "KYB events",
    "url": "https://yourapp.com/webhooks/didit-kyb",
    "subscribed_events": [
      "status.updated",
      "data.updated",
      "business.status.updated",
      "business.data.updated",
      "activity.created"
    ]
  }'
Filter for business sessions on your side by checking data.session_kind === "business" inside status.updated and data.updated events.

Next steps

Webhooks reference

Destinations, signing, retries, common patterns.

Statuses

Session and feature status reference.

Response schema

Decoding the KYB decision payload.