Skip to main content
Freeze, close, and other sensitive card updates use Grid’s 202 → signed-retry pattern — the same one used by Embedded Wallet credential revocation and wallet export. This page covers the flow, what each transition does, and how to handle the signing step. PATCH /cards/{id} covers freeze / unfreeze (state), funding source updates (fundingSources), and per-transaction spending limits (maxSpendPerTransaction). See Funding sources for the funding-source-only flow. The signed-retry mechanics below apply to all fields.

Valid state transitions

Any other transition returns 409 INVALID_STATE_TRANSITION. In particular, you cannot un-freeze a CLOSED card — close is terminal. You can also combine a state change with a funding source replacement in one PATCH — just include both fields in the body.

The signed-retry flow

Each request follows the same two-call shape:
The signature is produced with the session private key of a verified authentication credential on the card’s owning internal account.

Step 1 — initial call

Response — 202 Accepted:

Step 2 — signed retry

Sign payloadToSign with the session private key of a verified authentication credential on the card’s owning internal account, then retry the same request with the signature and the request id echoed back:
Response — 200 OK with the updated Card and a CARD.STATE_CHANGE webhook.
The signing flow is identical to the one used by Embedded Wallet credential revocation. If you’ve already wired that up, you can reuse the same key-handling code for cards.

What freeze does

Setting a card to FROZEN:
  • Causes Authorization Decisioning to decline new auths with CARD_PAUSED.
  • Does not pause the lifecycle of authorizations that already passed. Pulls, clearings, and refunds against existing transactions continue to reconcile normally.
  • Emits CARD.STATE_CHANGE with state: "FROZEN".
Unfreeze (state: "ACTIVE") reverses this — new auths flow normally again.

What close does

Closing a card is done with the same PATCH /cards/{id} endpoint by setting state: "CLOSED". The operation is permanent:
  • Card state transitions to CLOSED, stateReason: "CLOSED_BY_PLATFORM".
  • All pending authorizations reconcile to a terminal state via the existing reconcile primitive.
  • Funding-source bindings are detached. Refunds already in flight continue to complete because Lightspark holds the card-reserve keys.
  • Inbound clearings received after close follow the standard force-post / late-presentment path — Lightspark absorbs the loss if a post-hoc pull on the now-unbound source fails.
  • CARD.STATE_CHANGE fires with state: "CLOSED".
fundingSources cannot be supplied alongside state: CLOSED. 409 CARD_ALREADY_CLOSED is returned if the card is already in the terminal CLOSED state.

Updating the per-transaction limit

To set or change the per-transaction spending limit:
Supply a positive integer to set the limit (in the smallest unit of the card’s currency) or null to clear it. Omitting the field leaves the current limit unchanged. maxSpendPerTransaction cannot be supplied alongside state: CLOSED.

Sandbox behavior

In Sandbox the state changes are instant — no issuer round-trip is simulated, but the signed-retry shape is the same as production so you can exercise the full client flow.