Upload document
Deprecated
Upload a customer document for KYC or KYB verification. This is the first step of the server-to-server verification flow.
Documents are uploaded as base64-encoded strings along with metadata about the document type, customer information, and document details. The document is validated and stored in preparation for verification.
Supported document types
The metadata.idDocType field accepts the following values (lowercase):
-
Individual customers: passport, id_card, drivers_license, selfie, residence_permit, utility_bill, bank_card, vehicle_registration_certificate, other
-
Business customers: registration_certificate, company_doc, formation_document, ownership_document, proof_of_address, proof_of_address_document
Selfie documents must be an image (JPEG or PNG); PDF selfies are rejected.
Document subtypes
The supported document subtypes are as follows (case-sensitive, uppercase):
- FRONT_SIDE: Front side of document
- BACK_SIDE: Back side of document (if applicable)
File format
The filename extension and the decoded content MIME type must agree and must be one of: image/jpeg, image/png, application/pdf.
Size limits
The maximum decoded document size is 10 MB. The base64-encoded payload sent in content may be up to roughly 13.3 MB. Larger payloads are rejected at the ingress layer with a 413 before reaching the service.
Idempotency
The Idempotency-Key header is required on this endpoint. Replays of the same key with the same payload return the original response; replays with a different payload return 422.
After uploading all required documents, call the Initiate KYC S2S endpoint to start the verification process.
Headers
Unique key to dedupe retries. Required on this endpoint; 1–255 ASCII printable characters. Missing or malformed keys return 400.
Request Body
ID of the customer this document belongs to
Optional upstream applicant identifier. When omitted (server-to-server flow) the service resolves the applicant from customer_id.
Type of document being uploaded. Individual customer documents include passport, id_card, drivers_license, selfie, residence_permit, utility_bill, bank_card, vehicle_registration_certificate, and other. Business customer documents include registration_certificate, company_doc, formation_document, ownership_document, proof_of_address, and proof_of_address_document.
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
Subtype indicating which side of the document. Must be uppercase; lowercase values are passed through to the upstream verifier and may be silently rejected.
Possible values: FRONT_SIDE, BACK_SIDE
Document issuing country (ISO 3166-1 alpha-3 code, uppercase)
First name as shown on document
Middle name as shown on document (optional)
Last name as shown on document
Document issue date (YYYY-MM-DD)
Document expiration date (YYYY-MM-DD)
Document identification number
Date of birth (YYYY-MM-DD)
Place of birth as shown on document
Base64-encoded document content. The decoded bytes must be a JPEG, PNG, or PDF; the service sniffs the leading bytes and rejects other MIME types. Maximum decoded size is 10 MB.
Original filename of the document. Extension must be one of .jpg, .jpeg, .png, .pdf (case-insensitive); the file extension is validated before the content MIME sniff.
Whether to return document quality warnings in the response
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.jpg",
"return_doc_warnings": true
}
{
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"metadata": {
"idDocType": "selfie",
"idDocSubType": "FRONT_SIDE",
"country": "NGA",
"firstName": "John",
"lastName": "Doe",
"dob": "1990-05-20"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "selfie.jpg",
"return_doc_warnings": false
}
{
"customer_id": "c84d9a52-2978-43e5-9b86-eac9839e1147",
"metadata": {
"idDocType": "registration_certificate",
"idDocSubType": "FRONT_SIDE",
"country": "NGA",
"firstName": "Acme",
"lastName": "Corporation",
"number": "RC123456",
"issuedDate": "2020-01-15"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "registration_certificate.pdf",
"return_doc_warnings": true
}
{
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"metadata": {
"idDocType": "id_card",
"idDocSubType": "FRONT_SIDE",
"country": "NGA",
"firstName": "Jane",
"lastName": "Smith",
"number": "ID987654321",
"issuedDate": "2019-06-10",
"validUntil": "2029-06-10",
"dob": "1992-03-15",
"placeOfBirth": "Lagos"
},
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"filename": "id_card_front.jpg",
"return_doc_warnings": true
}
Responses
| Status | Description |
|---|---|
200 |
Document uploaded successfully |
400 |
Invalid request |
404 |
Customer not found |
409 |
Concurrent in-flight request with the same Idempotency-Key |
413 |
Payload too large. The decoded document exceeds the 10 MB service limit, or the request body exceeded the ingress 15 MB limit. The ingress-layer 413 is returned as HTML by nginx and does not match the schema below. |
422 |
Idempotency-Key reused with a different request payload |
200 response
Always "success" on a successful upload
Possible values: success
ID of the customer the document was saved for
Normalised document type derived from metadata.idDocType
Document sub-type as supplied in metadata.idDocSubType
ISO 3166-1 alpha-3 country code as supplied in metadata.country
Human-readable confirmation message
Error information if the request failed
{
"data": {
"status": "success",
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"document_type": "passport",
"document_sub_type": "FRONT_SIDE",
"country": "NGA",
"message": "Document saved. Use /initiate-kyc to submit for verification."
},
"error": null
}
{
"data": {
"status": "success",
"customer_id": "b84d9a52-2978-43e5-9b86-eac9839e1146",
"document_type": "selfie",
"document_sub_type": "FRONT_SIDE",
"country": "NGA",
"message": "Document saved. Use /initiate-kyc to submit for verification."
},
"error": null
}
400 response
Always null for error responses
Human-readable error message
{
"data": null,
"error": {
"code": "INVALID_ARGUMENT",
"message": "selfie is not a valid document type for business customers",
"details": {}
}
}
{
"data": null,
"error": {
"code": "INVALID_ARGUMENT",
"message": "filename is required",
"details": {}
}
}
{
"data": null,
"error": {
"code": "INVALID_ARGUMENT",
"message": "Invalid base64 encoded content",
"details": {}
}
}
{
"data": null,
"error": {
"code": "INVALID_ARGUMENT",
"message": "missing idempotency key in request headers",
"details": {}
}
}
{
"data": null,
"error": {
"code": "INVALID_ARGUMENT",
"message": "unsupported file content type: application/octet-stream. Supported types: JPEG, PNG, PDF",
"details": {}
}
}
404 response
Always null for error responses
Human-readable error message
{
"data": null,
"error": {
"code": "NOT_FOUND",
"message": "Customer not found",
"details": {}
}
}
409 response
Always null for error responses
Human-readable error message
{
"data": null,
"error": {
"code": "CONFLICT",
"message": "A request with the same Idempotency-Key is currently being processed",
"details": {}
}
}
413 response
Always null for error responses
Human-readable error message
{
"data": null,
"error": {
"code": "PAYLOAD_TOO_LARGE",
"message": "file too large: content exceeds maximum allowed size of 10MB",
"details": {}
}
}
422 response
Always null for error responses
Human-readable error message
{
"data": null,
"error": {
"code": "UNPROCESSABLE_ENTITY",
"message": "Idempotency-Key was previously used with a different request payload",
"details": {}
}
}
Authorization
- ApiKeyAuth