Skip to main content

Documentation Index

Fetch the complete documentation index at: https://ramps-moonrise-limestone.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

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 both freeze / unfreeze (state) and funding source updates (fundingSources); see Funding sources for the funding-source-only flow. The signed-retry mechanics below apply to all three.

Valid state transitions

FromToEndpoint
ACTIVEFROZENPATCH /cards/{id} body { "state": "FROZEN" }
FROZENACTIVEPATCH /cards/{id} body { "state": "ACTIVE" }
ACTIVE or FROZENCLOSEDDELETE /cards/{id}
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:
1. PATCH /cards/{id}   (or DELETE)        ─►  202  with payloadToSign, requestId, expiresAt
2. PATCH /cards/{id}   (or DELETE)        ─►  200  with the updated Card
   Headers:
     Grid-Wallet-Signature: <sig>
     Request-Id: <requestId from step 1>
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

curl -X PATCH "$GRID_BASE_URL/cards/Card:019542f5-b3e7-1d02-0000-000000000010" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "state": "FROZEN" }'
Response — 202 Accepted:
{
  "payloadToSign": "Y2hhbGxlbmdlLXBheWxvYWQtdG8tc2lnbg==",
  "requestId": "7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21",
  "expiresAt": "2026-05-08T15:35:00Z"
}

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:
curl -X PATCH "$GRID_BASE_URL/cards/Card:019542f5-b3e7-1d02-0000-000000000010" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "Grid-Wallet-Signature: <base64 signature>" \
  -H "Request-Id: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21" \
  -d '{ "state": "FROZEN" }'
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

DELETE /cards/{id} is the only way to reach CLOSED, and 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".
curl -X DELETE "$GRID_BASE_URL/cards/Card:019542f5-b3e7-1d02-0000-000000000010" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Grid-Wallet-Signature: <base64 signature>" \
  -H "Request-Id: <requestId from prior 202>"
409 CARD_ALREADY_CLOSED is returned if the card is already in the terminal CLOSED state.

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.