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

# Card transaction

`POST card-transaction` (webhook)

Webhook that is called on every lifecycle update of a card `CardTransaction`. Fires when an authorization is approved (`CARD_TRANSACTION.AUTHORIZED`), as clearings settle against it (`CARD_TRANSACTION.PARTIALLY_SETTLED`, `CARD_TRANSACTION.SETTLED`), when the authorization is declined (`CARD_TRANSACTION.DECLINED`), when an authorization is fully reversed or expires (`CARD_TRANSACTION.VOIDED`), and when a transaction settles to the card network but the funding-source pull fails (`CARD_TRANSACTION.EXCEPTION`). The payload carries the full `CardTransaction` resource.

A merchant return is its own `CardTransaction` row (`direction: CREDIT`) linked to the purchase via `originalTransactionId`, and fires its own `CARD_TRANSACTION.*` deliveries on that row — the purchase row is not re-fired for the return.

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

- CardTransactionWebhook
  - `id` string, required: Unique identifier for this webhook delivery (can be used for idempotency)
  - `type` 'CARD_TRANSACTION.AUTHORIZED' | 'CARD_TRANSACTION.PARTIALLY_SETTLED' | 'CARD_TRANSACTION.SETTLED' | 'CARD_TRANSACTION.DECLINED' | 'CARD_TRANSACTION.VOIDED' | 'CARD_TRANSACTION.EXCEPTION', 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` CardTransaction, required: One row per cardholder-visible card transaction. A purchase row rolls its clearings up into `settledAmount`; a merchant return is its own dated `CREDIT` row linked back to the purchase via `originalTransactionId` rather than a rollup on the parent, so statements can list purchases and refunds as separate dated lines. Delivered whole as the `data` payload of every `CARD_TRANSACTION.*` webhook, and returned as the `CARD` variant of `Transaction` from `GET /transactions`.
    - `type` 'CARD', required: Discriminator identifying this transaction as a card transaction in the `Transaction` list.
    - `id` string, required: System-generated unique card transaction identifier
    - `cardId` string: The id of the `Card` this transaction was made on.
    - `customerId` string, required: System ID of the customer (cardholder) this transaction belongs to.
    - `platformCustomerId` string, required: Platform-specific ID of the customer (cardholder) this transaction belongs to.
    - `issuerTransactionToken` string: Opaque identifier for the transaction on the underlying issuer. Used to cross-reference Grid records against issuer dashboards and webhooks.
    - `status` 'AUTHORIZED' | 'PARTIALLY_SETTLED' | 'SETTLED' | 'DECLINED' | 'VOIDED' | 'EXCEPTION', required: Lifecycle status of a card transaction. The status tracks the authorization outcome and settlement — a return against a purchase is its own dated `CREDIT` row linked to the purchase via `originalTransactionId`, not a status of its own. | Status | Description | |--------|-------------| | `AUTHORIZED` | The auth has been approved and a hold placed on the funding source; no clearing has arrived yet. | | `PARTIALLY_SETTLED` | At least one clearing has arrived and posted, but more clearings are still expected (split shipments, tips, multi-leg trips). | | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. A `RETURN` received afterwards keeps the purchase `SETTLED`; the return appears as its own `CREDIT` transaction. | | `DECLINED` | The authorization was declined before any money moved. Declines carry no settlement and must be excluded from cardholder statements. | | `VOIDED` | The authorization was fully reversed or expired before any clearing posted, so the hold closed without moving money. `authorizedAmount` reports what is still held, normally 0, and `settledAmount` is absent. | | `EXCEPTION` | The transaction settled to the card network but the corresponding pull from the funding source failed (e.g. balance no longer covers the post-hoc clearing). Surfaces high-urgency alerts and is the dashboard query for stuck reconciliations. |
    - `cardDeclinedReason` 'CARD_NOT_ACTIVE' | 'SPEND_LIMIT_EXCEEDED' | 'INSUFFICIENT_FUNDS' | 'NO_ELIGIBLE_FUNDING_SOURCE' | 'BLOCKED' | 'UNSUPPORTED_NETWORK' | 'INCORRECT_CARD_DETAILS' | 'TEMPORARILY_UNAVAILABLE' | 'PLATFORM_DECLINED' | 'PLATFORM_UNAVAILABLE' | 'OTHER': Why Grid declined a card authorization. Present only when a card transaction's `status` is `DECLINED`. | Reason | Returned when | |--------|---------------| | `CARD_NOT_ACTIVE` | The card is not `ACTIVE`. A `FROZEN`, `PROCESSING`, `PENDING_KYC`, or `CLOSED` card declines every authorization. | | `SPEND_LIMIT_EXCEEDED` | The authorization exceeds a configured card velocity limit or an applicable agent spending-policy cap. | | `INSUFFICIENT_FUNDS` | The funding source balance does not cover the authorization. Grid reserves the amount when it decides the authorization, so an underfunded card is declined. | | `NO_ELIGIBLE_FUNDING_SOURCE` | The card has no usable funding source, for example an Embedded Wallet source with no active delegated key. | | `BLOCKED` | Program rules block the merchant category or the transaction. | | `UNSUPPORTED_NETWORK` | Grid does not support the network or the transaction type. | | `INCORRECT_CARD_DETAILS` | The PIN, security code, expiry date, or billing address entered at the merchant did not match the card. | | `TEMPORARILY_UNAVAILABLE` | A temporary problem at Grid, the card processor, or the card network stopped the authorization. The cardholder can try again. | | `PLATFORM_DECLINED` | Your platform returned `decision: DECLINE`. `platformDeclineReason` carries the reason it gave. | | `PLATFORM_UNAVAILABLE` | Your platform did not return a valid decision to a `CARD_AUTHORIZATION.REQUEST` in time, and `cardConfigs.realTimeAuthorization.timeoutBehavior` is `DECLINE`. | | `OTHER` | Any other reason, including a security or fraud decline the card processor made. |
    - `platformDeclineReason` 'SUSPECTED_FRAUD' | 'UNAUTHORIZED_MERCHANT' | 'VELOCITY_EXCEEDED' | 'INSUFFICIENT_FUNDS' | 'CARD_PAUSED': Why your platform declined a card authorization. Grid passes it to the card network, so choose the most specific reason. | Reason | Use when | |--------|----------| | `SUSPECTED_FRAUD` | The authorization breaks your fraud rules. Use it only when no other reason fits. | | `UNAUTHORIZED_MERCHANT` | The merchant, merchant category, country, or transaction type is not allowed for this card. | | `VELOCITY_EXCEEDED` | The authorization exceeds a velocity limit you set. The merchant may retry later. | | `INSUFFICIENT_FUNDS` | The cardholder lacks funds by your own accounting. The merchant may retry later. | | `CARD_PAUSED` | You track a paused state for the card that Grid's card `status` does not reflect. |
    - `direction` 'CREDIT' | 'DEBIT', required: Whether the transaction credits (funds in) or debits (funds out) the customer's account. Independent of `type`: an incoming transaction is normally a `CREDIT`, but an inbound ACH pull, for example, is an `INCOMING` transaction with a `DEBIT` direction.
    - `originalTransactionId` string: On a refund row (`direction: CREDIT`), the id of the purchase this return credits back against. Absent on purchases and on standalone credits with no matching purchase.
    - `description` string: The merchant descriptor, repeated from `merchant.descriptor` so a transaction list reads without expanding each card row. Unlike `description` on other transaction types, this is set by Grid from the card network's descriptor, not supplied by the platform.
    - `merchant` CardMerchant, required
      - `descriptor` string, required: Merchant descriptor string captured from the card network at authorization time. On the sandbox simulate endpoints, where this is supplied rather than reported, it must be 1–25 characters — the width of the card network's acceptor-name field.
      - `mcc` string: Merchant Category Code (ISO 18245) — four-digit numeric string.
      - `city` string: Merchant city as reported by the card network, when present.
      - `state` string: Merchant state or region as reported by the card network, when present.
      - `country` string: Two-letter ISO 3166-1 alpha-2 country code of the merchant.
    - `authorizedAmount` CurrencyAmount, required
      - `amount` integer, required: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
      - `currency` Currency, required
        - `code` string: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
        - `name` string: Full name of the currency
        - `symbol` string: Symbol of the currency
        - `decimals` integer: Number of decimal places for the currency
    - `settledAmount` CurrencyAmount
      - `amount` integer, required: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
      - `currency` Currency, required
        - `code` string: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
        - `name` string: Full name of the currency
        - `symbol` string: Symbol of the currency
        - `decimals` integer: Number of decimal places for the currency
    - `refundedAmount` CurrencyAmount
      - `amount` integer, required: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
      - `currency` Currency, required
        - `code` string: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
        - `name` string: Full name of the currency
        - `symbol` string: Symbol of the currency
        - `decimals` integer: Number of decimal places for the currency
    - `accountId` string, required: Internal account id that funded this transaction (the funding source selected by Authorization Decisioning at auth time).
    - `authorizedAt` string, date-time, required: When the authorization was approved or declined.
    - `createdAt` string, date-time, required: Creation timestamp (same as `authorizedAt` for card transactions).
    - `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)
