Upload a KYC document
Stores one document file for a customer. This is step 1 of server-to-server verification. Upload each document, and each side of a two-sided card, in a separate call. Nothing is sent for review until you call POST /v1/customers/kyc/start-s2s.
Individual and UBO customers need one identity document (PASSPORT, ID_CARD or DRIVERS) with FRONT_SIDE, plus a SELFIE. Identity documents also need country, number and validUntil. A selfie must be a JPEG or PNG.
Business customers use idDocType: COMPANY_DOC for every file and set idDocSubType to INCORPORATION_CERT, SHAREHOLDER_REGISTRY, PROOF_OF_ADDRESS and TAX_DOCUMENT (or OTHER).
Uploading the same type and subtype again replaces the earlier file. On tenants with automatic document verification, the upload that completes the required set also completes KYC.
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. Individual and UBO customers may upload PASSPORT, ID_CARD, DRIVERS, SELFIE, PROOF_OF_ADDRESS or TAX_DECLARATION. To start verification they need one identity document (PASSPORT, ID_CARD or DRIVERS) with a front image, plus a SELFIE. Business customers upload only COMPANY_DOC, once for each idDocSubType.
Possible values: PASSPORT, ID_CARD, DRIVERS, SELFIE, PROOF_OF_ADDRESS, TAX_DECLARATION, COMPANY_DOC
Which part of the document this is. Values are case-sensitive. Identity documents need FRONT_SIDE, and BACK_SIDE as a separate upload for two-sided cards. COMPANY_DOC needs one of INCORPORATION_CERT, SHAREHOLDER_REGISTRY, PROOF_OF_ADDRESS, TAX_DOCUMENT or OTHER. A business needs each of the first three, plus TAX_DOCUMENT or OTHER. Omit it for SELFIE, PROOF_OF_ADDRESS and TAX_DECLARATION.
Possible values: FRONT_SIDE, BACK_SIDE, INCORPORATION_CERT, SHAREHOLDER_REGISTRY, PROOF_OF_ADDRESS, TAX_DOCUMENT, OTHER
Issuing country as an ISO 3166-1 alpha-2 or alpha-3 code. Required for every type except SELFIE. The response gives it as alpha-3.
Document number. Required for PASSPORT, ID_CARD and DRIVERS.
Expiry date as YYYY-MM-DD. Required for PASSPORT, ID_CARD and DRIVERS. The format is not checked here, but the verification review may reject a bad date.
Issue date as YYYY-MM-DD.
First name as shown on the document
Middle name as shown on the document
Last name as shown on the document
Date of birth as YYYY-MM-DD.
Place of birth as shown on the document
The file as plain standard base64, with no data: prefix. The decoded file must be a JPEG, PNG or PDF. The service checks the file bytes, not the name. The maximum decoded size is 10 MB. In sandbox, keep files under about 500 KB.
Name of the file. The extension is not checked. The content decides the file type.
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"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "selfie.png"
}
{
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"metadata": {
"idDocType": "ID_CARD",
"idDocSubType": "FRONT_SIDE",
"country": "NG",
"firstName": "Jane",
"lastName": "Smith",
"number": "ID987654321",
"issuedDate": "2019-06-10",
"validUntil": "2029-06-10"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "id_card_front.png"
}
{
"customer_id": "c84d9a52-2978-43e5-9b86-eac9839e1147",
"metadata": {
"idDocType": "COMPANY_DOC",
"idDocSubType": "INCORPORATION_CERT",
"country": "NGA"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "incorporation_certificate.png"
}
Responses
| Status | Description |
|---|---|
200 |
Document stored |
400 |
Invalid request |
404 |
Customer not found |
409 |
A request with the same Idempotency-Key is still running. Retry after the Retry-After header. |
413 |
The file or the request body is too large. |
422 |
The Idempotency-Key was used before with a different body. |
500 |
The document could not be stored |
503 |
The service is not configured or not reachable. Retry later. |
200 response
Always success.
Possible values: success
ID of the customer the document was saved for
The idDocType you sent, in upper case
The idDocSubType you sent
ID of the stored document. Uploading the same type and subtype again replaces the file and keeps this ID.
Issuing country as an alpha-3 code
Confirmation text. Despite its wording, the next call in the server-to-server flow is POST /v1/customers/kyc/start-s2s.
completed when this upload completed verification at once. Only tenants with automatic document verification see it.
Possible values: completed
{
"data": {
"status": "success",
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"document_type": "PASSPORT",
"document_sub_type": "FRONT_SIDE",
"document_id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"country": "USA",
"message": "Document saved. Use /start-kyc to submit for verification."
},
"error": null
}
{
"data": {
"status": "success",
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"document_type": "SELFIE",
"document_sub_type": "",
"document_id": "d2e3f4a5-b6c7-4d8e-9f0a-1b2c3d4e5f6a",
"country": "NGA",
"message": "Document saved. KYC auto-approved: all required documents received.",
"kyc_status": "completed"
},
"error": null
}
400 response
Always null for error responses
Error message. Most messages start with an upper-case code and a colon, such as INVALID_REQUEST: ....
{
"data": null,
"error": "INVALID_REQUEST: customer_id is required"
}
{
"data": null,
"error": "INVALID_REQUEST: content (base64 image) is required"
}
{
"data": null,
"error": "INVALID_REQUEST: filename is required"
}
{
"data": null,
"error": "INVALID_REQUEST: metadata.country is required"
}
{
"data": null,
"error": "INVALID_REQUEST: metadata.number is required for identity document uploads"
}
{
"data": null,
"error": "INVALID_REQUEST: metadata.idDocSubType is required for business document uploads (e.g. INCORPORATION_CERT, SHAREHOLDER_REGISTRY, PROOF_OF_ADDRESS, TAX_DOCUMENT)"
}
{
"data": null,
"error": "INVALID_REQUEST: document type \"PASSPORT\" is not allowed for business customers; allowed type: COMPANY_DOC"
}
{
"data": null,
"error": "INVALID_REQUEST: document content is not valid base64"
}
{
"data": null,
"error": "INVALID_REQUEST: unsupported file type \"application/octet-stream\"; allowed types are JPEG, PNG, and PDF"
}
{
"data": null,
"error": "missing idempotency key in request headers"
}
404 response
Always null for error responses
Error message. Most messages start with an upper-case code and a colon, such as INVALID_REQUEST: ....
{
"data": null,
"error": "CUSTOMER_NOT_FOUND: Customer not found. Please verify the customer exists in our system."
}
409 response
Possible values: idempotency_in_flight, idempotency_key_reused
{
"data": null,
"error": {
"code": "idempotency_in_flight",
"message": "A request with the same Idempotency-Key is currently being processed"
}
}
413 response
Always null for error responses
Error message. Most messages start with an upper-case code and a colon, such as INVALID_REQUEST: ....
{
"data": null,
"error": "the uploaded file is too large — the maximum is 10MB"
}
422 response
Possible values: idempotency_in_flight, idempotency_key_reused
{
"data": null,
"error": {
"code": "idempotency_key_reused",
"message": "Idempotency-Key was previously used with a different request payload"
}
}
500 response
Always null for error responses
Error message. Most messages start with an upper-case code and a colon, such as INVALID_REQUEST: ....
{
"data": null,
"error": "failed to get KYC information"
}
503 response
Always null for error responses
Error message. Most messages start with an upper-case code and a colon, such as INVALID_REQUEST: ....
{
"data": null,
"error": "verification provider not configured"
}
Authorization
- ApiKeyAuth