KYC · Customer onboarding
Asynchronous workflow that drives individual customer onboarding: register the customer, start the workflow, poll for status, and submit data for each waiting node.
Flow overview
Standard KYC workflow:
- Register the customer.
- Start the workflow.
- Poll status until a node is waiting.
- Submit node data (OCR / particular / liveness / OTP / forms).
- Workflow completes or routes to manual review.
1. Register customer
Endpoint: workflow.applicant.register (POST).
{
"customerId": "C_abc123",
"email": "john@example.com"
}
At least one of customerId or email is required. This API is idempotent.
2. Start workflow
Endpoint: workflow.apply.submit (POST).
{
"eventType": "KYC_EVENT",
"source": "API",
"data": {
"customerId": "C_abc123",
"referenceId": "onboarding-uuid-001"
}
}
3. Poll status
Endpoint: workflow.execution.status (POST).
{ "executionId": "exec-abc123def456" }
| Status | Meaning | Action |
|---|---|---|
RUNNING | Executing, no node waiting | Continue polling (2–5 sec) |
WAITING | Node waiting for input | Read currentNode, submit data |
COMPLETED | Workflow finished | Stop polling, read result |
FAILED | Execution failed | Stop polling, contact support |
TIMEOUT | Exceeded time limit | Stop polling, contact support |
CANCELLED | Execution cancelled | Stop polling |
4. Submit node data
When status is WAITING, dispatch on currentNode.nodeType:
nodeType | API | Purpose |
|---|---|---|
flow_action_identity_document | workflow.kyc.ocr | Upload ID, get OCR result |
flow_action_individual_particular | workflow.kyc.particular.data | Submit personal info |
flow_action_liveness_test | workflow.kyc.liveness.data | Submit liveness status |
flow_action_validate_email | workflow.kyc.otp.send/verify | Email OTP |
flow_action_validate_phone | workflow.kyc.otp.send/verify | Phone OTP |
flow_action_individual_required_document | workflow.kyc.required.doc | Supporting documents |
flow_action_individual_required_forms | workflow.kyc.required.form | Forms / questionnaires |
flow_action_screen_check | (automatic) | AML / sanctions screening |
Identity document (OCR)
Submit: workflow.kyc.ocr (POST). Poll for OCR results at workflow.kyc.ocr.data after 2–5 seconds — OCR usually completes in 5–15 seconds.
{
"provider": "WIDTH",
"frontImage": "s3://workflow-kyc/.../front.jpg",
"backImage": "s3://workflow-kyc/.../back.jpg",
"documentType": "INTERNATIONAL_PASSPORT",
"region": "SG",
"executionId": "exec-abc123def456",
"callbackKey": "kyc:ocr:exec-abc123def456:...",
"referenceId": "onboarding-uuid-001"
}
Particular submission
Endpoint: workflow.kyc.particular.data.
{
"executionId": "exec-abc123def456",
"callbackKey": "kyc:particular:exec-abc123def456:...",
"referenceId": "onboarding-uuid-001",
"personData": "{\"name\":\"John Smith\",\"dateOfBirth\":\"1990-01-15\",\"nationality\":\"SG\",\"sex\":\"MALE\",\"countryOfResidence\":\"SG\",\"address\":\"123 Main St\"}"
}
personData is a JSON-encoded string, not a nested object. Call JSON.stringify() on the data before placing it in the request body.Liveness
Endpoint: workflow.kyc.liveness.data.
{
"provider": "SELF",
"status": "PASS",
"scores": "{\"qualityScore\":1.0,\"brightnessScore\":100,\"brightnessStatus\":\"normal\"}",
"images": "{\"faceFull\":\"s3://workflow-kyc/.../selfie.jpg\"}",
"executionId": "exec-abc123def456",
"callbackKey": "kyc:liveness:exec-abc123def456:...",
"referenceId": "onboarding-uuid-001"
}
Email / Phone OTP
Two steps: workflow.kyc.otp.send then workflow.kyc.otp.verify.
// send
{
"type": "email",
"identity": "john@example.com",
"executionId": "exec-abc123def456",
"callbackKey": "kyc:email:exec-abc123def456:...",
"referenceId": "onboarding-uuid-001"
}
// verify
{
"type": "email",
"identity": "john@example.com",
"code": "985024",
"executionId": "exec-abc123def456",
"callbackKey": "kyc:email:exec-abc123def456:...",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"referenceId": "onboarding-uuid-001"
}
Required documents
Endpoint: workflow.kyc.required.doc. After all docs are uploaded, call workflow.kyc.required.doc.submit to advance.
{
"doc": "{\"front\":{\"url\":\"s3://workflow-kyc/.../bill.pdf\",\"filename\":\"bill.pdf\",\"content_type\":\"application/pdf\",\"size\":85618}}",
"isRequired": true,
"docType": "UTILITY_TELEPHONE_BILL",
"extraData": "{\"issueDate\":\"2026-03-01\"}",
"executionId": "exec-abc123def456",
"callbackKey": "kyc:required_doc:exec-abc123def456:...",
"referenceId": "onboarding-uuid-001"
}
Required forms
Endpoint: workflow.kyc.required.form.
{
"formId": "IndividualForm",
"formData": "{\"field_source_of_funds\":\"EMPLOYMENT\",\"field_annual_income\":\"50000-100000\"}",
"executionId": "exec-abc123def456",
"callbackKey": "kyc:required_form:exec-abc123def456:...",
"referenceId": "onboarding-uuid-001"
}