Know Your Customer (KYC) verification is required before a user can receive payments through Cadana. You submit identity documents and personal information via the API, and Cadana handles automated verification. This page covers the submission requirements, status tracking, and webhook events.
KYC Flow
| Status | Meaning | User can transact? |
|---|
not started | KYC has not been submitted | No |
processing | Documents submitted, verification in progress | No |
approved | Verification successful | Yes |
rejected | Verification failed — resubmission needed | No |
Most verifications complete automatically within minutes. If automated checks can’t verify the user’s identity, a manual review may take 1-2 business days.
Submit KYC
Submit identity information and documents for a user. Upload document images first using the file upload flow, then pass the returned fileId values.
curl -X POST 'https://api.cadanapay.com/v1/users/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/kyc' \
-H 'Authorization: Bearer YOUR_API_KEY'
Returns 204 on success. The user’s KYC status moves to processing.
| Field | API Field | Required | Rules |
|---|
| First name | firstName | Yes | Must match government-issued ID exactly |
| Last name | lastName | Yes | Must match government-issued ID exactly |
| Date of birth | dob | Yes | Format: YYYY-MM-DD |
| Nationality | nationality | Yes | 2-letter ISO country code (e.g., US, NG, KE) |
Identity Document
| Field | API Field | Required | Rules |
|---|
| Document type | idDetails.type | Yes | See supported types below |
| Document number | idDetails.number | Yes | Unique identifier on the document |
| Issuing authority | idDetails.issuedBy | Yes | Authority that issued the document |
| Issue date | idDetails.issuedDate | Yes | Format: YYYY-MM-DD |
| Expiration date | idDetails.expirationDate | Yes | Format: YYYY-MM-DD. Must not be expired |
| Issuing country | idDetails.issuedCountryCode | Yes | 2-letter ISO country code |
| Front of ID | idDetails.frontFileId | Yes | fileId from file upload |
| Back of ID | idDetails.backFileId | No | Required for driver’s licenses and some national IDs |
| Selfie | idDetails.selfieFileId | Yes | Photo of user holding the document |
Supported document types:
| Document | API Value |
|---|
| Passport | passport |
| Driver’s license | driver_license |
| National ID card | national_id |
| ID card | id_card |
| Voter ID card | voter_id_card |
Images must be clear and readable with all text visible. Supported formats: JPEG, PNG.
Address (Optional)
If provided, all required address fields must be completed.
| Field | API Field | Required |
|---|
| Street address | address.line1 | Yes |
| Address line 2 | address.line2 | No |
| City | address.city | Yes |
| State / Province | address.state | Yes |
| Postal code | address.postalCode | Yes |
| Country | address.countryCode | Yes (2-letter ISO code) |
An address proof document can be provided via addressProofFileId (utility bill, bank statement, or government document dated within the last 3 months).
Check KYC Status
Retrieve a user’s current KYC status.
curl -X GET 'https://api.cadanapay.com/v1/users/8ef9a712-cdae-4110-b1ea-9ba95abbee6e/kyc' \
-H 'Authorization: Bearer YOUR_API_KEY'
Response:
{
"userKyc": {
"firstName": "John",
"lastName": "Doe",
"identity": "approved",
"address": "not started",
"idDetails": {
"country": "US",
"type": "Drivers license"
}
}
}
Identity and address verification are tracked separately. A user needs at minimum identity: "approved" to receive payments. If a verification is rejected, the identityStatusReason or addressStatusReason field explains why.
Webhook Events
user.kyc.updated
Fired on every KYC status change — processing, approved, or rejected. The type field indicates which verification component changed.
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"eventType": "user.kyc.updated",
"version": "1.0",
"timestamp": 1765359752,
"data": {
"userId": "8ef9a712-cdae-4110-b1ea-9ba95abbee6e",
"status": "approved",
"type": "identity",
"tenantKey": "cad95193904"
}
}
| Field | Description |
|---|
userId | The user whose KYC status changed |
status | New status: processing, approved, or rejected |
type | Verification component: identity or address |
For rejected verifications, fetch the user’s KYC details with GET /v1/users/{userId}/kyc to see the failure reason.
user.kyc.expiry
Fired when a user’s identity document is approaching expiry or has expired.
{
"id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"eventType": "user.kyc.expiry",
"version": "1.0",
"timestamp": 1765359752,
"data": {
"userId": "8ef9a712-cdae-4110-b1ea-9ba95abbee6e",
"stage": "about-to-expire",
"documentType": "passport",
"expiryDate": "2026-03-15",
"tenantKey": "cad95193904"
}
}
| Stage | Meaning |
|---|
about-to-expire | Document expires within 30 days |
in-grace-period | Expired but within 60-day grace period — existing transactions continue, new ones may be restricted |
expired | Past grace period — user must re-verify |
See Events for all event types and payload details.
Handling Rejections
When KYC is rejected, the user needs to resubmit. Common rejection reasons:
| Reason | User action |
|---|
| Document expired | Submit valid, non-expired document |
| Image unreadable | Retake photo with good lighting |
| Document damaged | Submit undamaged document |
| Info mismatch | Verify name and DOB match the document exactly |
| Unsupported document | Submit an accepted document type |
To resubmit, call POST /v1/users/{userId}/kyc again with corrected information. The status resets to processing.
Next Steps