Skip to main content
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

Most verifications complete automatically within minutes. pending means automated checks could not verify the user, so a reviewer has to decide — allow 1-2 business days for it to settle into approved or rejected.

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. Returns 204 on success. The user’s KYC status moves to processing.

Personal Information

Identity Document

Supported document types:
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. 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. Response:
Identity and address verification are tracked separately. A user needs at minimum identity: "approved" to receive payments. Note that address is the verification status of the address, while userAddress holds the address itself.

Identity document status

identityDocumentStatus reports where the user’s identity document sits in its expiry window. It is separate from identity, which is the verification result, and it is what tells you whether Renew an Expiring Document is available for this user. Renewal is accepted from about-to-expire onwards, so a platform that polls rather than waiting on the webhook can read this field to decide when to collect a replacement document. See When renewal is allowed.
An approved identity always carries a status, so an absent field means the user has not completed verification yet — not that something went wrong. Check identity to see where they are.

Timestamps

The six timestamp fields are formatted as YYYY-MM-DD HH:MM:SS +0000 UTC, always in UTC. This is not RFC 3339, so parse it with an explicit layout rather than a standard ISO 8601 parser. Any of these is an empty string when the corresponding event has not happened — for example, lastAddressSubmissionDate stays "" until the user submits an address.

Resubmit KYC

If a user’s identity or address verification is rejected, use the PATCH endpoint to resubmit corrected information. You can resubmit identity, address, or both in a single request. Resubmission rules:
At least one of identity or address must be provided. When a section is included, all of its fields are required.
PATCH is the rejection route. If the user’s identity document is simply expiring, you do not have to wait for it to be rejected — use Renew an Expiring Document to replace it while the verification is still approved.

Resubmit identity only

Resubmit address only

Returns 204 on success. Only the resubmitted section(s) move to processing — approved sections remain unchanged.

Renew an Expiring Document

Identity documents expire. When one does, the user’s verification eventually reverts to rejected and they stop being able to transact. The renewal endpoint lets you get ahead of that: submit a replacement identity document while the current verification is still good, without waiting for a rejection.
Renewal covers identity documents only. type is carried on the request so an address variant can be added later, but identity is the only value accepted today.
Returns 204 on success. Identity moves to processing, and the result arrives asynchronously on the user.kyc.updated webhook — the endpoint does not return a verification outcome.

When renewal is allowed

Renewal is only accepted once the identity document has entered its expiry window. Cadana tracks that window as a document stage on the KYC record, and the same stage drives the user.kyc.expiry webhook — though the webhook renames the last one: The endpoint validates against the internal stage, so a platform that sees "stage": "expired" on the webhook is still eligible to call renewal — expired and out-of-grace are the same stage under two names. The current stage is also readable at any time as identityDocumentStatus on Check KYC Status, so you do not have to have received the webhook to know whether renewal is available. Calling renewal while the document is still valid returns a 400: kyc can only be renewed when the identity document is expiring or expired. Wait for the first user.kyc.expiry event, or drive your own schedule off the expiryDate it carries.
Once a document is out-of-grace, the user’s identity status is already rejected, so PATCH /v1/users/{userId}/kyc can replace it there too. Before that point the identity is still approved, so PATCH is not available — renewal is the only route.

Request body

identity takes the full personal-information and document block — firstName, lastName, dob, nationality, and idDetails. Field rules are identical to Submit KYC, with two extra constraints on the replacement document: The second check exists to catch the common mistake of re-uploading the same expiring document and assuming the clock has been reset.

Document files

The fileId values come from the same file upload flow the other KYC endpoints use: reserve a file ID with POST /v1/files/upload-url, PUT the bytes to the returned pre-signed URL, then pass the fileId. Use the kyc-id-front, kyc-id-back, and kyc-selfie purposes. Cadana verifies that each fileId resolves to a file you actually uploaded, so upload fresh files for the renewal. Reusing the fileId values from the original submission just re-submits the expiring document.

Webhook Events

user.kyc.updated

Fired on every KYC status change — processing, pending, approved, or rejected. The type field indicates which verification component changed.
For rejected verifications, have the user resubmit the affected section with the PATCH endpoint.

user.kyc.expiry

Fired when a user’s identity document is approaching expiry or has expired.
documentType is the document’s display name as stored on the KYC record: Passport, Drivers license, National ID Card, Voter's Card, or PAN Card.
The event fires once per stage, when the document first enters it — not repeatedly while it stays there. Expect three events per document: one when it enters about-to-expire, one on the expiry date, and one when the grace period runs out. To remind users as the date approaches, drive your own schedule off the expiryDate in the payload rather than waiting for another event.
To act on the event, submit a replacement document with Renew an Expiring Document — that works from the first about-to-expire event onwards. If you let the document reach expired, the user’s verification has already reverted to rejected, and PATCH /v1/users/{userId}/kyc becomes available as well. See Events for all event types and payload details.

Handling Rejections

When KYC is rejected, the user needs to resubmit. Common rejection reasons: To resubmit, call PATCH /v1/users/{userId}/kyc with corrected information for the rejected section(s). The status resets to processing.

Sandbox Testing

Use sentinel values to simulate KYC approval or rejection in the sandbox environment without waiting for real verification. These sentinels work with both initial submission (POST) and resubmission (PATCH).
In sandbox, a submission without a sentinel never gets a result on its own — the user stops at pending. PATCH cannot move them, because resubmission only works after a rejection. So either use a sentinel, approve them yourself, or delete the sandbox user and start over.

Identity Verification

Set idDetails.number to a sentinel value:

Address Verification

Set address.line2 to a sentinel value: You can combine both sentinels in a single request to auto-resolve identity and address independently. For example, idDetails.number: "auto-approve" with address.line2: "auto-reject" will approve identity and reject address.
When a sentinel is used, the document file IDs (frontFileId, selfieFileId, addressProofFileId) can be omitted — no file upload is needed. If you do pass them, they must reference files you actually uploaded; made-up IDs are rejected with a 404. Without a sentinel, file IDs are required, as in production.

Testing the Resubmission Flow

To test the full rejection-to-resubmission cycle in sandbox:
  1. Submit KYC with idDetails.number: "auto-reject" to get a rejected identity
  2. Resubmit via PATCH with idDetails.number: "auto-approve" to approve it
These test values only work in the sandbox environment and are silently ignored in production. Sentinel values are case-insensitive.

Testing Document Transfer

A sentinel tells Cadana the answer up front, so your uploaded files are never opened. That is quick, but it means a sentinel cannot prove your document upload works. To test the upload itself, submit the way your production code would — real ID number, real fileId values, no sentinel. Cadana stores the documents and sends them on for verification. Sandbox has no real reviewer, so the user stops at pending and waits. Approve them yourself to finish: Set action to approve or reject, and type to identity or address. Each call decides one check, so approving both takes two calls. It works from any status — including pending, which resubmission cannot rescue — and it fires user.kyc.updated just like a real result. For the full step-by-step version of this flow, plus what to do when a test user gets stuck, see Sandbox & Testing.

Next Steps

Working with Files

Upload identity documents before submitting KYC

KYB Requirements

Business verification requirements

Onboard Workers

Create Person and User records

Sandbox & Testing

Test values and simulated scenarios