Close Card
Submits an irreversible close (cancellation) request for an active virtual card. The call is accepted synchronously — the card immediately enters status=4 (closing) — while the actual closure and the balance refund complete asynchronously via webhook + platform review.
- Only cards owned by the current
AppIDaccount and of a virtual card type are accepted. - Only
status=2 (active)cards can be closed; afrozen(6)card must be unfrozen first. - The remaining card balance is refunded to your wallet after platform review, per the card package's close-fee rules — the refund is not instant.
Endpoint
| Item | Value |
|---|---|
| Method | POST |
| Path | /api/v1/openapi/card/close |
| Auth | HMAC |
| Idempotency | Not required |
No Idempotency-Key needed
Close is protected by the card state machine: retrying returns 400 card_is_closing (in progress) or 400 card_already_closed (done) rather than double-applying. The submission itself moves no money.
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
card_id | string | ✅ | card_<id> — must belong to your account and be a virtual card |
Example Request
json
{ "card_id": "card_12345" }Response Fields
| Field | Type | Description |
|---|---|---|
card_id | string | Echo of the card ID |
status | int | Card status after acceptance — always 4 (closing) on success |
status_desc | string | English status description — closing |
success | bool | true when the close request was accepted |
message | string | Human-readable acceptance note |
Example Response
json
{
"code": 200,
"message": "OK",
"data": {
"card_id": "card_12345",
"status": 4,
"status_desc": "closing",
"success": true,
"message": "close request accepted"
}
}Lifecycle after acceptance
- Acceptance — this call returns
status=4 (closing); the card can no longer be used for payments. - Provider closure — the upstream provider confirms the closure asynchronously; you receive the
card.closedwebhook and/card/infostarts reportingstatus=5 (closed). - Refund review — the remaining balance (minus the package's close fee) enters the platform's refund review; once approved it is credited to your wallet. Rejection restores the card to active — monitor
card.status_changed.
Preconditions & Rules
- Ownership —
card_idmust belong to the authenticated account, else404 card_not_found. - Card type — only virtual cards (
virtual_l/virtual_p/virtual_v/virtual_r/virtual_g/virtual_a). - State — only
status=2 (active);frozen(6)must be unfrozen first (card_frozen_cannot_close); repeat calls hitcard_is_closing/card_already_closed. - Irreversible — once accepted the closure cannot be cancelled by you.
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_is_closing | A close request is already in progress |
| 400 | card_already_closed | Card is already closed |
| 400 | card_frozen_cannot_close | Card is frozen — unfreeze first |
| 400 | card_status_cannot_close | Card is not active; cannot be closed |
| 400 | close_not_accepted_by_upstream | Provider did not accept the closure; the card has been restored to active — retry later |
| 400 | card_upstream_closed_pending_reconcile | Card was already closed directly by the provider and awaits manual refund reconciliation — do not close here |
| 400 | card_config_not_found / card_type_mismatch / operation_not_supported | Configuration / card-type problems |
| 401 | openapi_invalid_credentials | Auth failure |
| 404 | card_not_found | Card not found / not owned |
| 500 | openapi_close_card_failed | Server error |
Integration pitfalls & best practices
Read before integrating
Close is the highest-consequence card operation: irreversible, provider-bound, and money moves later via review.
- Synchronous, provider-bound call — allow up to ~60 s. The submission calls the upstream provider inline. Set your HTTP client timeout to ≥ 60 s for this endpoint.
- A client-side timeout does NOT mean the close failed. On any timeout / network error, reconcile via
/card/info:status=4/5→ accepted (do not resubmit as a "new" close);status=2→ not applied (safe to retry). - Completion signal is asynchronous. Treat the
card.closedwebhook (or polling untilstatus=5) as completion — the synchronous response only means "accepted". - Refund is not instant and not guaranteed to equal the last seen balance. It passes platform review and deducts the package close fee; a rejected review restores the card to active. Reconcile your books against the wallet credit, not against the pre-close card balance.
close_not_accepted_by_upstreamauto-rolls back. The card is already restored toactivewhen you receive this error — no cleanup needed on your side, just retry later.- Treat
card_is_closing/card_already_closedas "already in the desired state", not hard errors, when retrying.