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

NameInTypeRequiredDescription
id path string yes User identifier.

Request body

application/json · CreateCardholderRequest · required

FieldTypeRequiredDescription
accountId string yes Account ID that determines the provider.
bin string yes BIN code to determine the card type.

Responses

StatusBodyDescription
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.