# GET /v1/fair-price

> Independent. Not affiliated with, endorsed by or sponsored by Novig.

Canonical: https://novigapi.com/docs/endpoints/fair-price
Facts checked: 2026-11-12

GET /v1/fair-price returns the fair probability for each outcome of a Novig market, the midpoint of bid and ask, with spread, American odds and the taker fee when charged. On paid plans it is at most about 10 seconds old. Novig's taker fee coefficient was 0.06, checked 12 Nov 2026. (Source: [Novig API docs: Trading fees](https://docs.novig.com/api/concepts/fees.md))

## What it returns

Novig is an exchange, so there is no bookmaker margin to strip. Its book holds bids only: the price to buy one outcome is 1 minus the best bid on the other. The fair price is the midpoint of the two.

```
fair_yes = (bid_yes + (1 - bid_no)) / 2
```
fair_no = 1 - fair_yes. Needs a bid on both outcomes.

Use the fair price as the market's line when you compare other books, size a bet with [Kelly](https://novigapi.com/kelly-criterion-calculator) or check [EV](https://novigapi.com/ev-calculator).

## Parameters

Query and path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| market_id | string | Yes | Novig market id, one per call. |


## Request

```bash
curl -s "https://novigapi.com/api/v1/fair-price?market_id=01a1cffe-f325-7f23-a073-6f3daa1ee773" \
  -H "Authorization: Bearer nv_..."
```

## Response

Daniss Jenkins 23.5 points plus rebounds plus assists on 12 Nov 2026: bids of 0.49 and 0.47, so the Over ask is 0.53, the spread is 4 points and the fair Over is (0.49 + 0.53) / 2 = 0.51, or -104 in American odds. It is a game market (`WHEN_LIVE`) and the game had not started, so a fill at the ask would pay no fee yet; `fee_per_100_at_ask` shows what it would pay once live.

```json
{
  "data": {
    "market_id": "01a1cffe-f325-7f23-a073-6f3daa1ee773",
    "description": "Daniss Jenkins 23.5 POINTS_REBOUNDS_ASSISTS",
    "formula": "fair_yes = (bid_yes + (1 - bid_no)) / 2",
    "fee_formula": "fee = coefficient x p x (1 - p) x contracts x $0.01 (one contract pays $0.01)",
    "fee_coefficient": 0.06,
    "fee_charged": "WHEN_LIVE",
    "fee_charged_when": "taker pays only on fills matched while the event is OPEN_INGAME; pregame fills pay nothing; makers never pay",
    "two_sided": true,
    "outcomes": [
      {
        "outcome_id": "01a1cffe-f325-7f23-a073-6f45e65729ea",
        "name": "Over 23.5",
        "status": "PENDING",
        "bid": 0.49,
        "bid_qty": 49020,
        "ask": 0.53,
        "fair": 0.51,
        "last": 0.49,
        "spread_pp": 4,
        "american": -104,
        "decimal": 1.9608,
        "fee_per_100_at_ask": 0.014946,
        "ask_after_fee": 0.544946
      },
      {
        "outcome_id": "01a1cffe-f325-7f23-a073-6f50a7b6e1b1",
        "name": "Under 23.5",
        "status": "PENDING",
        "bid": 0.47,
        "bid_qty": 17000,
        "ask": 0.51,
        "fair": 0.49,
        "last": 0.51,
        "spread_pp": 4,
        "american": 104,
        "decimal": 2.0408,
        "fee_per_100_at_ask": 0.014994,
        "ask_after_fee": 0.524994
      }
    ],
    "observed_at": "2026-11-12T17:23:56.000Z",
    "source_age_seconds": 6,
    "edge_cached": true
  },
  "meta": {
    "observed_at": "2026-11-12T17:23:56.000Z",
    "source_age_seconds": 6,
    "edge_cached": true,
    "formula": "fair_yes = (bid_yes + (1 - bid_no)) / 2, the two-sided mid; fair_no = 1 - fair_yes. Prices are probabilities from 0 to 1 (Novig quotes percentages). Taker fee in dollars = 0.06 x P x (1 - P) x contracts x $0.01 (one contract pays $0.01; 0.06 is the fee_coefficient). Per docs.novig.com Trading fees: game markets charge the taker only while the event is live (fee_charged WHEN_LIVE); futures in NFL, NCAAF, NCAAB, NCAAWB, MLB, NBA, WNBA and NHL charge in every phase (ALWAYS); golf, tennis, UFC, F1 and NASCAR futures and series winners never charge. Makers never pay. The fair price is the mid before any fee.",
    "plan": "developer",
    "credits_charged": 1,
    "credits_remaining": 9874,
    "credit_policy": "credits_v1"
  }
}
```

## Fields

Response fields

| Field | Type | Description |
| --- | --- | --- |
| market_id, description | string | Novig market id and label. |
| formula, fee_formula | string | The fair price and fee formulas used, so the number is never a black box. |
| fee_coefficient | number or null | Novig's fee coefficient for this market, 0.06. |
| fee_charged | string or null | `WHEN_LIVE` (taker pays only while the event is `OPEN_INGAME`), `ALWAYS` (major US league futures) or null if not stored yet. |
| fee_charged_when | string | That rule in words. |
| two_sided | boolean | True when the market has two outcomes and both have a bid, which a fair price needs. |
| outcomes[].outcome_id | string | Novig outcome id. |
| outcomes[].name | string | Outcome label, such as `Over 1.5` or `PHX +13.5`. |
| outcomes[].status | string or null | `PENDING` until the outcome is graded (Novig's to-be-decided status), then Novig's grade. |
| outcomes[].bid | number or null | Best resting bid, as a probability from 0 to 1. Null when nobody is bidding. |
| outcomes[].bid_qty | integer or null | Contracts resting at the best bid. One contract pays $0.01. |
| outcomes[].ask | number or null | Price to buy now: 1 minus the best bid on the other outcome. Novig's book holds bids only. Two-outcome markets only. |
| outcomes[].fair | number or null | Fair price: (bid + (1 - other bid)) / 2. Null unless both outcomes have a bid. |
| outcomes[].last | number or null | Last traded price. |
| outcomes[].spread_pp | number or null | Ask minus bid, in percentage points. |
| outcomes[].american, outcomes[].decimal | number or null | The fair price (or the last price when there is no fair) as American and decimal odds. |
| outcomes[].fee_per_100_at_ask | number or null | Taker fee in dollars on 100 contracts ($1 of payout) at the ask, from fee = 0.06 x P x (1 - P) x contracts x $0.01, when it is charged. |
| outcomes[].ask_after_fee | number or null | The ask plus that fee per $1 of payout: the real price of taking it when the fee applies. |
| observed_at | string (ISO 8601) or null | When our collector last read this row from Novig. |
| source_age_seconds | integer or null | Seconds between that read and our answer. |
| edge_cached | boolean | True when the value came through Novig's public CDN, which may serve a copy up to its cache time (5 to 10 seconds) older. |
| meta.formula | string | The formula used, with the fee rule, so the number is never a black box. |
| meta.observed_at | string (ISO 8601) | When our collector read the oldest row in this answer from Novig's public catalog. Each row also carries its own `observed_at`. |
| meta.source_age_seconds | integer | Seconds between that read and our response. On paid plans this stays at about 10 or less. |
| meta.edge_cached | boolean | True when Novig's edge cache served any of the reads, so the source copy may itself be a few seconds old. |
| meta.plan, credits_charged, credits_remaining, credit_policy | string, integer | Your plan, what this call cost, the credits left this month and the credit rules version. |


## Credit cost

1 credit per call, whatever the size of the answer. Errors and 304 Not Modified cost 0; the `X-Credits-Cost` header and `meta.credits_charged` state the price of every call.

## Python

```python
import os
import requests

KEY = os.environ["NOVIGAPI_API_KEY"]  # nv_...
HEADERS = {"Authorization": f"Bearer {KEY}"}

def fair(bid_yes, bid_no):
    """Novig fair price: midpoint of the bid and the ask implied by the other side."""
    if bid_yes is None or bid_no is None:
        return None
    return round((bid_yes + (1 - bid_no)) / 2, 4)

print(fair(0.49, 0.47))  # 0.51, matches the API

r = requests.get("https://novigapi.com/api/v1/fair-price", params={"market_id": "01a1cffe-f325-7f23-a073-6f3daa1ee773"}, headers=HEADERS, timeout=10)
for o in r.json()["data"]["outcomes"]:
    print(o["name"], o["fair"], o["american"], "live price", o["ask_after_fee"])
```

## JavaScript

```javascript
const KEY = process.env.NOVIGAPI_API_KEY; // nv_...
const headers = { Authorization: "Bearer " + KEY };

const toAmerican = (p) => (p >= 0.5 ? Math.round((-100 * p) / (1 - p)) : Math.round((100 * (1 - p)) / p));
const res = await fetch("https://novigapi.com/api/v1/fair-price?market_id=01a1cffe-f325-7f23-a073-6f3daa1ee773", { headers });
const { data: m } = await res.json();
for (const o of m.outcomes) console.log(o.name, o.fair, toAmerican(o.fair));
```

## Notes and edge cases

- A wide spread means a soft fair price. Treat any market with a spread over about 0.05 with care, or weight by depth from the [order book](https://novigapi.com/docs/endpoints/orderbook-snapshot).
- Fees are not in the fair price. Pregame game markets carry no taker fee; once live, fee = 0.06 x P x (1 - P) x contracts x $0.01, which is 0.06 x P x (1 - P) per $1 of payout. Futures in NFL, NCAAF, NCAAB, NCAAWB, MLB, NBA, WNBA and NHL (`fee_charged: ALWAYS`) pay it pregame too. See the [fee calculator](https://novigapi.com/novig-fee-calculator).
- Markets with more than two outcomes, such as three-way moneylines, return `fair: null` and `two_sided: false`: the bids-only book gives no single ask per outcome there. Devig their prices with the [no-vig calculator](https://novigapi.com/no-vig-calculator).
- To devig another book's two prices yourself, use the [no-vig calculator](https://novigapi.com/no-vig-calculator) or the MCP `devig` tool.

## Sources

- [Novig API docs: Trading fees](https://docs.novig.com/api/concepts/fees.md)
- [Novig API reference: Get the order book](https://docs.novig.com/api-reference/catalog/get-the-order-book.md)
- [Novig API docs](https://docs.novig.com)

---

Get a free API key: https://novigapi.com/sign-up . Docs: https://novigapi.com/docs . MCP: https://novigapi.com/api/mcp . Operated by Stunning Couches LLC. Independent. Not affiliated with, endorsed by or sponsored by Novig.
