> ## Documentation Index
> Fetch the complete documentation index at: https://ramps-dp-card-limit-reached-error-code.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Freezing & Closing Cards

> Freeze, unfreeze, and close cards via the signed-retry pattern

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`), 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.

## Valid state transitions

| From                 | To       | Endpoint                                         |
| -------------------- | -------- | ------------------------------------------------ |
| `ACTIVE`             | `FROZEN` | `PATCH /cards/{id}` body `{ "state": "FROZEN" }` |
| `FROZEN`             | `ACTIVE` | `PATCH /cards/{id}` body `{ "state": "ACTIVE" }` |
| `ACTIVE` or `FROZEN` | `CLOSED` | `PATCH /cards/{id}` body `{ "state": "CLOSED" }` |

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.

```bash theme={null}
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" }'
```

The response is `200 OK` with the updated `Card` and a
`CARD.STATE_CHANGE` webhook.

## 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"`.

```bash theme={null}
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": "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:

```bash theme={null}
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 '{ "maxSpendPerTransaction": 10000 }'
```

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`.

## 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 theme={null}
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. The request and response shape is the same as production.
