/api/v1/customers
Register a cardholder
- Returns
- 202 · Customer
- Scope
- customers.write
All fields below are required except customer_type
and place_of_birth. There is no partial create:
a customer either has a complete identity or does not exist. The response is
202 — the record is saved and verification
has started.
| Field | Type | Rules |
|---|---|---|
customer_type
|
string | Optional. individual (default) or business. A business needs the two fields below as well as everything else — see the note. |
business_name
|
string | Max 150. Required when customer_type is business. |
registration_number
|
string | Max 64. The business or RC number. Required for a business. |
first_name
|
string | Max 100. |
last_name
|
string | Max 100. |
email
|
string | A valid address, max 254. |
phone_number
|
string | Digits only, 4–15 of them, without the country code. |
dial_code
|
string | The country code on its own, with the plus: +234. |
date_of_birth
|
string | YYYY-MM-DD. The cardholder must be at least 18 years old. |
id_type
|
string | One of bvn, nin, passport, drivers_license, national_id, vnin, voters_card, ghana_card. See the note below — the choice changes what else you must send. |
id_number
|
string | Max 64. Stored encrypted; only the last four are ever echoed back. |
line1
|
string | Street address, max 120. |
city
|
string | Max 120. |
state
|
string | Max 120. Required even where the country has no states — use the city or region. |
postal_code
|
string | Max 20. |
country
|
string | ISO 3166-1 alpha-3: USA, NGA. Letters only; case-insensitive on input. |
occupation
|
string | Max 100. Lowercase with underscores, e.g. software_engineer. |
employment_status
|
string | Max 50, e.g. employed, self_employed, student. |
account_purpose
|
string | Max 100. What the card is for, e.g. personal_spending. |
annual_salary
|
string | Declared annual income in whole units, digits only — not minor units, no decimal point. |
expected_monthly_volume
|
string | Anticipated monthly spend, same format as above. |
place_of_birth
|
string | Optional. Max 120. |
terms_of_service_accepted
|
boolean | Must be true. We record when the cardholder accepted; verification cannot be submitted without it. |
id_front_image
|
string | Base64 photo of the document front. Required for document ID types and rejected for bvn/nin. Send the photo you have — anything oversized is resized for you. |
A business is verified through a person.
business_name and
registration_number are
additions, not replacements. Send them
alongside the full personal identity — name, date of birth and an ID document — of
the natural person behind the account. That person is who actually gets verified;
without their details a business submission is rejected.
The ID type changes what else you send.
bvn and
nin are checked against a Nigerian national
database. They verify in seconds,
country must be
NGA, and you must
not send
id_front_image — sending one is rejected.
Every other type is a document. It requires
id_front_image, and a result comes back
within about 10 minutes. Send the front of the document in full, in focus and in
date — a blurred, cropped or expired photo is the most common reason a verification
is rejected.
first_name and
last_name are checked against the document,
so send them exactly as they appear on it.
Don't resize the photo yourself. A phone camera produces several megabytes, which is far more than the card network accepts — we recompress anything oversized, dropping quality before resolution so the document stays readable, and rotate it upright if the camera recorded it sideways. The document is held on private storage only until verification settles, then deleted.
The last six describe the cardholder rather than identify them, and the verification will not run without them. Send what the cardholder actually told you — these are declarations you are passing on, and a profile that does not match the person is the most common reason a verification comes back rejected.
{
"first_name": "Amina",
"last_name": "Bello",
"email": "[email protected]",
"phone_number": "8031234567",
"dial_code": "+234",
"date_of_birth": "1994-03-11",
"id_type": "bvn",
"id_number": "12345678901",
"line1": "14 Adeola Odeku Street",
"city": "Lagos",
"state": "Lagos",
"postal_code": "101241",
"country": "NGA",
"occupation": "software_engineer",
"employment_status": "employed",
"account_purpose": "personal_spending",
"annual_salary": "4800000",
"expected_monthly_volume": "150000",
"terms_of_service_accepted": true
}
{
"success": true,
"data": {
"id": "01KA7XR4W9YT6N3DK8C2QFMH5J",
"customer_type": "individual",
"first_name": "Amina",
"last_name": "Bello",
"email": "[email protected]",
"phone_number": "8031234567",
"dial_code": "+234",
"date_of_birth": "1994-03-11",
"id_type": "bvn",
"id_number_last4": "8901",
"line1": "14 Adeola Odeku Street",
"city": "Lagos",
"state": "Lagos",
"postal_code": "101241",
"country": "NGA",
"status": "active",
"kyc_status": "unsubmitted",
"kyc_failure_reason": null,
"created_at": "2026-08-17T21:00:00+00:00"
}
}
Note what comes back: id_number_last4, never the
id number you sent. The registry is not a place to look things up from later — keep your
own record of what you submitted.
kyc_status starts at
unsubmitted and moves to
pending within moments, then to
approved or
rejected. Note that
status and
kyc_status are separate things:
status is your own switch for whether a
cardholder may be used at all, and disabling an approved customer does not throw their
verification away.