> ## 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

> Merchant webhook events delivered after payment state changes.

Open Rails normalizes provider callbacks into one merchant webhook contract. Build your fulfillment logic against these events, not against provider-specific callbacks.

## Events

| Event                      | Meaning                                                                   |
| -------------------------- | ------------------------------------------------------------------------- |
| `payment.provider_pending` | The provider accepted the buyer handoff and payment is still in progress. |
| `payment.paid`             | Payment confirmed. Safe to fulfill the order.                             |
| `payment.failed`           | Payment failed, timed out, or was rejected.                               |

## Headers

Every merchant webhook delivery includes signing metadata.

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

Verify the signature before mutating order state. Process events idempotently using the event `id`.

## Sample 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"
    }
  }
}
```

## Generate a webhook example

Use the agent actions endpoint to generate a representative webhook payload for local testing:

```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"
    }
  }'
```

Supported event values: `payment.provider_pending`, `payment.paid`, `payment.failed`.

## Fulfillment rules

* Only fulfill after `payment.paid`. Do not fulfill on `payment.provider_pending`.
* Store the raw payload for replay debugging.
* Acknowledge with HTTP 200. Open Rails retries on non-200 responses.

For the full webhook guide including signature verification, see [Webhooks](/guides/webhooks).
