Overview
Initiate an optional automated KYC (Know Your Customer) verification session for a cardholder. This creates a secure verification session where the cardholder completes identity document capture and liveness verification.
KYC verification is not required for card issuance — you can issue cards to cardholders without completing KYC. Use this endpoint when you need to verify a cardholder’s identity for compliance or enhanced trust.
The verification result is delivered asynchronously via webhook (cardholder.kyc_approved or cardholder.kyc_rejected).
Endpoint
POST /api/v3/cardholders/{cardholderId}/kyc/session
Scope required: cardholders:write
Path Parameters
| Parameter | Type | Required | Description |
|---|
cardholderId | string | Yes | Unique cardholder identifier |
Request Body
No request body required.
How It Works
- Your app calls this endpoint to get a verification URL
- Redirect the cardholder to the
verificationUrl
- The cardholder completes ID document capture and liveness verification
- FYATU sends a webhook to your app with the result (
cardholder.kyc_approved or cardholder.kyc_rejected)
Verification Fee
A fee of $0.60 is charged per successful verification:
- The fee is held from your business wallet when the session is initiated
- Captured (charged) when the verification is approved
- Released (refunded) when the verification is declined, abandoned, or expires
If your wallet balance is insufficient, the request will return a 402 error.
Prerequisites
- Cardholder
kycStatus must be UNSUBMITTED or REJECTED
- Business wallet must have sufficient balance for the verification fee
Example Usage
<?php
$cardholderId = 'ch_1a2b3c4d5e6f7890abcdef1234567890';
$response = file_get_contents(
"https://api.fyatu.com/api/v3/cardholders/{$cardholderId}/kyc/session",
false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => [
'Authorization: Bearer ' . $accessToken,
'Content-Type: application/json'
]
]
])
);
$result = json_decode($response, true);
// Redirect cardholder to the verification URL
$verificationUrl = $result['data']['verificationUrl'];
echo "Redirect cardholder to: {$verificationUrl}\n";
Example Response
Success (201)
{
"success": true,
"status": 201,
"message": "KYC verification session created",
"data": {
"cardholderId": "ch_1a2b3c4d5e6f7890abcdef1234567890",
"sessionId": "ses_abc123def456",
"verificationUrl": "https://verify.didit.me/session/ses_abc123def456",
"kycStatus": "PENDING",
"fee": 0.60
},
"meta": {
"requestId": "req_kyc789xyz",
"timestamp": "2026-04-02T10:30:00+00:00"
}
}
Session Already In Progress (200)
If a verification session is already active, the existing session is returned:
{
"success": true,
"status": 200,
"message": "KYC session already in progress",
"data": {
"cardholderId": "ch_1a2b3c4d5e6f7890abcdef1234567890",
"sessionId": "ses_abc123def456",
"verificationUrl": "https://verify.didit.me/session/ses_abc123def456",
"kycStatus": "PENDING"
},
"meta": {
"requestId": "req_kyc790xyz",
"timestamp": "2026-04-02T10:35:00+00:00"
}
}
KYC Status Flow
UNSUBMITTED ──> PENDING (session initiated) ──> ACCEPTED (verification approved)
^ |
| ├──> REJECTED (verification failed) ──> UNSUBMITTED (can retry)
| |
| └──> UNSUBMITTED (session abandoned/expired, can retry)
|
└── REJECTED ──> PENDING (new session initiated)
| Status | Description | Can Initiate Session |
|---|
UNSUBMITTED | No verification started | Yes |
PENDING | Verification in progress | No (returns existing session) |
ACCEPTED | Verification approved | No |
REJECTED | Verification failed | Yes (retry allowed) |
Webhook Events
After the cardholder completes (or abandons) verification, you’ll receive one of these webhooks:
cardholder.kyc_approved
{
"event": "cardholder.kyc_approved",
"data": {
"cardholderId": "ch_1a2b3c4d5e6f7890abcdef1234567890",
"firstName": "John",
"lastName": "Smith",
"kycStatus": "ACCEPTED",
"documentType": "PASSPORT"
},
"timestamp": "2026-04-02T10:45:00+00:00"
}
cardholder.kyc_rejected
{
"event": "cardholder.kyc_rejected",
"data": {
"cardholderId": "ch_1a2b3c4d5e6f7890abcdef1234567890",
"firstName": "John",
"lastName": "Smith",
"kycStatus": "REJECTED",
"reason": "Document expired"
},
"timestamp": "2026-04-02T10:45:00+00:00"
}
Error Responses
Already Verified (409)
{
"success": false,
"status": 409,
"message": "KYC has already been verified for this cardholder",
"error": { "code": "CONFLICT" }
}
Insufficient Balance (402)
{
"success": false,
"status": 402,
"message": "Insufficient balance for KYC verification fee ($0.60)",
"error": { "code": "INSUFFICIENT_BALANCE" }
}
Invalid State (409)
{
"success": false,
"status": 409,
"message": "KYC cannot be initiated in current state",
"error": { "code": "KYC_INVALID_STATE" }
}
Provider Error (503)
{
"success": false,
"status": 503,
"message": "Failed to create verification session. Please try again.",
"error": { "code": "PROVIDER_ERROR" }
}
Store the verificationUrl and provide it to the cardholder. If the cardholder doesn’t complete verification, you can call this endpoint again to get a new session after the previous one expires.
The verification fee is only charged on successful verification. If the cardholder abandons the session or verification fails, no fee is charged.