Create a cardholder for the given user. Personal data is read from the user's `meta` field (see required fields below). What the endpoint does depends on the BIN's `providerCardHolderModel`: - **B2B** — short form. Only `firstName`, `lastName` and `email` are required in the user's `meta`; no identity data is collected or sent anywhere. The response already carries `status: "pass_audit"`, so the cardholder can be used to issue a card immediately — there is no review step to poll for. Calling it again for the same user and BIN returns the existing cardholder. - **B2C** — full identity check. Every field below is required, the user's KYC must be `completed`, and the cardholder goes through async review (`pending_review` → `wait_audit` → `pass_audit` / `reject`). **Required user `meta` fields for a B2C cardholder:** | Field | Type | Constraints | |-------|------|-------------| | `firstName` | string | Latin letters, space, hyphen, apostrophe and period only; must start with a letter; max 40 chars. `TEST`, `MOCK` and `SANDBOX` are rejected as substrings — a real legal name is required, also in sandbox. | | `lastName` | string | Same rules as `firstName`. | | `email` | string | **Max 50 chars.** 3DS OTP codes are sent here. A placeholder built from a full UUID (e.g. `no-reply+<uuid>@example.com`, 56 chars) does not fit — use a shortened alias. | | `phone` | string | Digits only, 7–15 digits, **without** the country code. Must be a **mobile** number for `country` — a landline is rejected (e.g. an Argentine number missing its `9` mobile token). | | `phoneCode` | string | `+` followed by 1–4 digits, e.g. `"+371"`. A missing `+` is added automatically. | | `birthday` | string | Date of birth, `YYYY-MM-DD`. | | `country` | string | Country code from `/v1/cardholders/regions`; validated against the live list. | | `town` | string | City code from `/v1/cardholders/cities?region=<country>`; validated against the live list. A free-text city name is rejected. | | `address` | string | Letters, digits, hyphens and spaces only — **no commas, periods, `#`, `/` or other punctuation** — max 40 chars. Keep it ASCII: accented or non-Latin letters are rejected by the card provider. | | `postCode` | string | Letters and digits only, max 15 chars. Spaces are stripped automatically (`SW3 4RP` → `SW34RP`); hyphens and other punctuation are rejected. | **Identity fields, B2C only:** | Field | Type | Constraints | |-------|------|-------------| | `gender` | string | `"M"` or `"F"`. | | `idType` | string | One of `PASSPORT`, `DLN`, `HK_HKID`, `GOVERNMENT_ISSUED_ID_CARD` (case-insensitive). A national ID card is `GOVERNMENT_ISSUED_ID_CARD` — `NATIONAL_ID` is rejected. | | `idNo` | string | Document number. | | `idIssueDate` | string | Document issue date, `YYYY-MM-DD`. **Required**, even though the schema marks it optional. | | `idExpiryDate` | string | Document expiry date, `YYYY-MM-DD`. Optional, but must not be earlier than `idIssueDate`. | | `nationality` | string | Country code, see `/v1/cardholders/regions`. | | `occupation` | string | Occupation code, see `/v1/cardholders/occupations`. | | `annualSalary` | string | Annual salary range (optional, free text). | | `accountPurpose` | string | Purpose of the account (optional, free text). | | `expectedMonthlyVolume` | string | Expected monthly transaction volume (optional, free text). | | `ipAddress` | string | User's IP address (optional). | **Where the rules are enforced** `POST /v1/users` and `PATCH /v1/users/{id}` store `meta` as given and do **not** validate it. Everything above is checked here and in `PATCH /v1/cardholders/{id}`, and a violation comes back as `400` with the offending field in the message — so validate at the point your user fills the form rather than at card issuance. Length limits count bytes, so a non-ASCII character consumes more than one of the 40/50 budget. On a **B2B** BIN only `firstName`, `lastName` and `email` are read and validated (same name and length rules as above); the identity fields are neither required nor used. `email` must be unique per BIN — reusing one that another cardholder on the same BIN already holds is rejected with `ErrAlreadyExists`. **B2C requirements:** - User must have KYC status `completed` before calling this endpoint. - KYC documents (idFrontImg, idBackImg, idHoldImg) are automatically uploaded from the KYC system.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | string |
yes | User identifier. |
Request body
application/json
· CreateCardholderRequest
· required
| Field | Type | Required | Description |
|---|---|---|---|
accountId |
string |
yes | Account ID that determines the provider. |
bin |
string |
yes | BIN code to determine the card type. |
Responses
| Status | Body | Description |
|---|---|---|
201 |
CardholderResponse |
Cardholder created (status will be pending_review until admin approves). |
400 |
Error |
Missing personal data or invalid request. |
404 |
Error |
User not found. |
412 |
Error |
B2C only: KYC not completed or required documents missing. |
Specification
This page is generated from the OpenAPI specification, which remains the authoritative machine-readable source.