Skip to main content

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

ParameterTypeRequiredDescription
cardholderIdstringYesUnique cardholder identifier

Request Body

No request body required.

How It Works

  1. Your app calls this endpoint to get a verification URL
  2. Redirect the cardholder to the verificationUrl
  3. The cardholder completes ID document capture and liveness verification
  4. 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)
StatusDescriptionCan Initiate Session
UNSUBMITTEDNo verification startedYes
PENDINGVerification in progressNo (returns existing session)
ACCEPTEDVerification approvedNo
REJECTEDVerification failedYes (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.