Skip to main content
GET
cURL

KYC and KYB support

This endpoint works for both User Verification (KYC) and Business Verification (KYB) sessions. The response always includes a top-level session_kind field:
  • "user" — User Verification (KYC) session. Response carries id_verifications, liveness_checks, face_matches, nfc_verifications, poa_verifications, database_validations.
  • "business" — Business Verification (KYB) session. Response carries registry_checks, document_verifications, key_people_checks.
Both kinds share aml_screenings, phone_verifications, email_verifications, questionnaire_responses, ip_analyses, document_ai_documents, bank_verifications, reviews, contact_details — plus the common top-level fields (session_id, session_number, session_url, status, workflow_id, vendor_data, metadata, callback, features, expected_details, created_at, expires_at). Didit resolves the session_id against both session types (User Verification first, Business Verification second) and returns whichever matches. UUIDs are unique per application — no ambiguity. See sessions overview for the full matrix of kind-specific features.

Examples

Response (truncated):

Handling the response on your side

Status, decision trace and review fields

Every decision explains how its status was reached.

Biometric data retention

biometric_retention is always present. deletes_at is the date the live biometric data of the session is deleted, and jurisdictions lists the US states whose biometric rules set a deletion limit for the person (US when the state is unknown). deletes_at is null when no date applies yet.

Location verification

When the workflow has a Location verification step, the decision carries two arrays. geolocation_checks[] has one item per step: its accepted attempt, with the outcome, the coordinates and their accuracy, the checks against the IP location and the address on file, and the step’s warnings. geolocation_attempts[] lists every attempt of every step, oldest first, with when each was received. Workflows without the step return both as null. Every field and outcome is in the Location verification report.

Workflow routing events

?include=events adds the session’s event timeline. Alongside the step and status changes, a workflow that routes through branch nodes leaves one event per routing decision, so an integration (or the Console timeline) can explain why a session ended on a given outcome without replaying the workflow graph by hand: Both events carry sent_at in milliseconds like every other event and have no component, feature_step or step: they come from the workflow engine, not from the user’s device. An “else” branch (a branch with no conditions) counts as a matched branch; fallback is only true when nothing matched. Nodes with a single outgoing edge make no decision and leave no event. The same shape also reports workflow_terminal_node_id: the node_id of the last recorded workflow status node that set a session status, or null if no such node ID has been recorded. This is historical workflow provenance. Manual approvals, declines and resubmissions do not clear it; a later workflow status node replaces it. For example, if a workflow sends a session to an In Review node and a reviewer later approves it, the current status is Approved while workflow_terminal_node_id still identifies the In Review node. It can also remain populated while a resubmission is in progress. Read the current status and the event and activity_reviews timelines to distinguish workflow outcomes from later manual decisions.

Earlier submissions (?include=resubmissions)

A resubmission sends the user back to the steps you select and keeps what those steps returned before. ?include=resubmissions adds a resubmissions array, oldest first, with one entry per resubmission request. Each entry carries the results that request replaced, so you can always read what the user submitted earlier. It works for user (KYC) and business (KYB) sessions, and you can combine it with events (?include=events,resubmissions). Without the parameter the response is unchanged. The current results (id_verifications and the rest at the top level) always describe the latest submission. Steps that were not sent back keep a single result there.
Deleting a session deletes the results of every submission with it.

ID Verification methods

Each id_verifications[] item says which of the three ID Verification methods produced it, so you can tell a document read apart from a register lookup or a wallet sign-in without guessing from the fields that happen to be populated: A document session reports document and documentary and leaves the rest null, so existing integrations need no change. Field-by-field types are in Data models. User Verification decisions carry a biometric_consent object: whether the session required explicit biometric consent, the trigger that required it, the status of the answer and its evidence. Two values tell you the consent was not collected: When the step appears and what each value means are in Biometric consent; every field is in Data models.

Bank verification

When the workflow has a Bank Verification step, the decision carries bank_verifications[], for both session kinds: one item per step, null until a step produces one. Read method, not ownership.method, to tell bank sign-in from the account check: ownership.method is the name comparison that produced the score. Every field is in the BankVerificationResult schema of this endpoint’s response.

E-signature

When the workflow has an E-signature step, the decision carries signatures[], for both session kinds. It has one item per signer: one for a User Verification, one per key person who signs for a Business Verification. Workflows without the step don’t return the key at all. Document selection is fixed when each signing attempt starts: a complete translation matching the signer language (or session language when unset), otherwise the original. Later edits or language changes do not replace that copy. Read language for the actual selected version, and require status: "signed" before treating it as signed. Download the files from the paths with your API key. See the E-signature report for every field.

Errors

Authorizations

x-api-key
string
header
required

Your application's API key, from Developers -> API keys in the Business Console. The primary key has full access. A named key can be scoped: none, read or write per resource, limited to some workflows or to approved sessions, to a list of IP addresses, and to an expiry date. 401 means the key is wrong, revoked or expired; 403 means no key was sent, the key has no access to this resource or action, or the request came from an address outside its IP list; 404 on a session route means the session is outside the key's workflows or statuses. A key without media access receives image, video and PDF URLs as null, and a key without sessions write receives session links and tokens as null. See https://docs.didit.me/console/api-keys.

Path Parameters

sessionId
string<uuid>
required

UUID of the verification session whose decision you want to retrieve. This is the session_id returned by POST /v3/session/. The same path works for both User Verification (KYC) and Business Verification (KYB) sessions — the server resolves the id against both session types.

Must be a valid UUID. The route only matches well-formed UUIDs, so a malformed value is rejected by the URL router before any application code runs and the response is a 404 HTML page rather than the JSON {"detail": ...} envelope shown below. Validate the UUID format client-side so you can distinguish an input error from a genuine missing-session 404.

Example:

"11111111-2222-3333-4444-555555555555"

Query Parameters

include
enum<string>

Comma-separated list of extra payload sections. Supported values: events and resubmissions, alone or together (events,resubmissions). When include=events is passed, the response additionally contains the session event timeline (events, including the WORKFLOW_BRANCH_EVALUATED / WORKFLOW_STATUS_NODE_REACHED routing events described on the Retrieve Session page), the full activity log (activity_reviews), blocklist flags (blocklisted), a per-session cost_breakdown, workflow metadata (workflow_type, workflow_version, workflow_version_id, and workflow_terminal_node_id - the last recorded workflow status node that set a session status, or null if none has been recorded; historical provenance that is not cleared by manual approvals, declines or resubmissions, and is replaced by a later workflow status node), and session metadata (api_service — string or null, set only for standalone-API sessions; session_type — API, HOSTED, or MIGRATED; has_device_nfc_support — boolean). Two fields change relative to the plain shape: the top-level session_kind discriminator is omitted (the events shape only exists for user sessions), and the features array switches from plain strings to {feature, node_id} objects — where the email feature is reported as EMAIL instead of EMAIL_VERIFICATION. This expanded shape is primarily used by the Didit Console; most API integrations should omit the parameter. KYB limitation: include=events only applies to user (KYC) sessions. Business sessions (session_kind = "business") always return the standard business decision shape — events, activity_reviews, blocklisted, cost_breakdown and the extra workflow_*/session metadata are never returned for business sessions, and their features array stays a plain string array. With include=resubmissions (user and business sessions alike) the response also contains resubmissions: one entry per resubmission request, oldest first, each with number, created_at, previous_status, nodes, reasons, requested_by and results (what the resubmitted steps returned before the request, under the same keys and in the same shape as the current results). Each cost_breakdown item carries usage_type, price, details and created_at: a resubmitted step that runs again is billed as a new item.

Available options:
events,
resubmissions,
events,resubmissions
Example:

"events"

Response

Full decision report. session_kind discriminates the two shapes: user sessions carry the KYC feature arrays shown below; business sessions instead carry registry_checks, document_verifications and key_people_checks alongside the shared arrays. Feature arrays are null until the workflow has run that feature; media URLs are short-lived presigned links.

session_id
string<uuid>

The unique identifier of the session.

session_kind
enum<string>

Discriminator indicating whether this is a User Verification (KYC) or Business Verification (KYB) session. When user, the KYC feature arrays (id_verifications, nfc_verifications, liveness_checks, face_matches, poa_verifications, document_ai_documents, database_validations, ...) apply and the business arrays are absent. When business, the payload instead carries registry_checks, document_verifications, key_people_checks plus the shared arrays (aml_screenings, phone_verifications, email_verifications, ip_analyses, questionnaire_responses). Omitted when include=events is passed — the events shape only exists for user sessions, so the discriminator is dropped from that variant.

Available options:
user,
business
shared_from_session
string<uuid> | null

For a session cloned with POST /v3/session/import-shared/: the session_id of the original session in the source application. null for every other session. Omitted when include=events is passed.

shared_from_session_number
integer | null

session_number of the source session when this session was imported from another application of your organization. null otherwise.

session_number
integer | null

The number of the session.

session_url
string<uri> | null

The URL of the session.

status
enum<string>

Overall lifecycle status of the session — the rolled-up workflow result. Terminal values are Approved, Declined, In Review, Expired, Kyc Expired, and Abandoned; Not Started, In Progress, Awaiting User, and Resubmitted indicate the session is still moving through the workflow.

Available options:
Not Started,
In Progress,
Awaiting User,
In Review,
Approved,
Declined,
Resubmitted,
Expired,
Kyc Expired,
Abandoned
status_override
object | null

Present when a reviewer set status by hand. null when the status is the automatic one. Use it to tell a manual approval from an automatic one.

decision_trace
object

How the status was reached: who set it and which warnings did.

linked_records
object | null

A summary of other records linked to the session. null when there is nothing to show, and for workflows that declare an age assurance standard.

workflow_id
string<uuid> | null

Stable identifier of the workflow group that produced this session. Workflows are versioned — this value identifies the workflow itself, not the specific version.

features
string[]

List of verification features configured for this session, as display names: ID_VERIFICATION, NFC, LIVENESS, FACE_MATCH, POA, PHONE, EMAIL_VERIFICATION, AML, IP_ANALYSIS, DATABASE_VALIDATION, QUESTIONNAIRE, AGE_ESTIMATION, FACE_SEARCH, GEOLOCATION (Location verification) (Business Verification sessions use the KYB feature set: KYB_REGISTRY, KYB_DOCUMENTS, KYB_KEY_PEOPLE, AML, PHONE, EMAIL_VERIFICATION, IP_ANALYSIS, QUESTIONNAIRE). With include=events each entry becomes an object {feature, node_id} instead of a plain string, and the email feature is renamed: it appears as EMAIL in events mode instead of the EMAIL_VERIFICATION used here.

The feature of the session.

vendor_data
string | null

The vendor data of the session.

metadata
object | null

The metadata of the session.

expected_details
object | null

Expected details supplied at session creation — used for cross-validation against extracted data (KYC) or to pre-fill the company registry search (KYB). Echoes back exactly the keys that were provided; null when none were supplied. KYC sessions carry the person fields; Business (KYB) sessions carry company_name, registry_country and registration_number.

contact_details
object | null

Contact details supplied when the session was created (used for notification emails, prefilled phone/email verification, and communication language). null when neither an email nor a phone number was provided.

callback
string<uri> | null

The callback URL of the session.

id_verifications
object[] | null

Array of ID verification (OCR) reports produced by ID-document steps in the workflow graph. Always a JSON array — read id_verifications[0] and iterate if your workflow can run more than one ID check (for example a primary check plus a step-up). null until at least one ID step has produced data. Each item is the full report, including node_id, feature-level status, extracted document fields, image URLs, quality scores, MRZ, address parsing, cross-session matches, and warnings[].

nfc_skip_reason
enum<string> | null

Why NFC chip verification did not run, populated whenever the workflow includes an NFC step. null while NFC is pending or when the chip was actually read. Values: USER_SKIPPED - the user chose to skip on an NFC-capable device (allowed by allow_nfc_skip); DOCUMENT_WITHOUT_CHIP - the document has no readable NFC chip (not an ICAO 9303 electronic document); CHIP_CERTIFICATE_UNAVAILABLE - the issuing country's signing certificate (CSCA) covering the document's issue period is unavailable, so the chip signature cannot be verified; DEVICE_WITHOUT_NFC - the device reported no NFC reader; INTEGRATION_WITHOUT_NFC_ACCESS - the verification ran without a native SDK (e.g. in a web browser), which has no access to the phone's NFC reader; MRZ_KEY_UNAVAILABLE - the chip access key could not be derived from the document's MRZ; JPKI_UNAVAILABLE - the document is a Japan My Number Card, whose chip is read through JPKI, and JPKI was not available for this verification: it is not enabled, or the app's native SDK cannot read My Number Cards.

Available options:
USER_SKIPPED,
DOCUMENT_WITHOUT_CHIP,
CHIP_CERTIFICATE_UNAVAILABLE,
DEVICE_WITHOUT_NFC,
INTEGRATION_WITHOUT_NFC_ACCESS,
MRZ_KEY_UNAVAILABLE,
JPKI_UNAVAILABLE
nfc_verifications
object[] | null

Array of NFC / ePassport reports produced by NFC steps in the workflow graph. This is always a JSON array, never a singular nfc object — read nfc_verifications[0] and iterate if your workflow can run NFC more than once. null until at least one NFC step has produced data. Each item is the full report, including node_id, feature-level status, chip_protocol, chip_data, authenticity (SOD + DG integrity), certificate_summary, and warnings[]. A Japan My Number Card is read through JPKI instead of ICAO 9303: its item has chip_protocol: "jpki", carries its evidence under jpki, and leaves the ICAO fields null. When the NFC step was bypassed before it could ever be offered (chipless document, missing certificate, no NFC capability reported, unreadable MRZ key, JPKI unavailable for a My Number Card), this stays null and nfc_skip_reason explains why; a skip at the step itself (user tapped skip, or the reader turned out unavailable at scan time) still produces a report with is_nfc_skipped: true.

liveness_checks
object[] | null

Array of liveness reports produced by liveness steps in the workflow graph. Always a JSON array — never a singular liveness object. null until at least one liveness step has produced data. Each item is the full report, including node_id, feature-level status, method, score, reference_image, video_url, optional age_estimation, cross-session matches[], and warnings[].

face_matches
object[] | null

Array of face-match reports produced by face-match steps in the workflow graph. Always a JSON array — never a singular face_match object. null until at least one face-match step has produced data. Each item is the full report, including node_id, feature-level status, similarity score, source_image, target_image, and warnings[].

phone_verifications
object[] | null

Array of phone verification reports — always a JSON array, never a singular phone object. null until at least one phone step has produced data. Each item is the full report, including node_id, feature-level status, the phone number and country metadata, lifecycle[], matches[], and warnings[].

email_verifications
object[] | null

Array of email verification reports — always a JSON array, never a singular email object. null until at least one email step has produced data. Each item is the full report, including node_id, feature-level status, the email address, breach data, lifecycle[], matches[], and warnings[].

poa_verifications
object[] | null

Array of Proof of Address (POA) reports — always a JSON array, never a singular poa object. null until at least one POA step has produced data. Each item is the full report, including node_id, feature-level status, the document file URL, issuer, dates, parsed address, and warnings[].

document_ai_documents
object[] | null

Document AI reports grouped by workflow node — always a JSON array, never a singular object. null until at least one Document AI step has produced data. Present only when session_kind = user. Each item is a node group with an aggregate status, the node_id, an items[] array of the per-document results (extracted data keyed by the configured field key), and warnings.

questionnaire_responses
object[] | null

Array of questionnaire response reports — always a JSON array, never a singular questionnaire object. null until at least one questionnaire step has produced data. Each item is the full report, including node_id, the questionnaire metadata, sections with form elements, and the user's answers.

bank_verifications
object[] | null

Bank Verification results, one item per Bank Verification step, for User and Business Verification. null until a step produces one. Each item's method says how the account was verified: open_banking (bank sign-in) or account_lookup (account check), or a statement or microdeposits fallback, and none when the person continued without a bank before any attempt was evaluated (continued_without_bank). See Bank verification methods.

signatures
object[]

E-signature results, one item per signer and signature step, for User and Business Verification. Present only when the workflow has an E-signature step; an empty array until a signer reaches it. See the E-signature report.

aml_screenings
object[] | null

Array of AML screening reports — always a JSON array, never a singular aml object. null until at least one AML step has produced data. Each item is the full report, including node_id, feature-level status, total_hits, entity_type, hits[], score, screened_data, is_ongoing_monitoring_enabled, and warnings[].

ip_analyses
object[] | null

Array of Device & IP Analysis reports — always a JSON array, never a singular ip_analysis object. null until at least one IP-analysis step has produced data. Each item is the full report, including node_id, feature-level status, IP and geolocation data, device fingerprint, and warnings[]. Entries with duplicate (node_id, ip_address, device_fingerprint) are deduplicated server-side.

geolocation_checks
object[] | null

Array of Location verification results, one per Location verification step: that step's accepted attempt. null until a Location verification step has produced data. Earlier attempts of the same step are in geolocation_attempts.

geolocation_attempts
object[] | null

Every attempt of every Location verification step of this session, oldest first. Attempts that a resubmission replaced are left out. A workflow that withholds geolocation_checks through its response attributes withholds this list too.

database_validations
object[] | null

Array of Database Validation reports — always a JSON array, never a singular database_validation object. null until at least one DB validation step has produced data. Each item is the full report, including node_id, feature-level status, screened_data, the per-service validations[] (each with its registry source_data), and warnings[]. The screened_data and source_data fields vary by country:

ARG (Argentina): screened_data: {document_number, selfie, gender, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name, date_of_birth, date_of_death, tax_id, tax_id_type, face_match_score, sit_1_since, banks, last_position, highest_position, rejected_checks}. Uses RENAPER biometric face-match validation. Gender is auto-inferred from face analysis or given name when not present in the document (e.g., driver licenses)

BOL (Bolivia): screened_data: {document_number, date_of_birth, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name, date_of_birth, gender}

BRA (Brazil): screened_data: {tax_number, first_name, last_name, date_of_birth}. source_data always includes {identification_number, first_name, last_name, date_of_birth, lgpd_minor, minor_under_18, minor_under_16} for successful CPF matches. Successful adult lookups set those flags to false. The Receita Federal Consulta CPF service may return HTTP 422 (minor under 18) or 451 (under 16) with LGPD-withheld data; in those cases source_data sets the minor flags to true as appropriate, includes the upstream HTTP status, and field-level validation is no_match. See the Brazil section of the Database Validation Outcome Codes reference for the full code list.

CHL (Chile): screened_data: {personal_number, first_name, last_name, date_of_birth}. source_data: {identification_number, first_name, last_name, date_of_birth, gender}

COL (Colombia): screened_data: {document_number, document_type, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name, date_of_birth, document_type}

CRI (Costa Rica): screened_data: {personal_number, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name}

DOM (Dominican Republic): screened_data: {personal_number}. source_data: {identification_number} (returns valid/invalid only)

ECU (Ecuador): screened_data: {personal_number, first_name, last_name}. source_data: {identification_number, first_name, last_name, street, formatted_address, gender, nationality, education, marital_status, spouse, mother_name, father_name, profession}

ESP (Spain): screened_data: {personal_number, document_type, expiration_date, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name, document_type, expiration_date}

GTM (Guatemala): screened_data: {document_number, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name}

HND (Honduras): screened_data: {document_number, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name}

MEX (Mexico): screened_data: {personal_number (CURP), first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name, date_of_birth, gender, nationality, curp_status, state_of_birth, doc_probatorio, registration_year, registration_state, registration_municipality, num_acta, crip, issuing_state_code, foreign_registry_number, folio_carta, folio_certificado}. Uses the RENAPO civil registry. A separate INE validity-check service is also available for MEX as an additional one-by-one validation.

PAN (Panama): screened_data: {personal_number, selfie}. source_data: {identification_number}. Uses SIB biometric validation

PER (Peru): screened_data: {personal_number (DNI), first_name, last_name}. source_data: {identification_number, first_name, last_name, paternal_name, maternal_name, verification_number, verification_letter}

PRY (Paraguay): screened_data: {document_number, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name}

SLV (El Salvador): screened_data: {document_number, date_of_birth, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name}

URY (Uruguay): screened_data: {personal_number, date_of_birth, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name}

VEN (Venezuela): screened_data: {document_number, first_name, last_name}. source_data: {identification_number, first_name, last_name, full_name, gender, date_of_birth, document_type}

database_validation_not_performed_reason
object | null

Why a configured database validation produced no result, as {code, message} plus context fields. Present only when database_validations is null for a workflow that has the step, so you can tell "the registry agreed" from "nothing ran". null otherwise.

reviews
object[]
assignee
object | null

The Console reviewer the session is assigned to, or null when nobody holds it.

waiting_since
string<date-time> | null

When the session started waiting for review. null unless the session is In Review and your application sets a review deadline.

sla_due_at
string<date-time> | null

When the review is due. null unless the session is In Review and your application sets a review deadline.

created_at
string<date-time>

Timestamp at which the session was created (ISO 8601, UTC).

expires_at
string<date-time> | null

Timestamp at which this session is scheduled to expire. Set on User Verification (KYC) sessions when an expiration was configured at creation time (or once Approved status triggers KYC expiry computation). null for sessions without a configured expiration, and for kinds that do not use expiry (e.g. Business Verification (KYB) sessions that never received an expires_at).

registry_checks
object[] | null

Company registry checks. Present only when session_kind = business. Each item wraps the full company-registry payload.

key_people_checks
object[] | null

Aggregate key-people checks. Present only when session_kind = business. Each item uses the two-bucket shape (registry, submitted, ubo_kyc_summary).

document_verifications
object[] | null

Document verification checks grouped by workflow node. Present only when session_kind = business.

environment
enum<string>

Whether the session was created by a live application (live) or a sandbox application (sandbox). Sandbox sessions are free, fully simulated, and never bill credits.

Available options:
live,
sandbox
sandbox_scenario
string | null

The sandbox scenario the session was created with. null for live sessions and for sandbox sessions created without one.

resubmissions
object[]

Returned only with include=resubmissions, for user and business sessions. One entry per resubmission request, oldest first. Each entry carries the results the resubmitted steps returned before the request, so earlier submissions stay readable. Deleting the session deletes every submission.

Whether the session required explicit biometric consent before a face capture, why, and the evidence of the answer. User Verification (KYC) sessions only; the same object is in the decision of session webhooks. null when the session was never evaluated, for example a workflow without a face capture. Fields with no recorded value are null. A native SDK below 4.10.0, or one that does not report its version, cannot show the consent step: its face captures run as before, and a session that required consent then reports status: "pending" with reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK". See Biometric consent.

investigator
object | null

The item's latest Investigator review, or null when it never had one. Carried by the V3 session and business session decision (and so by status.updated webhooks).

biometric_retention
object

When the live biometric data of this session is deleted.

fraud_check
object | null

The result of a Fraud Check API call. null for every other session.

full_session_video
string<uri> | null

Expiring URL of the full-session recording. Returned only when your organization records full-session video.

full_session_video_recorded_at
string<date-time> | null

When the full-session recording was made. Returned only when your organization records full-session video.

Last modified on November 11, 2026