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

# Webhook Endpoints

> The /quote and /confirm endpoints your pricer must implement

Your pricer exposes exactly two endpoints under whatever base URL you register. Novig calls them; you respond. Both bodies are JSON, both carry an `X-Novig-Signature` header, and both have hard timing requirements.

## `POST {webhook_url}/quote`

Novig calls `/quote` for every parlay RFQ that names outcomes you might quote. You return a price and a maximum wager you're willing to back at that price.

### Request body

```json theme={null}
{
    "rfq_id": "9b1d76e0-2fa9-0c1d-8e74-b3a5f6c218e0",
    "outcome_ids": ["11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222"],
    "timestamp": "2026-04-29T18:42:11.123Z",
    "min_wager": "50.00"
}
```

| Field         | Type                  | Notes                                                                                                                                                                                                          |
| ------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rfq_id`      | UUID string           | Novig-issued RFQ identifier. Echoed back as `rfq_id` on `/confirm`.                                                                                                                                            |
| `outcome_ids` | array of UUID strings | Ordered list of Novig outcome IDs. One leg per ID. See [Outcome IDs](/api-reference/outcome-ids).                                                                                                              |
| `timestamp`   | RFC3339 string        | When Novig created the RFQ.                                                                                                                                                                                    |
| `min_wager`   | string, optional      | Minimum stake the taker wants covered. **Omitted entirely** when the taker didn't set one. A quote whose `max_wager` can't cover it (or the platform minimum of 10.00, whichever is higher) is never selected. |

Header: `X-Novig-Signature: BLAKE3(shared_secret, body).hex()` — see [Signing](/api-reference/rfq/signing).

### Response body

```json theme={null}
{
    "price": 0.45,
    "max_wager": "250.00",
    "quote_id": "pricer-quote-xyz"
}
```

| Field       | Type             | Notes                                                                                                                                                                                                                                                                                  |
| ----------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `price`     | number, `(0, 1)` | Decimal probability you're quoting. `0.45` means `$0.45` stake per `$1.00` payout. <br /><br />Prices are resolved on a **0.001 grid** (`0.001`–`0.999`); more precision is rounded to the nearest tick. The standard order-book tick-size constraints **do not apply** to RFQ quotes. |
| `max_wager` | string           | Maximum taker stake you're willing to accept on this quote, in Novig Cash. **JSON string** to preserve precision.                                                                                                                                                                      |
| `quote_id`  | string, optional | Your own ID for the quote. If supplied, Novig echoes it back as `external_flag` on `/confirm`.                                                                                                                                                                                         |

<Note>
  There is **no expiry field**. Quote validity is platform-owned: Novig anchors a TTL when the auction closes (currently 30
  seconds pregame, 10 seconds for live markets) — your quote simply lapses when it expires.
</Note>

### Hard rules

<Warning>
  **Novig's total budget for `/quote` fanout is 3 seconds.** A response that arrives later is silently dropped. The taker sees
  only the quotes that landed inside the window.
</Warning>

* Non-2xx responses are dropped.
* `max_wager <= 0` is dropped.
* Malformed/unparseable JSON is dropped.
* A bad signature is dropped.

In every drop case the taker simply doesn't see your quote — there is no penalty beyond losing the trade.

### Declining to quote

If you don't want to quote a particular RFQ, the simplest way is to return **HTTP 204 No Content**. Anything non-2xx works.

## `POST {webhook_url}/confirm`

If your quote is selected as the winner, Novig calls `/confirm` with the actual taker wager (which may be ≤ your `max_wager`) immediately before writing the trade. This is your last chance to back out.

<Warning>
  **You have 1 second to answer.** The confirm window is a fixed 1-second last look: a pricer that hasn't responded by the bell
  is **rejected** (the trade does not execute). The window never closes early either — an early answer is held to the bell — so
  there is no advantage to racing, but a hard penalty for being slow.
</Warning>

### Request body

```json theme={null}
{
    "rfq_id": "9b1d76e0-2fa9-0c1d-8e74-b3a5f6c218e0",
    "wager": "100.00",
    "price": "0.45",
    "external_flag": "pricer-quote-xyz"
}
```

| Field           | Type             | Notes                                                                                                                  |
| --------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `rfq_id`        | UUID string      | Same `rfq_id` from the original `/quote`.                                                                              |
| `wager`         | string           | Taker stake in Novig Cash. JSON string. Always `<= max_wager` you returned.                                            |
| `price`         | string           | Price Novig selected — yours, since only the winning pricer is asked. JSON string.                                     |
| `external_flag` | string, optional | The `quote_id` you returned on `/quote`. **Field is omitted entirely** when none was provided — don't expect a `null`. |

Header: same `X-Novig-Signature` scheme as `/quote`.

### Response body

```json theme={null}
{ "confirmed": true }
```

| Field       | Type                  | Notes                                                                                        |
| ----------- | --------------------- | -------------------------------------------------------------------------------------------- |
| `confirmed` | boolean, **required** | `true` accepts the trade. `false` rejects — Novig writes nothing and the parlay is rejected. |

<Warning>A **missing `confirmed` field is a hard error** — it aborts the trade just like `false`. Always include it.</Warning>

## Type & encoding notes

* **Decimal numbers (`max_wager`, `wager`, `price` on `/confirm`) are JSON strings**, not numbers.
* **`price` on `/quote` response is a JSON number** in `(0, 1)` decimal probability.
* **UUIDs are lowercase strings** with hyphens.
