Create Workflow
Create a simple workflow. Send features in execution order (ordering rules apply); defaults to published v1. The body accepts ONLY the fields listed in SimpleWorkflowRequest — any other key (including workflow_type) is rejected with a 400. Not idempotent — each call creates a new workflow. Maximum 50 workflows per application.
features array in the order users should complete the checks. Didit converts it into a node-based workflow internally and adds the final status step automatically.
This POST /v3/workflows/ endpoint creates simple, linear workflows only — a flat features list. For branching, conditional routing, Document AI, and decline/decision nodes, use the node graph format documented below (it powers the visual builder in the console and the Didit MCP workflow tools).
See Workflow Feature Configs for every config field accepted by each feature.
Basic KYC workflow
Questionnaire workflow
First create the questionnaire withPOST /v3/questionnaires/. Then use the returned questionnaire_id as questionnaire_uuid.
OCR before FACE_MATCH, NFC, DATABASE_VALIDATION, or user AML checks that depend on document data.
Feature config reference
Eachfeatures[] item has this shape:
config object depends on the feature. Review the full field list, defaults, required settings, value ranges, and examples in Workflow Feature Configs.
For OCR, omit config.documents_allowed, send null, or send {} to allow every supported document type. Include it only when you want to restrict the workflow to specific countries or document types. For QUESTIONNAIRE, config.questionnaire_uuid is required.
Optional workflow settings
You can include any of these top-level fields when creating a workflow to control session behavior. They are all optional and fall back to the workflow defaults when omitted.Branching & node-based workflows (graph)
A linearfeatures list can’t express “if X then Y.” For conditional branching (decline on a status, route on an extracted field, gate a step on a match), a Document AI request step, or terminal decline/decision nodes, Didit workflows use a node graph — the same structure the console’s visual builder produces.
Graph shape
A graph is{ start_node, nodes }. nodes is a map of node id → node. Edges are implicit: each node points forward via next (unconditional) and/or branches[].goto (conditional).
start_node must be a feature node. Branches are evaluated in order, first match wins; an empty rules: [] is the catch-all “else” (keep it last). session_status: "Determine" auto-decides from the combined feature outcomes.
Branch rules & operators
Each rule compares a field to a value with an operator:- Fields name a feature outcome (
kyc.status,aml.status,document_ai.status,face_match.score, …) or an extracted value (kyc.full_name,kyc.age,kyc.nationality,kyc.extra_fields.profession, a Document-AI fielddocument_ai.<key>,expected_details.*). A branch may only read a field whose feature has run on every path reaching it. - Operators:
equals,not_equals,greater_than(_or_equals),less_than(_or_equals),contains,not_contains,in,not_in,is_empty,is_not_empty,regex, andfuzzy_match(string fields only; requires ascore0–100 — a similarity threshold, e.g. profession ≥ 80% similar to “Software Engineer”).
Document AI (e.g. proof of funds)
ADOCUMENT_AI feature node requests one or more documents and extracts named fields:
document_ai.<key>, and the step’s outcome is document_ai.status.
Set "is_full_name": true on the field that holds the document holder’s full name. Its extracted value is compared against the verified identity’s full name (the OCR/ID-verification name, or the session’s expected details), and document_ai_name_mismatch_action decides what happens on a mismatch below document_ai_name_match_score_threshold. The flag is optional — a document may mark no field — and at most one field per document may set it. See Workflow feature configs → Document AI for every Document AI config field.
Endpoints & draft lifecycle
Graph editing is per-application and uses the console/management endpoints (user-Bearer +read:workflows/write:workflows). A graph can only be edited on a draft version, so the lifecycle is create-draft → set graph → publish:
Worked example: route Software Engineers to proof of funds
After ID verification: if it was declined, decline the session; if the holder’s profession ≈ “Software Engineer” (≥80% similar), request a proof-of-funds document; then make a final decision.
session_status: "Determine", which auto-decides (approve / decline / in-review) from whatever features actually ran on the session — so both the proof-of-funds path and the else path resolve correctly without any branch reading document_ai.status (which doesn’t exist on the path that skips Document AI). Remember: a branch may only read a field whose feature ran on every path reaching it.
Send it as { "graph": <above> } to the …/workflow-graph/ endpoint (validate first). To build a new workflow from scratch use the MCP’s didit_workflow_set_graph; to modify an existing workflow use didit_workflow_edit_graph (small ops, preserves the existing nodes and allow-lists). See the Didit MCP.Authorizations
Body
Create a simple linear workflow. The API converts this feature list into a node-based workflow graph internally. STRICT field whitelist: any key not listed here (including workflow_type) is rejected with a 400.
Verification features in execution order. The API links each item to the next one and adds one final status node automatically.
1Display name for the workflow (max 50 characters). Defaults to "ID Verification" when omitted — always set it so workflows stay distinguishable.
50"Standard KYC"
Set this workflow as the default for new sessions.
Omit this field to create a published workflow ready for sessions. Use draft only when you want to save without publishing.
draft, published Enable white-label customization for sessions created with this workflow.
Allow the verification flow to run on desktop browsers.
Maximum retry attempts allowed after a declined verification. 0 blocks the user after the first decline.
0 <= x <= 10Rolling window in days used to count retries. null enforces an all-time limit.
1 <= x <= 365Maximum liveness submissions per session. Default 3: one initial attempt plus two retries. This value is also copied into generated liveness and age-estimation workflow nodes unless the feature-level config overrides it.
1 <= x <= 3Maximum face-match submissions per session. Default 3: one initial attempt plus two retries. This value is also copied into generated face-match workflow nodes unless the feature-level config overrides it.
1 <= x <= 3Seconds before an unfinished session expires. Minimum 1 hour (3600), maximum 4 weeks (2419200).
3600 <= x <= 2419200Response
Workflow created. The response body is the FULL workflow configuration — the same raw VerificationSettings serialization returned by GET /v3/workflows/{settings_uuid}/ (~190 fields: every feature toggle, threshold, action and the generated workflow_graph), not the compact list item. Store the uuid (also exposed as workflow_id) so you can reference it from later session-creation calls. Note: features is a " + "-joined string and prices are JSON numbers.
Full workflow configuration (abbreviated here — see GET /v3/workflows/{settings_uuid}/).