---
title: "Card state change"
method: POST
path: "card-state-change"
tags: ["Webhooks"]
---

# Card state change

`POST card-state-change` (webhook)

Webhook that is called when a card's lifecycle state changes. Fires on `PROCESSING → ACTIVE`, on `PROCESSING → CLOSED (ISSUER_REJECTED)` when issuer provisioning fails, and on every subsequent `ACTIVE ⇄ FROZEN` and `→ CLOSED` transition.

This endpoint should be implemented by clients of the Grid API.

### Authentication

The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid.
To verify the signature:
1. Get the Grid public key provided to you during integration
2. Decode the base64 signature from the header
3. Create a SHA-256 hash of the request body
4. Verify the signature using the public key and the hash

If the signature verification succeeds, the webhook is authentic. If not, it should be rejected.

## Payload

- CardStateChangeWebhook
  - `id` string, required — Unique identifier for this webhook delivery (can be used for idempotency)
  - `type` 'CARD.STATE_CHANGE', required — Type of webhook event in OBJECT.EVENT dot-notation. The part before the dot identifies the resource, the part after identifies the event. This lets consumers route purely on type without inspecting data.status.
  - `timestamp` string, date-time, required — ISO 8601 timestamp of when the webhook was sent
  - `data` Card, required
    - `id` string, required — System-generated unique card identifier
    - `cardholderId` string, required — The id of the `Customer` who holds this card.
    - `platformCardId` string — Platform-specific card identifier. Optional on create — system-generated if omitted, mirroring `platformCustomerId` semantics.
    - `state` 'PENDING_KYC' | 'PROCESSING' | 'ACTIVE' | 'FROZEN' | 'CLOSED', required — Lifecycle state of a card. | State | Description | |-------|-------------| | `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in this state cannot transact. | | `PROCESSING` | The card has been requested and is being provisioned with the issuer. | | `ACTIVE` | The card is live and can authorize transactions. | | `FROZEN` | The card is temporarily disabled by the platform. New authorizations are declined with `CARD_PAUSED`. Existing settlements and refunds continue to reconcile. | | `CLOSED` | The card is permanently closed. Terminal, irreversible state. |
    - `stateReason` 'ISSUER_REJECTED' | 'CLOSED_BY_PLATFORM' | 'CLOSED_BY_GRID' — Reason a card reached a terminal or non-active state. Present on `CLOSED` cards, and on cards that fail provisioning before reaching `ACTIVE`. | Reason | Description | |--------|-------------| | `ISSUER_REJECTED` | The card issuer rejected provisioning during `PROCESSING`. | | `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}` (`state: CLOSED`) by the platform. | | `CLOSED_BY_GRID` | The card was closed by Grid (e.g. compliance or risk action). |
    - `brand` 'VISA' | 'MASTERCARD' — Card network brand. Read-only — determined by Grid when the card is provisioned with the issuer.
    - `form` 'VIRTUAL', required — Physical form factor of the card. Only `VIRTUAL` is supported in v1; `PHYSICAL` will be added in a later release.
    - `last4` string — Last four digits of the card PAN.
    - `expMonth` integer — Card expiration month (1–12).
    - `expYear` integer — Card expiration year (four digits).
    - `fundingSources` string[], required — Internal account ids bound to this card as funding sources, in priority order — the first entry is tried first by Authorization Decisioning. Every card has at least one funding source.
    - `currency` string — Currency the card transacts in (ISO 4217 for fiat, tickers for crypto). Derived from the funding sources at issue time — all funding sources bound to a card must be denominated in the same card-eligible currency.
    - `processorRef` string — Opaque processor-side reference for the card (e.g. the Lithic card token). Useful for cross-referencing in the processor's dashboards; not used for any Grid request routing.
    - `issuerRef` string — Opaque identifier for the card on the issuer of record (e.g. the Lead Bank account/card identifier). Useful for cross-referencing in issuer dashboards; not used for any Grid request routing.
    - `createdAt` string, date-time, required — Creation timestamp
    - `updatedAt` string, date-time, required — Last update timestamp

## Acknowledgement `200`

Webhook received successfully

## Other responses

- `400` — Bad request
- `401` — Unauthorized - Signature validation failed
- `409` — Conflict - Webhook has already been processed (duplicate id)

---

[API](https://skmtc.net/stainless-api/apis/grid-api.md) · [All operations](https://skmtc.net/stainless-api/apis/grid-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/stainless-api/grid-api/revisions/151f2d9bad9c/schema)
