---
title: "Card PIN status change"
method: POST
path: "card-pin-status-change"
tags: ["Webhooks"]
---

# Card PIN status change

`POST card-pin-status-change` (webhook)

Sent when Grid records a change to a card's PIN status, including changes detected after a hosted PIN submission, an API request, or a PIN becoming blocked. The data contains the updated Card resource and its new pinStatus.

Initial card creation does not trigger this event. Changing an existing PIN while its status remains OK does not trigger it either; use the submission result to confirm that the PIN changed.

Changes made outside the Grid API are detected asynchronously. The event describes the status Grid observed, not every intermediate PIN status. Delivery can be repeated or arrive out of order. Deduplicate by id and use data.updatedAt to avoid replacing newer card data with an older snapshot. Read pinStatus from GET /cards/{id} to retrieve the card's saved status.

Verify the X-Grid-Signature header using your Grid webhook public key, as for other Grid webhooks. No PIN, encrypted PIN block, or PIN-entry session credential is included.

## Payload

- CardPinStatusChangeWebhook
  - `id` string, required: Unique identifier for this webhook delivery (can be used for idempotency)
  - `type` 'CARD.PIN_STATUS_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. `CARD_AUTHORIZATION.REQUEST` is a synchronous decision request that Grid sends only while `cardConfigs.realTimeAuthorization` is set.
  - `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
    - `customerId` string, required: The id of the `Customer` who holds this card.
    - `platformCardId` string: Platform-specific card identifier generated by the server.
    - `status` 'PENDING_KYC' | 'PROCESSING' | 'PENDING_AUTH' | 'ACTIVE' | 'FROZEN' | 'CLOSED', required: Lifecycle status of a card. | Status | Description | |-------|-------------| | `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in this status cannot transact. | | `PROCESSING` | The card has been requested and is being provisioned with the issuer. | | `PENDING_AUTH` | The issuer has provisioned the card, but its USDB Embedded Wallet funding source lacks an active delegated signing key. Complete `POST /auth/delegated-keys` before using the card. | | `ACTIVE` | The card is live and can authorize transactions. | | `FROZEN` | The card is temporarily disabled by the platform or by Grid. New authorizations are declined with `cardDeclinedReason: CARD_NOT_ACTIVE`. Existing settlements and refunds continue to reconcile. A card Grid froze for review, or one frozen as `COMPROMISED`, cannot be unfrozen by the platform. | | `CLOSED` | The card is permanently closed. Terminal, irreversible status. |
    - `statusReason` 'DELEGATION_REQUIRED' | 'ISSUER_REJECTED' | 'CLOSED_BY_PLATFORM' | 'CLOSED_BY_GRID': Reason a card reached a terminal or non-active status. Present on `PENDING_AUTH` and `CLOSED` cards, and on cards that fail provisioning before reaching `ACTIVE`. | Reason | Description | |--------|-------------| | `DELEGATION_REQUIRED` | The card funding source has no usable delegated signing key. Present while the card is `PENDING_AUTH`. | | `ISSUER_REJECTED` | The card issuer rejected provisioning during `PROCESSING`. | | `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}` (`status: 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.
    - `pinStatus` 'NOT_SET' | 'OK' | 'BLOCKED': State of the card's PIN. On the Card resource, this is the last known status and is present whenever PIN management is supported. An absent value means PIN management is unavailable for this card; it does not mean `NOT_SET`. Use `GET /cards/{id}` to retrieve `pinStatus`. | Status | Description | |--------|-------------| | `NOT_SET` | No PIN has been set on the card. PIN verification is not enabled. Set one with `POST /cards/{id}/set-pin` or the hosted form returned by `GET /cards/{id}/pin-entry-url`. | | `OK` | A PIN is set and usable. | | `BLOCKED` | The PIN was entered incorrectly three consecutive times and is refused until cleared with `POST /cards/{id}/pin/unblock`, or replaced with `POST /cards/{id}/set-pin`. |
    - `pinUnblockAvailableAt` string, date-time: Earliest time another PIN unblock attempt is allowed. Absent until the unblock allowance is used. Changing the PIN does not reset this time.
    - `last4` string: Last four digits of the card PAN.
    - `expMonth` integer: Card expiration month (1–12).
    - `expYear` integer: Card expiration year (four digits).
    - `fundingSource` string, required: Internal account id that funds this card.
    - `cardCapabilities` CardCapabilities: Actions supported by the card program associated with this resource.
      - `supportsVelocityLimits` boolean, required: Whether this card program supports platform-managed limits through `/card-velocity-limits`. Supported where Grid makes authorization decisions; false where the issuer makes them. Amounts use the card's currency, regardless of its funding source.
      - `supports3dSecurePassword` boolean, required: Whether cards in this program accept a caller-supplied `threeDSecurePassword`.
      - `supportsPanReveal` boolean, required: Whether cards in this program can be revealed through `POST /cards/{id}/reveal`.
      - `supportsDigitalWalletTokenization` boolean, required: Whether cards in this program can be added to Apple Pay, Google Pay, or Samsung Pay from your app through `POST /cards/{id}/tokenize`. Manual entry into a wallet works regardless of this flag.
    - `maxNetworkRiskScore` integer, nullable: Maximum normalized network risk score allowed for real-time card authorizations. Scores range from 0 (lowest risk) to 999 (highest risk). Visa scores are normalized by multiplying the raw 0–99 score by 10. Scores equal to the ceiling are allowed. Authorizations without a score are also allowed. The lowest configured card or platform ceiling applies. Null means no card-specific ceiling. Platform controls still apply.
    - `allowedMccs` string[]: Merchant category codes the card may spend at. Present only on a card issued for an agent; absent when that card may spend at any category not blocked.
    - `blockedMccs` string[]: Merchant category codes a card issued for an agent declines, with `cardDeclinedReason: BLOCKED`. Present only on such a card, which also declines Grid's default agent categories unless `defaultMccBlocksLifted` is true.
    - `agentId` string: The agent the card was issued for, when there is one.
    - `defaultMccBlocksLifted` boolean: Whether the platform lifted Grid's default agent merchant-category blocks on this card. Present only for a card issued for an agent.
    - `currency` string: Currency the card transacts in, fixed at issuance by its card program. USDB-funded cards transact in USD, with funding converted at 1 USDB = 1 USD. Spending limits use the smallest unit of the card's currency (USD cents for USDB-funded cards). Changing the funding source does not change the card's currency or spending-limit units.
    - `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.dev/lightsparkdev/apis/grid-api.md) - [All operations](https://skmtc.dev/lightsparkdev/apis/grid-api/llms.txt) - [OpenAPI document](https://skmtc.dev/lightsparkdev/apis/grid-api/revisions/7a1db46ec552?raw)
