Freeze Card
Freezes an active virtual card. Once frozen the card cannot be used for any payment/authorization until you unfreeze it.
- The freeze is recorded as a user-initiated freeze and can be reversed by the Unfreeze Card endpoint.
- Only cards owned by the current
AppIDaccount and of a virtual card type are accepted. - No money moves — freezing/unfreezing has no fee and does not touch the card balance or your wallet.
Endpoint
| Item | Value |
|---|---|
| Method | POST |
| Path | /api/v1/openapi/card/freeze |
| Auth | HMAC |
| Idempotency | Not required |
No Idempotency-Key needed
Freeze is naturally idempotent-safe: retrying on an already-frozen card returns 400 card_already_frozen rather than double-applying. There is no monetary effect to protect against, so no Idempotency-Key header is required.
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
card_id | string | ✅ | card_<id> — must belong to your account and be a virtual card |
reason | string | optional | Free-text reason recorded with the freeze (max 255 chars) |
Example Request
json
{
"card_id": "card_12345",
"reason": "suspected fraud on merchant side"
}Response Fields
| Field | Type | Description |
|---|---|---|
card_id | string | Echo of the card ID |
status | int | Card status after the operation — always 6 (frozen) on success |
status_desc | string | English status description — frozen |
success | bool | true on success |
Example Response
json
{
"code": 200,
"message": "OK",
"data": {
"card_id": "card_12345",
"status": 6,
"status_desc": "frozen",
"success": true
}
}Preconditions & Rules
- Ownership —
card_idmust belong to the authenticated account, else404 card_not_found(no distinction from "not found", to prevent enumeration). - Card type — only virtual cards (
virtual_l/virtual_p/virtual_v/virtual_r/virtual_g/virtual_a) may be operated via OpenAPI. - State — only
status=2 (active)cards may be frozen. Apending/failed/closing/closed/ already-frozencard is rejected.
Common Errors
| HTTP | message_key | Description |
|---|---|---|
| 400 | openapi_invalid_card_id | Missing/invalid card_id |
| 400 | openapi_card_type_not_supported | Card is not a virtual card type |
| 400 | card_already_frozen | Card is already frozen |
| 400 | card_status_cannot_freeze | Card is not active; cannot be frozen |
| 400 | operation_not_supported | This provider/card type does not support freeze |
| 401 | openapi_invalid_credentials | Auth failure |
| 404 | card_not_found | Card not found / not owned |
| 500 | openapi_freeze_card_failed | Server error |
Notes
- After a successful freeze,
/card/inforeportsstatus=6. - To reverse, call Unfreeze Card. Only user-initiated freezes (this endpoint) are reversible by you; freezes applied by risk-control/admin are not.
Integration pitfalls & best practices
Read before integrating
These are the failure modes most likely to leave your system's card-state / bookkeeping out of sync with reality.
- Synchronous, provider-bound call — allow up to ~60 s. Freeze calls the upstream card provider inline. Latency is usually a few seconds but can reach 10–15 s, and the server permits up to 60 s. Set your HTTP client timeout to ≥ 60 s for this endpoint. A short timeout (10–30 s) invites pitfall #2.
- A client-side timeout does NOT mean the freeze failed. If your client times out (or the connection drops) after the provider already froze the card, you get an error but the card is frozen — a silent divergence. Never record a timeout as "not frozen". On any timeout / network error, reconcile via
/card/info:status=6→ freeze succeeded (proceed);status=2→ not applied (safe to retry). - No webhook for freeze/unfreeze. The synchronous response is the only signal — this operation does not emit an asynchronous
card.*webhook. Do not wait for a callback; treat the response (or/card/info) as the source of truth. - No
Idempotency-Key, but safe to retry. Retries are not deduplicated (each one hits the provider), but the card state machine protects you: re-freezing an already-frozen card returns400 card_already_frozen. Treatcard_already_frozenas "already in the desired state", not a hard error. Prefer the reconcile-via-/card/infopattern over blind retry loops. - Freeze only blocks new payments. It does not reverse authorizations already approved before the freeze, and moves no money (no fee, balance untouched).