Cardholders
Cardholders are managed users your business creates and controls. You can issue physical or virtual cards to them, fund their wallets, and monitor spending — all programmatically.
Full Lifecycle
1. Create cardholder
2. Complete KYC (via SumSub token)
3. Issue a card
4. Fund the cardholder's wallet
5. Manage card — freeze/unfreeze, set limits, view secrets
6. Monitor transactions
7. Recall unused fundsCardholder Object
{
"id": "uuid",
"business_id": "uuid",
"name": "Bob Jones",
"email": "bob@yourcompany.com",
"username": "bob_abc123",
"is_kyc_verified": false,
"created_at": "2026-03-16T10:00:00Z"
}Card Object
{
"id": "uuid",
"user_id": "uuid",
"catalogue_id": "uuid",
"status": "active",
"ctype": "virtual",
"last4": "4242",
"exp_month": "03",
"exp_year": "2029",
"spend_tx_max": 100000,
"spend_daily_max": 500000,
"spend_monthly_max": 2000000,
"spend_online_enabled": true,
"spend_present_enabled": false,
"created_at": "2026-03-16T10:00:00Z"
}Card status values: notActivated | active | locked | canceled
Step 1 — Create Cardholder
POST /v1/cardholdersBody
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | Full name |
email | string | Email address |
Example
curl -X POST https://api-test.dpt.xyz/v1/cardholders \
-H "Authorization: Bearer dptb_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Bob Jones", "email": "bob@yourcompany.com" }'Response 200
Returns the Cardholder object. Note the id — you will need it for all subsequent calls.
Step 2 — Start KYC
Returns a SumSub SDK token. Embed the SumSub Web SDK in your app and pass the token to collect the cardholder's identity documents.
POST /v1/cardholders/{id}/kycResponse 200
{ "token": "sumsub_sdk_token_..." }After the cardholder completes verification, is_kyc_verified becomes true. KYC status is updated automatically via webhook from SumSub — no polling needed.
Step 3 — Issue a Card
The cardholder must be KYC-verified before a card can be issued.
POST /v1/cardholders/{id}/cardsBody
| Field | Type | Required | Description |
|---|---|---|---|
catalogue | uuid | ✓ | Card product ID (get from dashboard) |
type | string | ✓ | virtual or physical |
Example
curl -X POST https://api-test.dpt.xyz/v1/cardholders/CH_ID/cards \
-H "Authorization: Bearer dptb_..." \
-H "Content-Type: application/json" \
-d '{ "catalogue": "CATALOGUE_UUID", "type": "virtual" }'Step 4 — Fund Cardholder
Transfer funds from your business wallet to the cardholder's wallet.
POST /v1/cardholders/{id}/fundBody
| Field | Type | Required | Description |
|---|---|---|---|
amount | integer | ✓ | Amount in smallest unit |
currency | string | ✓ | e.g. USDC |
remark | string | Optional memo |
Example
curl -X POST https://api-test.dpt.xyz/v1/cardholders/CH_ID/fund \
-H "Authorization: Bearer dptb_..." \
-H "Content-Type: application/json" \
-d '{ "amount": 1000000000, "currency": "USDC" }'Returns 204 No Content.
List Cardholders
GET /v1/cardholdersGet Cardholder
GET /v1/cardholders/{id}Recall Funds
Pull unused funds back from a cardholder's wallet to your business wallet.
POST /v1/cardholders/{id}/recallSame body as Fund Cardholder. Returns 204 No Content.
List Cardholder Cards
GET /v1/cardholders/{id}/cardsGet Card
GET /v1/cardholders/{ch_id}/cards/{card_id}Update Card (Freeze / Unfreeze)
PATCH /v1/cardholders/{ch_id}/cards/{card_id}Body
| Field | Type | Required | Description |
|---|---|---|---|
status | string | ✓ | active to unfreeze, locked to freeze |
Update Card Spending Limits
PUT /v1/cardholders/{ch_id}/cards/{card_id}/limitsBody
| Field | Type | Description |
|---|---|---|
spend_tx_max | integer | Max per-transaction amount (cents/micro-units) |
spend_daily_max | integer | Max daily spend |
spend_monthly_max | integer | Max monthly spend |
spend_online_enabled | bool | Allow online / card-not-present transactions |
spend_present_enabled | bool | Allow in-person / contactless transactions |
Get Card Secrets (PAN + CVV)
Returns the full card number and CVV, encrypted with Rain's public key. You must use the Rain Secure SDK to decrypt and display these to the cardholder.
POST /v1/cardholders/{ch_id}/cards/{card_id}/secretsBody
| Field | Type | Required | Description |
|---|---|---|---|
session | string | ✓ | Session token from Rain Secure SDK |
encrypted_data | object | Additional encrypted payload if required |
Response 200
{
"encryptedCvc": { "iv": "...", "data": "..." },
"encryptedPan": { "iv": "...", "data": "..." }
}Get Card PIN
GET /v1/cardholders/{ch_id}/cards/{card_id}/pinSame request body as Get Secrets.
Response 200
{
"encryptedPin": { "iv": "...", "data": "..." }
}Set Card PIN
PUT /v1/cardholders/{ch_id}/cards/{card_id}/pinBody
| Field | Type | Required | Description |
|---|---|---|---|
session | string | ✓ | Session token from Rain Secure SDK |
encrypted_data | object | ✓ | New PIN encrypted with Rain's public key |
Returns 200 OK.
List Card Transactions
GET /v1/cardholders/{ch_id}/cards/{card_id}/transactionsReturns the most recent card transactions for this card.
Response 200
[
{
"id": "uuid",
"amount": -50000,
"currency": "USDC",
"description": "Starbucks #1234",
"status": "completed",
"created_at": "2026-03-16T09:00:00Z"
}
]