Webhooks

Card authorization request

Real-time decision request for a card authorization. Grid sends it to the webhookEndpoint in your platform config while cardConfigs.realTimeAuthorization is set. Your response decides whether the authorization proceeds. This endpoint should be implemented by clients of the Grid API that want to make their own authorization decisions.

When Grid sends it

Grid runs its own checks first: card status, card and platform spend limits, merchant category rules, and network support. Grid sends this request only for authorizations those checks approve, so a declined authorization never reaches your endpoint. Balance inquiries are never sent. It covers only cards whose authorization decisions Grid makes.

Responding

Return HTTP 200 with a CardAuthorizationDecision body within 1.5 seconds. decision: APPROVE lets the authorization proceed. decision: DECLINE declines it, and Grid passes your declineReason to the card network. If your endpoint returns any other status or an invalid body, or does not respond in time, Grid applies the timeoutBehavior in cardConfigs.realTimeAuthorization. Grid does not retry this request.

After you approve

Grid reserves the authorized amount from the funding source after you approve. If the funding source cannot cover it, Grid still declines with INSUFFICIENT_FUNDS. The final outcome arrives as a CARD_TRANSACTION.AUTHORIZED or CARD_TRANSACTION.DECLINED webhook. A decline you return arrives there with cardDeclinedReason: PLATFORM_DECLINED and your declineReason in platformDeclineReason.

Duplicates

Grid can send the same authorization more than once if the card network retries it. Each delivery has a new id, but data.transactionId and data.issuerTransactionToken stay the same. Return the same decision for each.

Authentication

The request includes a signature in the X-Grid-Signature header that allows you to verify that the request 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 request is authentic. If not, reject it. Also reject a request whose timestamp is more than a few minutes old.

postWebhookcard-authorization-request

Payload

idstring required

Unique identifier for this webhook delivery (can be used for idempotency)

type'CARD_AUTHORIZATION.REQUEST' 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.

timestampstring date-time required

ISO 8601 timestamp of when the webhook was sent

Example payload

{
  "id": "Webhook:019542f5-b3e7-1d02-0000-000000000007",
  "timestamp": "2025-08-15T14:32:00Z",
  "data": {
    "transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000100",
    "cardId": "Card:019542f5-b3e7-1d02-0000-000000000010",
    "platformCardId": "card_8f2a1c",
    "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
    "platformCustomerId": "18d3e5f7b4a9c2",
    "issuerTransactionToken": "lithic_txn_b81c2a4f",
    "transactionType": "AUTHORIZATION",
    "requestedAmount": {
      "amount": 12550,
      "currency": {
        "code": "USD",
        "name": "United States Dollar",
        "symbol": "$",
        "decimals": 2
      }
    },
    "approvedAmount": {
      "amount": 12550,
      "currency": {
        "code": "USD",
        "name": "United States Dollar",
        "symbol": "$",
        "decimals": 2
      }
    },
    "merchantAmount": {
      "amount": 12550,
      "currency": {
        "code": "USD",
        "name": "United States Dollar",
        "symbol": "$",
        "decimals": 2
      }
    },
    "merchant": {
      "descriptor": "BLUE BOTTLE COFFEE SF",
      "mcc": "5814",
      "city": "San Francisco",
      "state": "CA",
      "country": "US"
    },
    "accountId": "InternalAccount:019542f5-b3e7-1d02-0000-000000000002"
  }
}

Response

Your decision on the authorization.

decision'APPROVE' | 'DECLINE' required

Your platform's decision on a card authorization.

declineReason'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.

ReasonUse when
SUSPECTED_FRAUDThe authorization breaks your fraud rules. Use it only when no other reason fits.
UNAUTHORIZED_MERCHANTThe merchant, merchant category, country, or transaction type is not allowed for this card.
VELOCITY_EXCEEDEDThe authorization exceeds a velocity limit you set. The merchant may retry later.
INSUFFICIENT_FUNDSThe cardholder lacks funds by your own accounting. The merchant may retry later.
CARD_PAUSEDYou track a paused state for the card that Grid's card status does not reflect.

Example response

{
  "decision": "APPROVE",
  "declineReason": "SUSPECTED_FRAUD"
}

Changes

Webhooks have no change history: a webhook is keyed by its event name rather than a path and method, so no recorded change can name it.