Cardholders are the end users who receive and use cards. Each cardholder belongs to a single partner and must complete KYC before cards can be issued.
Create a cardholder
curl -X POST https://api.contro.me/v1/partner/cardholders \
-H "x-contro-api-key: $CONTRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"externalUserId": "your_user_id",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane@example.com",
"phoneNumber": "+1234567890",
"metadata": { "plan": "premium" }
}'
Required fields
| Field | Type | Description |
|---|
externalUserId | string | Your unique identifier for this user. Min 1 character. Example: "user_42" |
firstName | string | Cardholder’s first name. Min 1 character. Example: "Jane" |
lastName | string | Cardholder’s last name. Min 1 character. Example: "Doe" |
email | string | Valid email address. Example: "jane@example.com" |
Optional fields
| Field | Type | Description |
|---|
phoneNumber | string | E.164 formatted phone number. Example: "+14155552671" |
metadata | object | Arbitrary key-value pairs for your use. Example: { "plan": "premium", "tier": "gold" } |
KYC verification
Cards cannot be issued until a cardholder’s KYC status is approved. The KYC flow has two steps:
Initiate KYC
curl -X POST https://api.contro.me/v1/partner/cardholders/{id}/kyc \
-H "x-contro-api-key: $CONTRO_API_KEY"
Check KYC status
curl https://api.contro.me/v1/partner/cardholders/{id}/kyc \
-H "x-contro-api-key: $CONTRO_API_KEY"
Response:
{
"kycStatus": "approved"
}
KYC status lifecycle
| Status | Description |
|---|
pending | KYC has been initiated, verification in progress |
approved | Verification passed — cards can be issued |
rejected | Verification failed — review and retry |
In sandbox mode, KYC is auto-approved for testing. In production, verification is performed by the KYC provider.
Update a cardholder
Update mutable fields on an existing cardholder:
curl -X PATCH https://api.contro.me/v1/partner/cardholders/{id} \
-H "x-contro-api-key: $CONTRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "jane.doe@newdomain.com",
"metadata": { "plan": "enterprise" }
}'
Updatable fields: firstName, lastName, email, phoneNumber, metadata.
List cardholders
Retrieve cardholders with optional filtering:
curl "https://api.contro.me/v1/partner/cardholders?limit=20&status=active&kycStatus=approved" \
-H "x-contro-api-key: $CONTRO_API_KEY"
Query parameters
| Parameter | Type | Description |
|---|
cursor | string | Pagination cursor from the previous response’s nextCursor |
limit | integer | Items per page (1–100, default 20). Example: 50 |
status | string | Filter by cardholder status. One of active, suspended, closed |
kycStatus | string | Filter by KYC status. One of pending, approved, rejected |
Get a cardholder
Retrieve a single cardholder by ID:
curl https://api.contro.me/v1/partner/cardholders/{id} \
-H "x-contro-api-key: $CONTRO_API_KEY"
Response fields
| Field | Type | Description |
|---|
id | string | Contro cardholder ID. Example: "ch_abc123" |
externalUserId | string | Your user identifier. Example: "user_42" |
firstName | string | First name. Example: "Jane" |
lastName | string | Last name. Example: "Doe" |
email | string | Email address. Example: "jane@example.com" |
phoneNumber | string | null | E.164 phone number, or null if not provided. Example: "+14155552671" |
kycStatus | string | KYC verification status. One of pending, approved, rejected |
status | string | Cardholder account status. One of active, suspended, closed |
metadata | object | null | Custom metadata, or null if not set. Example: { "plan": "premium" } |
createdAt | string | ISO 8601 creation timestamp. Example: "2026-03-20T14:30:00Z" |