Create cardholder KYC session
POST /v1/api-gateway/cardholder/kyc
Starts (or resumes) hosted KYC for the cardholder identified by end_. If no cardholder with that id exists it is created under your organization. When a verification session issued less than 7 days ago is still valid its existing url is returned; when the cardholder already has a KYC session in a state that cannot be restarted, url is null and status tells you where it stands. Returns 200 (not 201). API-key (B2B) credentials only.
Request
Authentication: your API key in the x-api-key header.
Headers
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | A unique string you choose, up to 255 characters, that makes this request safe to retry. If a request times out or fails in transit, send it again with the same key: the status code and body of the first attempt are returned and the operation is not performed a second time. Stored replies — including failures — are replayed for 24 hours, after which the same key starts a fresh request. Reusing a key for a different request, or sending it while the first request is still running, returns 409. Omit the header and the request behaves exactly as before. Document upload endpoints do not accept it. |
Body
| Field | Type | Description |
|---|---|---|
external_ | string | Your identifier for the cardholder (not the Moon cardholder id). If no cardholder with this id exists in your top-level organization, one is created. Must not be empty. Required — send it as external_ or as end_. |
end_ | string | Deprecated alias of external_, kept working for existing integrations. Send one or the other; sending both with different values is rejected. |
Example request
cURL
curl --request POST \
--url 'https://api.themooncard.com/v1/api-gateway/cardholder/kyc' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'content-type: application/json' \
--data '{
"external_id": "customer_123",
"end_customer_id": "customer_123"
}'Responses
200 Success
| Field | Type | Description |
|---|---|---|
url required | string, nullable | Hosted verification link to send the cardholder to. Null when the cardholder already has a KYC session in a state that cannot be restarted. |
status required | string | Current KYC status, e.g. NOT_, IN_, APPROVED, DECLINED, RETRY. |
JSON
{
"url": "https://verify.paywithmoon.com/kyc?token=eyJhbGciOiJIUzI1NiJ9.xyz789",
"status": "NOT_STARTED"
}400 Error
Validation failed (end_ is required), or the request was not made with an API key ("This endpoint is only available for API key (B2B) requests.").
The body is the standard error object: see Errors.
401 Error
Missing or invalid credentials, e.g. { "message": "Invalid API Key", "code": "UNAUTHORIZED" }.
The body is the standard error object: see Errors.
403 Error
KYC is temporarily unavailable ("KYC is temporarily unavailable.").
The body is the standard error object: see Errors.
404 Error
Your organization could not be found (ORGANIZATION_).
The body is the standard error object: see Errors.
409 Error
The Idempotency-Key you sent is already in use. IDEMPOTENCY_ — the key was used for a different request; send a new key, or repeat the original request exactly to receive its stored response. IDEMPOTENCY_ — the first request with this key has not finished yet; retry in a few seconds.
The body is the standard error object: see Errors.
500 Error
Unexpected server error. Body is { message: "Internal server error", code: "INTERNAL_.
The body is the standard error object: see Errors.
Last updated April 30, 2026