Skip to main content
This guide is the companion to the quickstart. It covers the architecture, every integration decision, and the operational patterns that make KYB reliable in production.

Architecture

Authentication

All requests require the x-api-key header with your application’s API key. See API authentication for key rotation, environment separation, and scopes.

Session creation

Single endpoint: POST /v3/session/. The workflow’s type determines whether the session is KYC or KYB — no explicit “business” flag is needed. Recommended fields on creation:
FieldPurpose
workflow_idRequired — references your KYB workflow.
vendor_dataYour identifier for the business. Binds the session to a Business entity.
callback_urlOptional — where to redirect the user after completion.
expected_countryOptional — pre-selects country of incorporation.
metadataOptional JSON attached to the session.
Full schema: create session. The response url is a hosted verification link. Options for delivery:
  • Email it from your own platform.
  • Embed it in your onboarding UI as a link.
  • Open it in an in-app webview (iOS / Android / React Native).
You can customize the hosted experience — logo, color, domain, email templates — via White-label.

Polling vs webhooks

Webhooks are the recommended pattern. Didit POSTs completion events to your subscribed endpoint as soon as processing finishes. Polling is supported for development or when your webhook endpoint is unreachable:
  • Poll GET /v3/session/{id}/decision/ with exponential backoff (every 10s initially, up to 60s).
  • Stop polling when status is one of APPROVED, DECLINED, IN_REVIEW.
Polling at high frequency may hit rate limits. Always prefer webhooks in production.

Webhook handling

Subscribe to the events you care about — the same events cover both KYC and KYB, with session_kind: "business" inside the payload to identify business-session events:
  • status.updated — session status changed. Filter on data.session_kind === "business" for KYB sessions.
  • data.updated — session data changed (registry refresh, key-people submission, documents, ongoing AML). Same session_kind filter applies.
  • business.status.updated / business.data.updated — the linked Business entity changed.
Full event catalog: KYB webhooks. Signature verification and retry semantics: webhooks reference.

Handling decisions

switch (decision.status) {
  case 'APPROVED':
    await onboardBusiness(decision);
    break;
  case 'DECLINED':
    await logRejection(decision.decision_reason_code, decision);
    break;
  case 'IN_REVIEW':
    // Wait for analyst decision — another webhook will fire
    await markPending(decision);
    break;
  case 'RESUBMITTED':
    // The business was asked to re-upload a document
    await notifyBusiness(decision);
    break;
}
See KYB statuses for the full state machine and reason codes.

Resubmission flow

When a Business Verification (KYB) session transitions to RESUB_REQUESTED (or a feature is marked for resubmission), the business needs to upload corrected or additional data. You can:
  • Re-deliver the same url — the hosted flow picks up where resubmission is needed.
  • Open a case in the Business Console to track the back-and-forth internally.

Business profile aggregation

If you pass vendor_data on session creation, Didit aggregates all sessions for that business into a single Business entity. Use the entity’s features map to answer “is this business fully verified right now?” without iterating sessions. Benefits:
  • Periodic re-KYB flows append to the same profile.
  • Transactions monitored against the same vendor_data carry the business’s risk context.
  • UBOs and officers linked to User entities populate cross-entity relationships.

Best practices

PracticeWhy
Always pass vendor_dataWithout it, the session is orphaned and can’t be aggregated.
Use webhooks, not pollingLower latency, no rate limit pressure.
Verify webhook signaturesPrevents spoofed events.
Store the session_id on your sideNeeded to retrieve the decision and generate PDFs.
Tag sessions with metadataSimplifies reporting and debugging.
Set up a test workflowUse a sandbox workflow for integration testing before production.

Error handling

ScenarioResponse
Invalid workflow_id400 Bad Request
Duplicate session with same vendor_dataCreates a new session — that’s by design, since re-verification is expected.
Dangerous countrySession is created but immediately DECLINED with reason blocked_country.
Blocklisted vendor_dataSession auto-declined with reason blocked_business.
Rate limit429 Too Many Requests with Retry-After header.
Full rate limiting reference.

Next steps

Webhooks

Every KYB event and payload.

Statuses

State machine reference.

Response schema

Decoding the KYB decision.

Troubleshooting

Common issues and fixes.