Gravv docs
Docs Agent Sign in Get API keys

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.

POSThttps://api.gravv.xyz/v1/risk/upload-document

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
Was this page helpful?
ESC