Skip to main content
POST
/
cardholders
/
{id}
/
kyc
Submit KYC Documents
curl --request POST \
  --url https://api.fyatu.com/api/v3/cardholders/{id}/kyc \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "documentType": "PASSPORT",
  "documentNumber": "AB123456",
  "idFrontUrl": "https://storage.example.com/documents/id_front.jpg",
  "idBackUrl": "https://storage.example.com/documents/id_back.jpg",
  "selfieUrl": "https://storage.example.com/documents/selfie.jpg"
}
'
{
  "success": true,
  "status": 200,
  "message": "KYC documents submitted successfully",
  "data": {
    "id": "ch_1a2b3c4d5e6f7890abcdef1234567890",
    "kycStatus": "SUBMITTED",
    "message": "KYC documents submitted successfully. Verification is pending."
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.fyatu.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Submit identity documents for a cardholder on their behalf using Shared KYC. This endpoint is only available to businesses that have completed FYATU’s Shared KYC onboarding process. The endpoint responds immediately with kycStatus: PENDING. Documents are processed in the background and a cardholder.kyc_approved webhook is dispatched when complete.
This endpoint returns 403 SHARED_KYC_NOT_ENABLED if your business does not have Shared KYC enabled. To apply, reach out to FYATU through your dedicated Slack channel. Enabling Shared KYC requires a due diligence review and the use of a recognised KYC provider (e.g. Sumsub, Persona, Onfido).

Endpoint

POST /api/v3/cardholders/{cardholderId}/kyc
Scope required: cardholders:write

Path Parameters

ParameterTypeRequiredDescription
cardholderIdstringYesUnique cardholder identifier

Request Fields

FieldTypeRequiredDescription
idFrontUrlstringYesURL to the front image of the ID document
selfieUrlstringYesURL to a selfie photo of the cardholder
idBackUrlstringNoURL to the back image of the ID document
documentTypestringNoPASSPORT, NATIONAL_ID, or DRIVER_LICENSE

Image Requirements

  • Format: JPEG, PNG, GIF, or WebP
  • Maximum size: 5MB per image
  • Accessibility: URLs must be publicly accessible

How It Works

  1. Your app sends document URLs to this endpoint
  2. FYATU responds immediately with PENDING status
  3. FYATU processes the documents in the background
  4. On success, kycStatus is set to ACCEPTED and a cardholder.kyc_approved webhook is dispatched with the final document URLs
  5. On failure, kycStatus is set to REJECTED — you can re-submit

Prerequisites

  • Business must have Shared KYC enabled (contact FYATU via your dedicated Slack channel)
  • Cardholder kycStatus must be UNSUBMITTED or REJECTED
  • All image URLs must be publicly accessible

Example Usage

<?php
$cardholderId = 'CH1a2b3c4d5e6f';

$data = [
    'idFrontUrl' => 'https://storage.example.com/docs/id-front.jpg',
    'idBackUrl'  => 'https://storage.example.com/docs/id-back.jpg',
    'selfieUrl'  => 'https://storage.example.com/docs/selfie.jpg',
    'documentType' => 'NATIONAL_ID',
];

$response = file_get_contents(
    "https://api.fyatu.com/api/v3/cardholders/{$cardholderId}/kyc",
    false,
    stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => [
                'Authorization: Bearer ' . $accessToken,
                'Content-Type: application/json'
            ],
            'content' => json_encode($data)
        ]
    ])
);

$result = json_decode($response, true);
echo "KYC status: " . $result['data']['kycStatus'] . "\n";
// Output: KYC status: PENDING

Example Response

Success (200)

{
  "success": true,
  "status": 200,
  "message": "KYC documents received and are being processed",
  "data": {
    "id": "CH1a2b3c4d5e6f",
    "kycStatus": "PENDING"
  },
  "meta": {
    "requestId": "req_kyc123abc",
    "timestamp": "2026-01-08T17:00:00+00:00"
  }
}
The final approved state arrives via webhook once background processing completes:
{
  "event": "cardholder.kyc_approved",
  "data": {
    "id": "CH1a2b3c4d5e6f",
    "kycStatus": "ACCEPTED",
    "document": {
      "type": "NATIONAL_ID"
    },
    "kyc": {
      "idFrontUrl": "https://cdn.fyatu.com/kyc/CH1a2b3c4d5e6f/front_1234567890.jpg",
      "idBackUrl":  "https://cdn.fyatu.com/kyc/CH1a2b3c4d5e6f/back_1234567890.jpg",
      "selfieUrl":  "https://cdn.fyatu.com/kyc/CH1a2b3c4d5e6f/selfie_1234567890.jpg"
    }
  }
}

Error Responses

Shared KYC Not Enabled (403)

{
  "success": false,
  "status": 403,
  "message": "Shared KYC is not enabled for this business",
  "error": { "code": "SHARED_KYC_NOT_ENABLED" }
}

Already Accepted (409)

{
  "success": false,
  "status": 409,
  "message": "KYC has already been accepted for this cardholder",
  "error": { "code": "CONFLICT" }
}

Already Processing (409)

{
  "success": false,
  "status": 409,
  "message": "KYC documents are already being processed",
  "error": { "code": "KYC_PENDING" }
}

Validation Error (400)

{
  "success": false,
  "status": 400,
  "message": "Validation failed",
  "error": {
    "code": "VALIDATION_ERROR",
    "details": [
      { "field": "selfieUrl", "message": "The selfieUrl field is required." }
    ]
  }
}
You can also submit KYC documents at cardholder creation time by including a kyc object in the POST /cardholders request body. See the Create Cardholder endpoint for details.

Authorizations

Authorization
string
header
required

JWT access token obtained from /auth/token

Path Parameters

id
string
required

Unique cardholder identifier

Body

application/json
documentType
enum<string>
required

Type of identification document

Available options:
PASSPORT,
NATIONAL_ID,
DRIVER_LICENSE
documentNumber
string
required

Document identification number

Required string length: 3 - 50
idFrontUrl
string<uri>
required

URL to the front image of the ID document

Maximum string length: 500
idBackUrl
string<uri>

URL to the back image of the ID document (optional for passports)

Maximum string length: 500
selfieUrl
string<uri>

URL to a selfie photo holding the ID document

Maximum string length: 500

Response

KYC documents submitted successfully

success
boolean
Example:

true

status
integer
Example:

200

message
string
Example:

"KYC documents submitted successfully"

data
object