Update Session Status
Manually override the final decision of a KYC or KYB verification session. Set new_status to Approved or Declined to record a manual decision, or to Resubmitted to clear specific verification steps and let the user redo them through the same verification URL. The endpoint accepts both user (KYC) and business (KYB) session IDs.
Call it once a session has reached a reviewable state: the current status must be Approved, Declined, In Review, Kyc Expired, Abandoned, or Resubmitted. Sessions that are still Not Started, In Progress, or Awaiting User, or that ended as Expired, return 400. The new status must differ from the current one, and your API key’s organization needs the write:sessions permission. The eligible-state check runs before body validation, so an ineligible session returns the Wrong Current Status error even when the payload is also invalid.
For Resubmitted, pass nodes_to_resubmit to choose which workflow steps the user must redo, or omit it to auto-select existing feature attempts in a resubmittable state (Declined, In Review, Not Finished, Expired). Never-attempted features are not auto-selected — list them explicitly in nodes_to_resubmit, or the request returns 400 when no recorded attempt needs resubmission. Captured data for the selected steps is deleted, the steps are reordered to match the workflow graph, the session’s expiration window restarts, and the original verification URL becomes usable again. Backend-only steps (AML, DATABASE_VALIDATION, IP_ANALYSIS) at the head of the list run immediately without user interaction; if every resubmitted step is backend-only, the session re-finalizes within the same request. KYB_REGISTRY and KYB_KEY_PEOPLE cannot be resubmitted directly — resubmit the relevant child KYC sessions instead and the parent business session recomputes automatically.
Every successful call fires the status.updated webhook once the change commits and appends an activity entry — with actor attribution and your comment — to the session’s reviews, visible in Get Decision and in the console activity timeline. The user-profile aggregates linked to the session’s vendor_data update as well. Declining disables ongoing AML monitoring for the session; re-approving re-enables it (from Resubmitted, Declined, or Kyc Expired) when the workflow has monitoring turned on. Approving or declining a child KYC that belongs to a KYB key-people check recomputes the parent business session’s status. Set send_email: true (with email_address) to notify the user: a status notice for Approved/Declined, or a resubmission email containing the verification link and per-step reasons for Resubmitted.
The operation is intentionally not repeatable with the same value: re-sending the current status returns 400 (The new status is the same as the current status.), so accidental double-submissions are harmless. Authentication and permission failures both return 403 — this API never responds 401.
Session kind
This endpoint works identically for User Verification (KYC) and Business Verification (KYB) sessions. Didit looks up thesession_id in both tables; status-transition validation is model-agnostic (the same enum of statuses applies to both).
The response includes session_kind so your downstream logic can switch on the outcome kind.
Allowed transitions
You can move a session toAPPROVED, DECLINED, IN_REVIEW, or RESUBMITTED. The session’s current status must be one of: APPROVED, DECLINED, IN_REVIEW, KYC_EXPIRED, ABANDONED, or RESUBMITTED — otherwise the API returns a validation error.
Examples
- Approve a User Verification (KYC) session
- Decline a Business Verification (KYB) session
- Request resubmission
Permission
Requires thewrite:sessions privilege. The same privilege covers both kinds.
Related
- Verification statuses — status-machine reference.
- Retrieve session — fetch the decision after updating.
- Sessions overview — kind discrimination.
Authorizations
Path Parameters
UUID of the verification session to update. Accepts both user (KYC) and business (KYB) session IDs — the service resolves the ID across both session types.
"11111111-2222-3333-4444-555555555555"
Body
Target status. Approved and Declined record a final manual decision (each can also overturn the other). Resubmitted clears the selected steps and sends the session back to the user. Any other value returns 400.
Approved, Declined, Resubmitted "Approved"
Free-text reason for the change, stored on the session's review trail and returned in the reviews array of Get Decision. For example Duplicated user.
"All checks passed manual review"
Workflow steps the user must redo. Only acted on when new_status is Resubmitted. For Approved/Declined the entries are still schema-validated (an invalid feature value returns 400) but schema-valid entries are semantically ignored. If omitted, the server auto-selects existing OCR, Liveness, Face Match, POA, Phone, Email, AML, Database Validation, and Questionnaire attempts whose status is Declined, In Review, Not Finished, or Expired (NFC, IP analysis, age estimation, face search, and KYB document attempts are never auto-selected; non-face-match face attempts are selected as LIVENESS) — features the user never attempted (no recorded attempt) are NOT selected, so a session with zero attempts returns 400 ("No features found that need resubmission") even though nothing was approved; pass nodes_to_resubmit explicitly in that case. Steps are executed in workflow-graph order regardless of the order you send them. KYB_REGISTRY, KYB_KEY_PEOPLE, and the KYB alias are rejected with 400 — those parent checks recompute from their child KYC sessions.
Whether to email the user about the change. Requires email_address. For Approved/Declined the user receives a status notice; for Resubmitted the email includes the verification link and the per-step resubmission reasons.
false
Recipient for the notification email. Required when send_email is true — omitting it returns 400.
"user@example.com"
Language for the notification email. Accepts any string at schema level; unsupported codes silently fall back to English (en).
"en"
Response
Status updated. The response contains only the session_id — fetch the updated session via Get Decision. The status.updated webhook fires once the change commits.
UUID of the updated session.