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

# Exchange webhook events

> Payloads for exchange order lifecycle and fill events.

Exchange events use three data shapes: an order snapshot, an order plus one
fill, or an original-and-replacement order pair.

| Event                | `data` shape                          | Meaning                                                       |
| -------------------- | ------------------------------------- | ------------------------------------------------------------- |
| `exchange.accepted`  | `order`                               | A create order was accepted or immediately partially filled.  |
| `exchange.filled`    | `order`, `fill`                       | One fill was committed for your side of the trade.            |
| `exchange.replaced`  | `original_order`, `replacement_order` | A replace command committed.                                  |
| `exchange.cancelled` | `order`                               | An order was cancelled, including any remaining IOC quantity. |
| `exchange.rejected`  | `order`                               | A create or replace command was rejected.                     |

## Order snapshot events

`exchange.accepted`, `exchange.cancelled`, and `exchange.rejected` have the same
`data.order` shape. The event type and order status identify the transition.

```json theme={null}
{
  "id": "6674cf38-e84a-5ec1-98c6-2806efee09d4",
  "type": "exchange.accepted",
  "version": 1,
  "occurred_at": "2026-07-17T10:20:15Z",
  "data": {
    "order": {
      "id": "019bd2d1-92a8-78d0-bcaf-24af6de054fb",
      "pair_id": "USD/NGN",
      "side": "buy",
      "order_type": "limit",
      "time_in_force": "gtc",
      "status": "accepted",
      "quantity": "100.00",
      "filled_quantity": "0",
      "remaining_quantity": "100.00",
      "price": "1650.00",
      "avg_fill_price": null,
      "reject_reason": null,
      "cancel_reason": null,
      "client_order_id": "partner-order-123",
      "replace": {
        "replaces_order_id": null,
        "replaced_by_order_id": null
      },
      "created_at": "2026-07-17T10:20:15+00:00"
    }
  }
}
```

For `exchange.cancelled`, `order.status` is `cancelled`. `cancel_reason` is
usually `null`; an immediate order with an executed portion and cancelled
remainder uses `unfilled_ioc_quantity`.

For `exchange.rejected`, `order.status` is `rejected` and `reject_reason` is a
public value such as `insufficient_balance`, `post_only_would_cross`,
`self_trade_prevention`, `order_not_found`, `no_fill`, or `engine_rejected`.

## `exchange.filled`

One order can produce several fill events. `data.fill.id` identifies the fill;
`data.order` is the order snapshot after that fill was applied.

```json theme={null}
{
  "id": "c0f64131-464a-52b8-a06c-4c459b4412b6",
  "type": "exchange.filled",
  "version": 1,
  "occurred_at": "2026-07-17T10:21:03Z",
  "data": {
    "order": {
      "id": "019bd2d1-92a8-78d0-bcaf-24af6de054fb",
      "pair_id": "USD/NGN",
      "side": "buy",
      "order_type": "limit",
      "time_in_force": "gtc",
      "status": "partially_filled",
      "quantity": "100.00",
      "filled_quantity": "40.00",
      "remaining_quantity": "60.00",
      "price": "1650.00",
      "avg_fill_price": "1649.50",
      "reject_reason": null,
      "cancel_reason": null,
      "client_order_id": "partner-order-123",
      "replace": {
        "replaces_order_id": null,
        "replaced_by_order_id": null
      },
      "created_at": "2026-07-17T10:20:15+00:00"
    },
    "fill": {
      "id": "019bd2d1-9654-76c0-837f-6012dd933faa",
      "price": "1649.50",
      "quantity": "40.00",
      "fee": "0.08",
      "fee_currency": "USD",
      "created_at": "2026-07-17T10:21:03+00:00"
    }
  }
}
```

## `exchange.replaced`

A replacement event contains both snapshots. The original is `cancelled` and
links to the replacement through `replace.replaced_by_order_id`. The replacement
links back through `replace.replaces_order_id`.

```json theme={null}
{
  "id": "6a597f4e-e7be-5cba-aab4-cf97915ca9bc",
  "type": "exchange.replaced",
  "version": 1,
  "occurred_at": "2026-07-17T10:24:09Z",
  "data": {
    "original_order": {
      "id": "019bd2d1-92a8-78d0-bcaf-24af6de054fb",
      "pair_id": "USD/NGN",
      "side": "buy",
      "order_type": "limit",
      "time_in_force": "gtc",
      "status": "cancelled",
      "quantity": "100.00",
      "filled_quantity": "40.00",
      "remaining_quantity": "60.00",
      "price": "1650.00",
      "avg_fill_price": "1649.50",
      "reject_reason": null,
      "cancel_reason": null,
      "client_order_id": "partner-order-123",
      "replace": {
        "replaces_order_id": null,
        "replaced_by_order_id": "019bd2d1-a179-741d-b4ce-9edc119c9ac1"
      },
      "created_at": "2026-07-17T10:20:15+00:00"
    },
    "replacement_order": {
      "id": "019bd2d1-a179-741d-b4ce-9edc119c9ac1",
      "pair_id": "USD/NGN",
      "side": "buy",
      "order_type": "limit",
      "time_in_force": "gtc",
      "status": "accepted",
      "quantity": "60.00",
      "filled_quantity": "0",
      "remaining_quantity": "60.00",
      "price": "1645.00",
      "avg_fill_price": null,
      "reject_reason": null,
      "cancel_reason": null,
      "client_order_id": "partner-order-124",
      "replace": {
        "replaces_order_id": "019bd2d1-92a8-78d0-bcaf-24af6de054fb",
        "replaced_by_order_id": null
      },
      "created_at": "2026-07-17T10:24:09+00:00"
    }
  }
}
```

Use `data.order.id`, `data.original_order.id`, or
`data.replacement_order.id` with `GET /v1/partner/exchange/orders/{order_id}`
for the authoritative order state. Fill history is available through
`GET /v1/partner/exchange/fills`.

[Return to the webhook overview](/docs/webhooks)
