Skip to main content

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:

  1. Register the customer.
  2. Start the workflow.
  3. Poll status until a node is waiting.
  4. Submit node data (OCR / particular / liveness / OTP / forms).
  5. 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" }
StatusMeaningAction
RUNNINGExecuting, no node waitingContinue polling (2–5 sec)
WAITINGNode waiting for inputRead currentNode, submit data
COMPLETEDWorkflow finishedStop polling, read result
FAILEDExecution failedStop polling, contact support
TIMEOUTExceeded time limitStop polling, contact support
CANCELLEDExecution cancelledStop polling

4. Submit node data

When status is WAITING, dispatch on currentNode.nodeType:

nodeTypeAPIPurpose
flow_action_identity_documentworkflow.kyc.ocrUpload ID, get OCR result
flow_action_individual_particularworkflow.kyc.particular.dataSubmit personal info
flow_action_liveness_testworkflow.kyc.liveness.dataSubmit liveness status
flow_action_validate_emailworkflow.kyc.otp.send/verifyEmail OTP
flow_action_validate_phoneworkflow.kyc.otp.send/verifyPhone OTP
flow_action_individual_required_documentworkflow.kyc.required.docSupporting documents
flow_action_individual_required_formsworkflow.kyc.required.formForms / 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"
}