> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getopenrails.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Receive one normalized webhook payload for provider-pending, paid, and failed payments.

Open Rails normalizes provider callbacks into one merchant webhook contract. Your app should rely on the Open Rails event type and session id, not the provider's raw callback shape.

## Events

| Event                      | Meaning                                                               |
| -------------------------- | --------------------------------------------------------------------- |
| `payment.provider_pending` | The provider accepted the buyer handoff and payment is still pending. |
| `payment.paid`             | Payment succeeded and the merchant can fulfill the order.             |
| `payment.failed`           | The payment failed, timed out, or was rejected.                       |

## Headers

Merchant webhooks include signing metadata.

```text theme={null}
x-gateway-event: evt_chk_nimbus_1056_paid
x-gateway-signature: t=1779584129,v1=<hmac>
```

## Payload

```json theme={null}
{
  "id": "evt_chk_nimbus_1056_paid",
  "type": "payment.paid",
  "livemode": false,
  "created": "2026-05-24T17:37:00.000Z",
  "data": {
    "session_id": "chk_nimbus_1056",
    "customer_id": "cus_7G42M9",
    "status": "paid",
    "amount": 899,
    "currency": "USD",
    "asset": "USDC",
    "network": "Base",
    "route": {
      "id": "card-bridge-a",
      "kind": "card",
      "label": "Credit card",
      "provider": "Transak Direct"
    },
    "fees": {
      "buyer_fee": 28.77,
      "gateway_fee": 26.97,
      "merchant_net": 872.03,
      "total": 927.77
    },
    "tx_hash": "0xabc123",
    "metadata": {
      "order_id": "ord_284"
    }
  }
}
```

## Local testing

Generate a representative webhook from the API:

```bash theme={null}
curl https://dash.getopenrails.com/api/agent/actions/webhook.example \
  -H "Content-Type: application/json" \
  -d '{
    "event": "payment.paid",
    "sessionId": "chk_nimbus_1056",
    "customerId": "cus_7G42M9",
    "amount": 899,
    "routeId": "card-bridge-a",
    "metadata": {
      "order_id": "ord_284"
    }
  }'
```

In production, verify signatures before mutating order state, process events idempotently by event id, and store the raw payload for replay debugging.
