List Cards
List all bank cards owned by the current AppID. Supports status / date-range / balance-range filters and pagination.
Key behaviors:
- Virtual cards only — the response is force-filtered to virtual cards (
virtual_l/virtual_p/virtual_v/virtual_r/virtual_g/virtual_a); physical cards are never exposed via OpenAPI. - Default behavior — when neither
statusesnorusable_onlyis provided, the server returnsstatus ∈ [1, 2](pending + active) by default, hiding failed / closed / frozen historical cards. - List endpoint does not carry sensitive fields — the list response never includes full PAN / CVV / expiry / cardholder name, regardless of credential permissions. For those fields, use
/openapi/card/infowithwith_sensitive=true(per-card, opt-in, authorized via the account's second-factor verification or a verification-exempt credential).
Endpoint
| Item | Value |
|---|---|
| Method | POST |
| Path | /api/v1/openapi/cards/list |
| Auth | HMAC |
| Idempotency | Not required |
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
statuses | int[] | optional | Status filter array, allowed values 1 2 3 4 5 6; mutually exclusive with usable_only |
usable_only | bool | optional | Convenience filter: true is equivalent to statuses=[2]; mutually exclusive with statuses |
start_date | string | optional | Lower bound of creation date, format YYYY-MM-DD |
end_date | string | optional | Upper bound of creation date, format YYYY-MM-DD (inclusive) |
min_balance | string | optional | Minimum balance (decimal string, e.g. "10.5") |
max_balance | string | optional | Maximum balance (decimal string) |
page | int | optional | Page number, min 1, default 1 |
page_size | int | optional | Page size, 1–100, default 20 |
Card Status Values
| status | Meaning | Included by default? |
|---|---|---|
| 1 | pending (opening / KYC review) | ✅ |
| 2 | active | ✅ |
| 3 | failed (open failed) | ❌ (must pass statuses=[3]) |
| 4 | closing | ❌ |
| 5 | closed | ❌ |
| 6 | frozen | ❌ |
Why hide failed/closed/frozen by default
To prevent merchants from accidentally treating dead cards as usable. For reconciliation or audit work, pass statuses explicitly.
Example Requests
1. Default query (usable cards only: pending + active)
curl -X POST "${baseUrl}/api/v1/openapi/cards/list" \
-H "Content-Type: application/json" \
-H "X-App-Id: cp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Timestamp: 1715251200" \
-H "X-Nonce: 9b5603a21d2d4e1d" \
-H "X-Signature: <hmac_sha256_hex>" \
-d '{}'2. Active cards only (immediately usable)
{ "usable_only": true }3. Custom statuses (include historical cards)
{
"statuses": [2, 5, 6],
"page": 1,
"page_size": 50
}4. Balance + date range filter
{
"min_balance": "10",
"max_balance": "1000",
"start_date": "2026-01-01",
"end_date": "2026-12-31"
}Response Fields
Envelope
| Field | Type | Description |
|---|---|---|
list | CardListItemOut[] | Array of cards (see below) |
total | int64 | Total record count |
page | int | Current page number |
page_size | int | Page size |
total_pages | int | Total page count |
has_next | bool | Whether a next page exists |
has_prev | bool | Whether a previous page exists |
CardListItemOut
| Field | Type | Description |
|---|---|---|
card_id | string | card_<id> — usable as input to /card/info, /card/recharge, etc. |
card_type | string | Lowercase: virtual_l / virtual_p / virtual_v / virtual_r / virtual_g / virtual_a |
card_brand | string | Brand display name: Visa / Mastercard |
card_holder_name | string | Cardholder name (provided at apply time) |
currency | string | Card currency, ISO 4217 (e.g. USD) |
status | int | 1=pending 2=active 3=failed 4=closing 5=closed 6=frozen |
status_desc | string | English description: pending / active / failed / closing / closed / frozen |
masked_card_no | string | Masked PAN (first 6 + last 4) |
last_four | string | Last 4 digits |
balance | string (decimal) | Available balance |
frozen_balance | string (decimal) | Frozen balance |
freeze_type | int | Freeze type: 0=none 1=user 2=system 3=admin 4=risk-control |
nickname | string | Card nickname (optional) |
activated_at | string nullable | Activation time (RFC3339) |
created_at | string | Creation time (RFC3339) |
No sensitive cardholder data in the list response
The list response never includes the full card number, CVV, card expiry, or cardholder first/last name — these fields are not part of this endpoint's contract under any circumstances. Internal-only fields (DB identifiers, provider-side references, intermediate stats, internal labels) are likewise not exposed.
To retrieve full PAN / CVV / expiry / cardholder name for a single active card, call /openapi/card/info with with_sensitive=true, passing the account's second-factor verification codes (or using a verification-exempt credential).
Example Response
{
"code": 200,
"message": "OK",
"data": {
"list": [
{
"card_id": "card_133",
"card_type": "virtual_r",
"card_brand": "Visa",
"card_holder_name": "John Doe",
"currency": "USD",
"status": 2,
"status_desc": "active",
"masked_card_no": "493724******4245",
"last_four": "4245",
"balance": "37.72",
"frozen_balance": "0.00",
"freeze_type": 0,
"nickname": "Primary card",
"activated_at": "2026-05-09T01:06:25Z",
"created_at": "2026-05-08T10:55:12Z"
}
],
"total": 1,
"page": 1,
"page_size": 20,
"total_pages": 1,
"has_next": false,
"has_prev": false
}
}Empty Response
{
"code": 200,
"message": "OK",
"data": {
"list": [],
"total": 0,
"page": 1,
"page_size": 20,
"total_pages": 0,
"has_next": false,
"has_prev": false
}
}Common Errors
| HTTP | message_key | Description |
|---|---|---|
| 400 | openapi_conflicting_card_filters | Do not pass usable_only and statuses at the same time |
| 400 | openapi_invalid_status_value | statuses may only contain values 1–6 |
| 400 | invalid_min_balance | min_balance must be a valid non-negative decimal string |
| 400 | invalid_max_balance | max_balance must be a valid non-negative decimal string |
| 400 | min_balance_exceeds_max_balance | min_balance must not exceed max_balance |
| 400 | invalid_date_format | Dates must be in YYYY-MM-DD format |
| 401 | openapi_invalid_credentials | HMAC / timestamp / nonce / credential check failed |
| 500 | openapi_list_cards_failed | Server error — retry with backoff |
Notes
- Resource ownership — only cards belonging to the user_id behind the current
X-App-Idare returned. Even after secret rotation, the list of cards a merchant sees stays consistent (credentials are isolated per user_id). - Physical cards filtered — this endpoint hard-filters to virtual cards only. Even if a merchant opened a physical card via the user portal, it won't appear here.
- Historical cards —
status ∈ {3, 4, 5, 6}is hidden by default. For reconciliation, passstatuses=[5]etc. explicitly. - Relation to other endpoints:
- With
card_idin hand, call/openapi/card/infofor single-card detail. - Call
/openapi/card/rechargeto top up. - Important: only
status=2cards can be recharged; otherwise the server returnsinvalid_card_status.
- With
- Treat
card_idas an opaque string — store it as a string on your side rather than parsing the numeric portion. Future ID encoding migrations should not require schema changes on your end.