Upload a cardholder KYC document
Stores one document file for a cardholder. This is step 1 of server-to-server card KYC. Nothing is sent for review until you call POST /v1/risk/start-kyc-s2s.
Check data.status. A validation failure returns HTTP 200 with data.status: error and a generic message. Common causes are a two-letter country, a file name that does not end in .jpg, .jpeg, .png or .pdf, a PDF selfie, or a date that is not YYYY-MM-DD.
Every upload is stored as a front image. Send the back of a card as a second upload with idDocSubType: BACK_SIDE. Uploading the same type and subtype again replaces the earlier file. Keep files under 5 MB.
Headers
Required for POST requests. 1 to 255 printable ASCII characters. A retry with the same key and body within 24 hours returns the first response.
Request Body
ID of the customer this document belongs to
Type of document, in lower case. Individual customers need a selfie plus one of passport, id_card or drivers_license. Business customers need one of company_doc, registration_certificate or formation_document. These names differ from the customer KYC upload. Do not mix the two upload flows for one customer.
Possible values: passport, id_card, drivers_license, selfie, residence_permit, utility_bill, bank_card, vehicle_registration_certificate, other, registration_certificate, company_doc, formation_document, ownership_document, proof_of_address, proof_of_address_document
Which side of the document this is. Send the back of a card as a second upload with BACK_SIDE.
Possible values: FRONT_SIDE, BACK_SIDE
Issuing country as an ISO 3166-1 alpha-3 code. Required for every type, including selfie.
First name as shown on the document
Middle name as shown on the document
Last name as shown on the document
Issue date as YYYY-MM-DD
Expiry date as YYYY-MM-DD
Document number
Date of birth as YYYY-MM-DD
Place of birth as shown on the document
The file as plain standard base64. The decoded file must be a JPEG, PNG or PDF. Keep files under 5 MB. Larger files fail with a 400.
Name of the file. It must end in .jpg, .jpeg, .png or .pdf, in any case.
Request Examples
{
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"metadata": {
"idDocType": "passport",
"idDocSubType": "FRONT_SIDE",
"country": "USA",
"firstName": "John",
"middleName": "Michael",
"lastName": "Doe",
"issuedDate": "2020-01-15",
"validUntil": "2030-01-15",
"number": "A12345678",
"dob": "1990-05-20",
"placeOfBirth": "New York, NY"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "passport_front.png"
}
{
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"metadata": {
"idDocType": "selfie",
"country": "NGA"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "selfie.png"
}
{
"customer_id": "c84d9a52-2978-43e5-9b86-eac9839e1147",
"metadata": {
"idDocType": "company_doc",
"country": "NGA",
"number": "RC123456"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "registration_certificate.png"
}
Responses
| Status | Description |
|---|---|
200 |
Document stored, or a validation failure with data.status: error |
400 |
Invalid customer, missing KYC record, or a file that is too large |
409 |
A request with the same Idempotency-Key is still running. |
413 |
The request body is too large. |
422 |
The Idempotency-Key was used before with a different body. |
200 response
One of the following variants:
Possible values: success
ID of the customer the document was saved for
Stored type, in upper case. For example id_card is stored as ID_CARD, drivers_license as DRIVERS, and company_doc as REGISTRATION_CERTIFICATE.
The idDocSubType you sent
Issuing country as an alpha-3 code
Confirmation text. Despite its wording, the next call is POST /v1/risk/start-kyc-s2s.
A validation or storage failure, returned with HTTP 200. The message is generic, so check the request against the rules on this page.
Possible values: error
Possible values: INVALID_REQUEST, DOCUMENT_ERROR
{
"data": {
"status": "success",
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"document_type": "PASSPORT",
"document_sub_type": "FRONT_SIDE",
"country": "USA",
"message": "Document saved. Use /initiate-kyc to submit for verification."
},
"error": null
}
{
"data": {
"status": "error",
"error_code": "INVALID_REQUEST",
"message": "The provided data format is invalid. Please check your request and try again."
},
"error": null
}
400 response
Always null for error responses
Error message. Most messages start with an upper-case code and a colon, such as CUSTOMER_NOT_FOUND: ....
{
"data": null,
"error": "CUSTOMER_NOT_FOUND: Customer not found. Please verify the customer exists in our system."
}
{
"data": null,
"error": "missing idempotency key in request headers"
}
409 response
{
"data": null,
"error": {
"code": "idempotency_in_flight",
"message": "A request with the same Idempotency-Key is currently being processed"
}
}
413 response
{
"data": null,
"error": {
"code": "request_body_too_large",
"message": "Request body exceeds the maximum allowed size",
"limit": 13997400
}
}
422 response
{
"data": null,
"error": {
"code": "idempotency_key_reused",
"message": "Idempotency-Key was previously used with a different request payload"
}
}
Authorization
- ApiKeyAuth