Workflows API
The Workflows API lets you send DDQ questionnaires, identity verification requests, or both to an entity in a single API call, mirroring the full flow available in the KYC Genie web interface.
Under the hood, every send creates an OnboardingSession — a secure magic-link session that lets the entity access their DDQ, complete identity verification, or both, without needing a KYC Genie account.
The existing POST /responses/ endpoint creates a
response object but uses an older email delivery path. The Workflows API uses
the OnboardingSession system — the same infrastructure the web UI uses — giving
you magic-link delivery, combined DDQ + verification flows, and a richer response
payload including the session ID and expiry timestamp.
Two Delivery Paths
Choose which path fits your integration:
| Path | How to trigger | What happens |
|---|---|---|
| Direct send | ddq.prefill: false (default) |
Entity + Response (DRAFT) + optional Verification Session created,
workflow generated, magic-link email dispatched immediately,
send_ddq credit charged.
|
| Prefill → Send | ddq.prefill: true |
Response created in PREFILL status only.
No email, no credit charge. You fill the form via
PUT /responses/{id}/save/, then call
POST /responses/{id}/send/ when ready.
All verification config is stored on the response and dispatched automatically
at send time.
|
Workflow Response Object
Both POST /workflows/send/ and
POST /responses/{id}/send/ return the same object.
| Field | Type | Description |
|---|---|---|
workflow_session_id |
uuid | null |
ID of the workflow session created. null
on the prefill path (no session until
/send/ is called).
|
status |
string |
sent — email dispatched, credits charged.prefill_ready — PREFILL response created; send
later via POST /responses/{id}/send/.
|
email_sent |
boolean |
true if the workflow email was dispatched
in this request.
|
entity_id |
uuid | ID of the entity (existing or newly created). |
entity_name |
string | Display name of the entity. |
response_id |
uuid | null | ID of the created Response. null if no DDQ block was included. |
verification_session_id |
uuid | null |
ID of the created VerificationSession.
null if verification was not included,
or if this is a prefill response (the session is created at send time).
|
steps |
array |
Steps included in the session, e.g.
["ddq"],
["verification"], or
["ddq", "verification"].
|
expires_at |
datetime | null | UTC datetime when the workflow magic link expires. null on the prefill path. |
Send Workflow
Creates an entity (or uses an existing one), optionally creates a DDQ response and/or identity verification session, and dispatches a magic-link workflow email.
/api/v1/workflows/send/
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id |
uuid | Conditional |
ID of an existing entity. Mutually exclusive with the
entity block — provide exactly one.
|
entity |
object | Conditional |
Inline entity creation. Mutually exclusive with
entity_id. See
Entity Block below.
|
ddq |
object | Conditional* |
DDQ block. Include to send a questionnaire. See
DDQ Block below. At least one of
ddq or
verification must be provided.
|
verification |
object | Conditional* |
Verification block. Include to request identity verification.
Requires entity_type: individual. See
Verification Block below.
|
email |
string | Conditional |
Email address to deliver the workflow link to. Required unless
ddq.prefill is
true.
|
expiry_hours |
integer | No | Hours until the workflow magic link expires (1-168). Defaults to your tenant's configured setting (typically 48 h). |
Entity Block
Used when creating a new entity inline. If you already have an entity, pass
entity_id instead.
| Field | Type | Required | Description |
|---|---|---|---|
entity_type |
string | No |
company (default) or
individual
|
legal_name |
string | Required for company | Official registered name of the company |
trading_name |
string | No | Trading / DBA name (companies only) |
first_name |
string | Required for individual | First name (individuals only) |
last_name |
string | Required for individual | Last name (individuals only) |
email |
string | No | Entity's email address (stored on the entity record) |
phone |
string | No | Phone number |
jurisdiction |
string | No | ISO-3166-1 alpha-2 country code (e.g. GB) |
DDQ Block
| Field | Type | Required | Description |
|---|---|---|---|
questionnaire_id |
integer | Yes | ID of the DDQ template to use (must belong to your tenant) |
response_name |
string | No | Display name for the response. Auto-generated as "{entity name} – {questionnaire name}" if omitted. |
prefill |
boolean | No |
Default false. When
true, creates a PREFILL response for you
to populate before sending. No email is sent and no credit is charged
until POST /responses/{id}/send/ is called.
|
Verification Block
The verification block requires the entity to be
entity_type: individual. Passing it with a company
entity returns a 400 error.
| Field | Type | Required | Description |
|---|---|---|---|
checks |
object | Yes |
Which verification checks to run. At least one must be
true. See
Checks Object below.
|
Verification Checks Object
| Field | Type | Description |
|---|---|---|
document |
boolean | Run a document check (passport, driving licence, etc.) |
identity |
boolean | Run a biometric selfie / liveness check |
enhancedIdentity |
boolean | Run an enhanced video identity check |
proofOfAddress |
boolean | Request a proof-of-address document upload |
API Response
Returns a Workflow Response Object with
status 201 Created.
Response — Direct Send (201 Created)
{
"workflow_session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "sent",
"email_sent": true,
"entity_id": "1b83f447-4a1e-4589-8a12-b8767e3c5426",
"entity_name": "Acme Corp",
"response_id": "d67177bf-6871-45bf-85f2-95a1e52ccc64",
"verification_session_id": null,
"steps": ["ddq"],
"expires_at": "2026-02-26T12:00:00Z"
}
Response — DDQ + Verification (201 Created)
{
"workflow_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "sent",
"email_sent": true,
"entity_id": "9c4e1b2d-3f5a-4e6b-8c7d-2a1b3c4d5e6f",
"entity_name": "Jane Smith",
"response_id": "770g0611-g40d-63f6-c938-668877662222",
"verification_session_id": "cc123456-7890-abcd-ef01-234567890abc",
"steps": ["ddq", "verification"],
"expires_at": "2026-02-26T12:00:00Z"
}
Response — Prefill Path (201 Created)
{
"workflow_session_id": null,
"status": "prefill_ready",
"email_sent": false,
"entity_id": "1b83f447-4a1e-4589-8a12-b8767e3c5426",
"entity_name": "Acme Corp",
"response_id": "d67177bf-6871-45bf-85f2-95a1e52ccc64",
"verification_session_id": null,
"steps": ["ddq"],
"expires_at": null
}
Error Responses
| Status | Description |
|---|---|
400 |
Validation error — missing required fields, both entity_id
and entity provided, no DDQ or verification block,
email missing on non-prefill path, or verification requested for a company entity.
|
404 |
Questionnaire not found or does not belong to your account. |
500 |
Email dispatch failed. The questionnaire response record is deleted and no credits are charged. Any entity record created by this request is retained. You may retry the request. |
Send a Prefill Response
Transitions a PREFILL response to
DRAFT, creates a verification session if
pending_verification_config was set, and
dispatches the workflow email. This is the second step of the
Prefill Workflow.
/api/v1/responses/{response_id}/send/
Path Parameters
| Parameter | Type | Description |
|---|---|---|
response_id |
uuid | ID of the PREFILL response to send |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
email |
string | Conditional | Email to deliver the workflow link to. If omitted, falls back to the email address stored on the entity. Required if the entity has no email on record. |
expiry_hours |
integer | No | Hours until the magic link expires (1-168). Defaults to your tenant's setting. |
When a PREFILL response is sent, any AI autofill source annotations and AI analysis data are removed before delivery. This ensures the recipient sees a clean form with no internal metadata visible. The answer text itself is preserved.
API Response
Returns a Workflow Response Object with
status 200 OK.
Response (200 OK)
{
"workflow_session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "sent",
"email_sent": true,
"entity_id": "1b83f447-4a1e-4589-8a12-b8767e3c5426",
"entity_name": "Acme Corp",
"response_id": "d67177bf-6871-45bf-85f2-95a1e52ccc64",
"verification_session_id": null,
"steps": ["ddq"],
"expires_at": "2026-02-26T12:00:00Z"
}
Error Responses
| Status | Description |
|---|---|
400 |
Response is not in PREFILL status, or no email address is available (provide one in the request body). |
404 |
Response not found or does not belong to your account. |
500 |
Email dispatch failed. The response is reverted to PREFILL status and no credits are charged. You may retry. |
Prefill Workflow
The prefill workflow lets you populate a questionnaire on behalf of the entity before they see it. Use it when you have existing data or documents that you want to pre-load into the form.
-
Create a PREFILL response via
POST /workflows/send/withddq.prefill: true. You receive aresponse_id. No email is sent. -
(Optional) Autofill from documents via
POST /responses/{id}/autofill/. The AI reads entity documents and fills answers automatically. Monitor completion via theresponse.autofill_completedwebhook. -
(Optional) Fill answers manually via
PUT /responses/{id}/save/. You can combine this with autofill. -
Send to the entity via
POST /responses/{id}/send/. The response transitions to DRAFT, a workflow session is created, the magic-link email is dispatched, andsend_ddqcredits are charged.
To include identity verification in a prefill workflow, pass the
verification block when creating the
PREFILL response. The check configuration is stored and dispatched
automatically when POST /responses/{id}/send/
is called — you do not need to pass it again at send time.
Credits
| Action | Charged? |
|---|---|
Direct send (POST /workflows/send/ — non-prefill) |
Yes — one send credit, charged after email succeeds |
| Creating a PREFILL response | No |
POST /responses/{id}/send/ |
Yes — one send credit, charged after email succeeds |
If the email delivery fails, the response object is rolled back and no credits are charged. You will receive
a 500 error and can safely retry.