KYC Compliance Flow
This guide explains how to integrate the KYC compliance system using both webhooks (push) and the Compliance Status API (pull).
Overview
The KYC system provides two complementary mechanisms:
- Webhooks (Push): Real-time notifications when KYC state changes
- Compliance Status API (Pull): On-demand status with actionable guidance
Use webhooks for real-time updates; use the API to get current state and determine next steps.
Webhook Events
Subscribe to these events via the Webhook API:
| Event | When it fires | What it means |
|---|---|---|
CUSTOMER_KYC_STARTED | POST /v1/compliance/kyc called | KYC process initiated |
CUSTOMER_KYC_SDK_FLOW_REQUIRED | SDK links generated | User needs to complete identity verification |
CUSTOMER_KYC_SDK_FLOW_COMPLETED | User finishes SDK | Identity verification submitted |
CUSTOMER_KYC_FINISHED | Final outcome reached | KYC approved or denied (check status field) |
CUSTOMER_KYC_RESTARTED | POST /v1/compliance/kyc/:id/rerun | KYC re-run, new onboarding created |
CUSTOMER_KYC_SDK_EXPIRED | SDK links expire | Links expired before user completed |
CUSTOMER_KYC_ERROR | Verification error | System error during verification |
Webhook Payload
{
"eventType": "CUSTOMER_KYC_SDK_FLOW_COMPLETED",
"data": {
"customerId": "uuid",
"status": "APPROVED",
"onboardingId": "uuid"
}
}
For CUSTOMER_KYC_RESTARTED, also includes previousOnboardingId.
Compliance Status API
Endpoint: GET /v1/compliance/status/:customerId
Returns actionable compliance data without requiring message parsing.
Response Structure
{
"isCompliant": false,
"onboardingStatus": "PROCESSING",
"nextAction": "UPLOAD_DOCUMENT",
"checks": [
{
"type": "KYC_STATUS",
"passed": false,
"required": true,
"suggestedAction": "UPLOAD_DOCUMENT"
},
{
"type": "DOC_SOURCE_OF_FUNDS",
"passed": false,
"required": true,
"suggestedAction": "UPLOAD_DOCUMENT"
},
...
],
"summary": {
"passed": 8,
"failed": 2,
"requiredFailed": ["KYC_STATUS", "DOC_SOURCE_OF_FUNDS"]
}
}
Suggested Action Values
| Action | What to do |
|---|---|
START_KYC | Initiate KYC |
COMPLETE_SDK_FLOW | User must complete identity verification SDK |
UPLOAD_DOCUMENT | Upload required document via API |
UPDATE_PROFILE | Update customer profile data |
RERUN_KYC | Rerun KYC |
WAIT | No user action needed - system processing (e.g., SDK done, docs uploaded, awaiting approval) |
CONTACT_SUPPORT | Terminal failure, verification error, or denied - requires support |
Check Types
| Check | Description |
|---|---|
KYC_DATA_PRESENT | Customer has KYC data submitted |
KYC_STARTED | KYC process initiated |
SDK_VERIFICATION_COMPLETED | Identity verification SDK completed |
KYC_STATUS | Overall KYC approved/denied |
REGISTRATION_ADDRESS | Registration address on file |
TAX_COUNTRY | Tax country specified |
OCCUPATION | Occupation registered |
DOC_SOURCE_OF_FUNDS | Source of funds document |
DOC_FATCA | W9/W8BEN document |
DOC_BIOMETRIC_REPORT | Biometric verification report (only required for clients that run their own KYC) |
DOC_PROOF_OF_ADDRESS | Proof of address document (only required when no IP Address is set for said customer) |
Complete Integration Flow
┌─────────────────────────────────────────────────────────────────────────────┐
│ PHASE 1a: Customer Creation (without KYC data) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Client API Webhook │
│ │ │ │ │
│ │──POST /v1/customers──────────▶│ │ │
│ │◀──────────────────────────────│ │ │
│ │◀────────────────────────────────────────────CUSTOMER_CREATED─│ │
│ │ │ │ │
│ │──GET /compliance/status──────▶│ │ │
│ │◀──────────────────────────────│ │ │
│ │ KYC_DATA_PRESENT: false │ │ │
│ │ nextAction: UPDATE_PROFILE │ │ │
│ │ │ │ │
│ │──PATCH /v1/customers/:id─────▶│ (add KYC data) │ │
│ │◀────────────────────────────────────────────CUSTOMER_UPDATED─│ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ PHASE 1b: Customer Creation (with KYC data) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Client API Webhook │
│ │ │ │ │
│ │──POST /v1/customers──────────▶│ │ │
│ │◀──────────────────────────────│ │ │
│ │◀────────────────────────────────────────────CUSTOMER_CREATED─│ │
│ │ │ │ │
│ │──GET /compliance/status──────▶│ │ │
│ │◀──────────────────────────────│ │ │
│ │ KYC_DATA_PRESENT: true │ │ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────────────┐
│ PHASE 2: KYC Initiation │
├────────────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Client API Webhook │
│ │ │ │ │
│ │──GET /compliance/status──────▶│ │ │
│ │◀──────────────────────────────│ │ │
│ │ KYC_DATA_PRESENT: true │ │ │
│ │ KYC_STARTED: false │ │ │
│ │ nextAction: START_KYC │ │ │
│ │ │ │ │
│ │──POST /v1/compliance/kyc─────▶│ │ │
│ │◀──────────────────────────────│ │ │
│ │ { sdk: { link, qrCode } } │ │ │
│ │◀───────────────────────────────────────────────────────CUSTOMER_KYC_STARTED─│ │
│ │◀─────────────────────────────────────────────CUSTOMER_KYC_SDK_FLOW_REQUIRED─│ │
│ │ │ │ │
│ │ Display SDK link/QR to user │ │ │
│ │
└────────────────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ PHASE 3: User Completes SDK │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Client API Webhook │
│ │ │ │ │
│ │ (User completes SDK flow) │ │ │
│ │ │ │ │
│ │◀──────────────────────────────────CUSTOMER_KYC_SDK_FLOW_DONE─│ │
│ │ │ │ │
│ │──GET /compliance/status──────▶│ │ │
│ │◀───────────────────────────── │ │ │
│ │ SDK_VERIFICATION_COMPLETED: ✓│ │ │
│ │ KYC_STATUS: false │ │ │
│ │ DOC_SOURCE_OF_FUNDS: false │ │ │
│ │ DOC_FATCA: false │ │ │
│ │ nextAction: UPLOAD_DOCUMENT │ │ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ PHASE 4: Document Upload │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Client API Webhook │
│ │ │ │ │
│ │──POST /compliance/upload-doc─▶│ (Source of Funds) │ │
│ │◀──────────────────────────────│ │ │
│ │ │ │ │
│ │──POST /compliance/upload-doc─▶│ (W9 or W8BEN) │ │
│ │◀──────────────────────────────│ │ │
│ │ │ │ │
│ │──GET /compliance/status──────▶│ │ │
│ │◀──────────────────────────────│ │ │
│ │ All DOC_* checks: ✓ │ │ │
│ │ KYC_STATUS: false │ │ │
│ │ nextAction: WAIT │ (processing, docs present) │ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────── ─────────────────────────────────────────────┐
│ PHASE 5: KYC Approved │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Client API Webhook │
│ │ │ │ │
│ │◀─────────────────────────────────CUSTOMER_KYC_FINISHED───────│ │
│ │ │ (status: APPROVED) │ │
│ │ │ │ │
│ │──GET /compliance/status──────▶│ │ │
│ │◀──────────────────────────────│ │ │
│ │ isCompliant: true │ │ │
│ │ nextAction: null │ │ │
│ │ │ │ │
│ │ Customer ready for │ │ │
│ │ virtual account creation │ │ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Edge Case Flows
SDK Expired
Webhook: CUSTOMER_KYC_SDK_EXPIRED
│
▼
GET /compliance/status
│
├─ SDK_VERIFICATION_COMPLETED: false
└─ nextAction: RERUN_KYC
│
▼
POST /compliance/kyc/:onboardingId/rerun
│
▼
Webhook: CUSTOMER_KYC_RESTARTED
│
▼
(Flow continues from Phase 2)
KYC Denied
Webhook: CUSTOMER_KYC_FINISHED (status: DENIED_COMPLIANCE)
│
▼
GET /compliance/status
│
├─ onboardingStatus: DENIED_COMPLIANCE
├─ KYC_STATUS: false
└─ nextAction: CONTACT_SUPPORT
│
▼
Contact Connect Financial support
Verification Error
Webhook: CUSTOMER_KYC_ERROR
│
▼
GET /compliance/status
│
├─ SDK_VERIFICATION_COMPLETED: false
└─ nextAction: CONTACT_SUPPORT
│
▼
Contact Connect Financial support
Under Review
When identity verification requires manual review by our compliance team, the system enters a "pending review" state.
Webhook: CUSTOMER_KYC_SDK_FLOW_COMPLETED
│
▼
GET /compliance/status
│
├─ SDK_VERIFICATION_COMPLETED: false (pending review, not yet completed)
├─ KYC_STATUS: false (awaiting decision)
└─ nextAction: WAIT
│
▼
Wait for review completion:
- Poll /compliance/status periodically
- Or await CUSTOMER_KYC_FINISHED webhook
│
▼
Review outcome:
- APPROVED → CUSTOMER_KYC_FINISHED (status: APPROVED)
- DENIED → CUSTOMER_KYC_FINISHED (status: DENIED_COMPLIANCE)
Important: During manual review, SDK_VERIFICATION_COMPLETED remains false because the verification is not yet complete as it's awaiting human decision. The nextAction: WAIT indicates no user action is required.