Docs
ENFR
Dashboard
API reference

Cardholders

A cardholder is the person a card is issued to: a member of your team or one of your customers. The card issuer verifies their identity before any card is issued.

The cardholder object

Attributes
idstring

Unique identifier (UUID).

livemodeboolean

true for live objects, false for test objects.

objectstring

Always cardholder.

typestring

team for your own staff, customer for your customers.

teamcustomer
first_namestring
last_namestring
emailstring
phonestring | null

International format.

countrystring

ISO 3166-1 alpha-2.

citystring | null
birth_datestring | null

YYYY-MM-DD.

id_documentstring

Identity document type.

national_idpassportdriver_licensevoters_card
id_number_last4string | null

Last 4 characters of the document number. The full number is never returned.

verificationobject

Identity verification by the card issuer. A card can only be issued once status is verified.

Show child attributes
statusstring
pendingin_reviewverifiedrejected
reasonstring | null

Why it was rejected.

verified_atstring | null

When it was verified.

documents_on_fileboolean

true when the document photos sent on creation are on file: the verification can be submitted without sending them again.

created_atstring

Creation time, ISO 8601 (UTC).

updated_atstring

Last change, ISO 8601 (UTC).

The cardholder object
{
  "id": "5df6acd9-4bac-4e19-869c-fcde6b79f389",
  "object": "cardholder",
  "livemode": false,
  "type": "customer",
  "first_name": "Awa",
  "last_name": "Ndiaye",
  "email": "awa@example.com",
  "phone": "+237670000999",
  "country": "CM",
  "city": "Douala",
  "birth_date": "1991-02-03",
  "id_document": "national_id",
  "id_number_last4": "3408",
  "verification": {
    "status": "pending",
    "reason": null,
    "verified_at": null,
    "documents_on_file": true
  },
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:06.394Z"
}

Create a cardholder

POST/v1/cardholders

Creates the cardholder with verification.status pending. A photo of the identity document is required (documents): it is checked before anything is created and reused by the identity verification. Then submit the identity verification.

Key roles: Owner or Finance

Body
first_namestringRequired

Exactly as on the identity document. 1 to 50 characters: letters (accents allowed), spaces, apostrophes, periods and hyphens.

last_namestringRequired

Same rules as first_name.

emailstringRequired

Valid address, up to 200 characters. Unique per business.

countrystringRequired

Country of residence, ISO 3166-1 alpha-2, among: CM, GA, TD, CG, CF, CD, CI, SN, BJ, TG, BF, ML, NE, GN, NG, GH, KE, UG, TZ, RW, ZM, ZA. Otherwise country_unsupported.

typestringOptionalDefault team
teamcustomer
phonestringRequired

Mobile number in international E.164 format (+237670000999). A national number gets the country code of country. The national part must have the length used in that country, otherwise phone_invalid. Returned normalized.

birth_datestringRequired

YYYY-MM-DD, a real date, exactly as on the document. The cardholder must be at least 18 (cardholder_underage).

id_documentstringOptionalDefault national_id

Document used for verification. In Ghana, national_id is the Ghana Card. A passport needs its photo page only; the other documents need both sides.

national_idpassportdriver_licensevoters_card
id_numberstringOptional

Document number, as printed (upper-cased). Passport: 6 to 9 letters or digits, no spaces. Other documents: 4 to 30 characters among letters, digits, spaces, / and -. Optional here, required by the verification. Only its last 4 characters are returned.

citystringOptional

Optional. 2 to 60 characters, no digits.

addressobjectOptional

Home address, kept with the cardholder: line1, line2, city, state, postal_code. The verification asks for it again.

documentsobjectRequired

Photos of the identity document, as base64 or data:image/…;base64, URIs. JPEG or PNG, 4 MB each at most, at least 600 × 400 px. Missing: parameter_missing; unreadable, too large or too small: document_invalid. param names the side.

Show child attributes
frontstringRequired

Front side (photo page of a passport).

backstringOptional

Back side. Required, except for a passport.

Returns

Returns the new cardholder object with 201.

Errors worth handling
HTTPCodeDescription
400parameter_missingA required parameter is missing. See param.
400parameter_invalidA parameter has the wrong type or value. See param.
400document_invalidA document image is not accepted: JPEG or PNG only, 4 MB at most, at least 600 × 400 px. param names the side.
400phone_invalidThe number cannot be read as an international number.
400country_unsupportedThis country is not open for this currency. See Coverage.
400cardholder_underageThe cardholder must be at least 18 years old.
400id_document_unsupportedUnsupported identity document type.
403permission_deniedThe key’s creator does not have the role required for this operation.
409cardholder_existsA cardholder already uses this email.
429rate_limitedA rate limit was reached. Wait for Retry-After seconds. See Rate limits.
curl https://api.monerails.com/v1/cardholders \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a1f3c9e2-5b7d-4c21-9f80-3e6b2d1c7a45" \
  -d '{
    "type": "customer",
    "first_name": "Awa",
    "last_name": "Ndiaye",
    "email": "awa@example.com",
    "phone": "+237670000999",
    "country": "CM",
    "city": "Douala",
    "birth_date": "1991-02-03",
    "id_document": "national_id",
    "documents": {
      "front": "data:image/jpeg;base64,/9j/4AAQ…",
      "back": "data:image/jpeg;base64,/9j/4AAQ…"
    }
  }'
Response201
{
  "id": "5df6acd9-4bac-4e19-869c-fcde6b79f389",
  "object": "cardholder",
  "livemode": false,
  "type": "customer",
  "first_name": "Awa",
  "last_name": "Ndiaye",
  "email": "awa@example.com",
  "phone": "+237670000999",
  "country": "CM",
  "city": "Douala",
  "birth_date": "1991-02-03",
  "id_document": "national_id",
  "id_number_last4": "3408",
  "verification": {
    "status": "pending",
    "reason": null,
    "verified_at": null,
    "documents_on_file": true
  },
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:06.394Z"
}

Submit identity verification

POST/v1/cardholders/{id}/verification

Sends the identity details and document images to the card issuer. Returns 202 with verification.status in_review. The decision arrives with the cardholder.kyc_updated event. After a rejection, call it again with corrected details. If the cardholder is already verified, returns 200 with no change; while a review is in progress, documents are not sent again. The first name, last name and birth date must match the document exactly. Verification is per business: a person already verified by another business is verified again for yours. Limited to 5 calls per cardholder per 24 hours.

Key roles: Owner or Finance

Path parameters
idstringRequired

ID of the cardholder.

Body
id_numberstringRequired

Document number, same rules as on creation (passport: 6 to 9 letters or digits; other documents: 4 to 30 characters).

birth_datestringOptional

YYYY-MM-DD, 18 or older. Defaults to the cardholder’s birth_date.

place_of_birthstringRequired

City of birth, as on the document. 2 to 60 characters, no digits.

addressobjectRequired

Home address. Accents are accepted and sent without them.

Show child attributes
line1stringRequired

3 to 100 characters: letters, digits, spaces and , . - only.

line2stringOptional

Optional. Same characters as line1, up to 100.

citystringRequired

2 to 60 characters, no digits.

statestringRequired

Region, province or state. 2 to 60 characters, no digits.

postal_codestringOptional

Optional. 1 to 10 letters, digits, spaces or hyphens. Leave it out where there is none.

documentsobjectOptional

Photos of the document, as base64 or data:image/…;base64, URIs. JPEG or PNG, 4 MB each at most, at least 600 × 400 px (document_invalid otherwise). Sharp, uncropped, without glare, with the whole document visible. Optional when the photos were sent on creation (verification.documents_on_file); if sent, they replace them.

Show child attributes
frontstringRequired

Front side (photo page of a passport).

backstringOptional

Back side. Required, except for a passport.

phonestringOptional

Only if the cardholder has none. Same rules as on creation.

Returns

Returns the cardholder object with 202: the outcome follows by webhook.

Errors worth handling
HTTPCodeDescription
400parameter_missingA required parameter is missing. See param.
400parameter_invalidA parameter has the wrong type or value. See param.
400phone_invalidThe number cannot be read as an international number.
400document_invalidA document image is not accepted: JPEG or PNG only, 4 MB at most, at least 600 × 400 px. param names the side.
400cardholder_underageThe cardholder must be at least 18 years old.
402identity_already_registeredThe card issuer already holds this identity for a pending or completed verification. Contact support.
402verification_declinedThe card issuer declined the verification submission. Check the details and document images, then submit again.
403permission_deniedThe key’s creator does not have the role required for this operation.
429rate_limitedA rate limit was reached. Wait for Retry-After seconds. See Rate limits.
curl https://api.monerails.com/v1/cardholders/5df6acd9-4bac-4e19-869c-fcde6b79f389/verification \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id_number": "CM12345678",
    "birth_date": "1991-02-03",
    "place_of_birth": "Douala",
    "address": {
      "line1": "12 rue Joss",
      "city": "Douala",
      "state": "Littoral"
    },
    "documents": {
      "front": "data:image/jpeg;base64,/9j/4AAQ…",
      "back": "data:image/jpeg;base64,/9j/4AAQ…"
    }
  }'
Response202
{
  "id": "5df6acd9-4bac-4e19-869c-fcde6b79f389",
  "object": "cardholder",
  "livemode": false,
  "type": "customer",
  "first_name": "Awa",
  "last_name": "Ndiaye",
  "email": "awa@example.com",
  "phone": "+237670000999",
  "country": "CM",
  "city": "Douala",
  "birth_date": "1991-02-03",
  "id_document": "national_id",
  "id_number_last4": "3408",
  "verification": {
    "status": "in_review",
    "reason": null,
    "verified_at": null,
    "documents_on_file": true
  },
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:09.807Z"
}

Retrieve a cardholder

GET/v1/cardholders/{id}

Key roles: Every role

Path parameters
idstringRequired

ID of the cardholder.

Returns

Returns the cardholder object.

curl https://api.monerails.com/v1/cardholders/5df6acd9-4bac-4e19-869c-fcde6b79f389 \
  -H "Authorization: Bearer $MONERAIL_KEY"
Response200
{
  "id": "5df6acd9-4bac-4e19-869c-fcde6b79f389",
  "object": "cardholder",
  "livemode": false,
  "type": "customer",
  "first_name": "Awa",
  "last_name": "Ndiaye",
  "email": "awa@example.com",
  "phone": "+237670000999",
  "country": "CM",
  "city": "Douala",
  "birth_date": "1991-02-03",
  "id_document": "national_id",
  "id_number_last4": "3408",
  "verification": {
    "status": "verified",
    "reason": null,
    "verified_at": "2026-10-30T13:47:09.807Z"
  },
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:06.394Z"
}

List cardholders

GET/v1/cardholders

Newest first.

Key roles: Every role

Query parameters
limitintegerOptionalDefault 20

Number of objects to return, 1 to 100.

starting_afterstringOptional

Cursor: the ID of the last object of the previous page.

Returns

Returns a list object: data holds up to limit cardholder objects, and has_more tells whether more follow.

curl "https://api.monerails.com/v1/cardholders?limit=10" \
  -H "Authorization: Bearer $MONERAIL_KEY"
Response200
{
  "object": "list",
  "url": "/v1/cardholders",
  "data": [
    {
      "id": "5df6acd9-4bac-4e19-869c-fcde6b79f389",
      "object": "cardholder",
      "livemode": false,
      "type": "customer",
      "first_name": "Awa",
      "last_name": "Ndiaye",
      "email": "awa@example.com",
      "phone": "+237670000999",
      "country": "CM",
      "city": "Douala",
      "birth_date": "1991-02-03",
      "id_document": "national_id",
      "id_number_last4": "3408",
      "verification": {
        "status": "pending",
        "reason": null,
        "verified_at": null,
        "documents_on_file": true
      },
      "created_at": "2026-10-30T13:47:06.394Z",
      "updated_at": "2026-10-30T13:47:06.394Z"
    }
  ],
  "has_more": false
}