Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 54 additions & 6 deletions mintlify/openapi.yaml

Large diffs are not rendered by default.

86 changes: 22 additions & 64 deletions mintlify/snippets/cards/freezing-and-closing.mdx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
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.
Freeze, close, and other card updates use a single authenticated
`PATCH /cards/{id}` request and return the updated card with `200 OK`.


`PATCH /cards/{id}` covers freeze / unfreeze (`state`), funding source
updates (`fundingSources`), and per-transaction spending limits
(`maxSpendPerTransaction`). See
updates (`fundingSources`), per-transaction spending limits
(`maxSpendPerTransaction`), and UTC-calendar-day spending limits
(`maxSpendPerDay`). See
[Funding sources](/cards/card-management/funding-sources) for the
funding-source-only flow. The signed-retry mechanics below apply to all
fields.
funding-source-only flow.

## Valid state transitions

Expand All @@ -26,65 +24,16 @@ 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:

```text
1. PATCH /cards/{id} ─► 202 with payloadToSign, requestId, expiresAt
2. PATCH /cards/{id} ─► 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

```bash
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`:

```json
{
"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:

```bash
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
The response is `200 OK` with the updated `Card` and a
`CARD.STATE_CHANGE` webhook.

<Note>
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.
</Note>

## What freeze does

Setting a card to `FROZEN`:
Expand Down Expand Up @@ -118,8 +67,6 @@ setting `state: "CLOSED"`. The operation is permanent:
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: <requestId from prior 202>" \
-d '{ "state": "CLOSED" }'
```

Expand All @@ -135,8 +82,6 @@ To set or change the per-transaction spending limit:
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: <requestId from prior 202>" \
-d '{ "maxSpendPerTransaction": 10000 }'
```

Expand All @@ -145,8 +90,21 @@ card's currency) or `null` to clear it. Omitting the field leaves the
current limit unchanged. `maxSpendPerTransaction` cannot be supplied
alongside `state: CLOSED`.

## Updating the daily limit

Set `maxSpendPerDay` to a positive integer in the smallest unit of the card's
currency, or set it to `null` to clear the card-specific daily limit. The
window resets at 00:00 UTC. Refunds, reversals, and authorization expiries do
not restore capacity during the same day.

```bash
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 '{ "maxSpendPerDay": 25000 }'
```

## 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.
simulated. The request and response shape is the same as production.
4 changes: 3 additions & 1 deletion mintlify/snippets/cards/issuing-cards.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ curl -X POST "$GRID_BASE_URL/cards" \
"fundingSources": [
"InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
],
"maxSpendPerTransaction": 5000
"maxSpendPerTransaction": 5000,
"maxSpendPerDay": 25000
}'
```

Expand All @@ -26,6 +27,7 @@ curl -X POST "$GRID_BASE_URL/cards" \
| `form` | Yes | `VIRTUAL` in v1. `PHYSICAL` will be added later. |
| `fundingSources` | Yes | Ordered array of `InternalAccount` ids. Each must belong to the cardholder and share one card-eligible currency. The first entry is tried first by Authorization Decisioning. |
| `maxSpendPerTransaction` | No | Largest amount a single card transaction may authorize, in the smallest unit of the card's currency. Omit for no limit. Supported only for card programs where Grid makes the authorization decision. |
| `maxSpendPerDay` | No | Cumulative new spend allowed per UTC calendar day, in the smallest unit of the card's currency. Refunds, reversals, and expiries do not restore capacity that day. |

The card's `currency` is derived from the funding sources at issue time
and surfaces on the returned `Card` resource — all bound sources share
Expand Down
Loading
Loading