Sports odds in one schema, with the +EV worked out.

UnerringAPI reads sportsbooks, exchanges and pick'em apps, merges them into one event per game, and scores each price against a sharp consensus. Arbitrage, middles and low holds come from the same board. Read it over REST, or hold a WebSocket stream open.

One schema

Each venue answers in the same shape: event, bookmaker, market, outcome. What only some venues have is an extra field on that shape, not a different format.

FieldSportsbookExchange or prediction marketPick'em app
priceAmerican, decimal or probabilityAmerican, decimal or probabilityNull unless the app publishes one
liquidityNot sentDollars at this price, where knownNot sent
multiplierNot sentNot sentPer-pick payout, where published
variantNot sentNot sentstandard, goblin or demon
time_basisOn the bookmaker, not each outcome: snapshot when the book's newest copy is older than our receipt (its Date, Age or the venue's own read time say so), read when it is as of our receipt
{
  "id": "mkt_0k2v9qa1x7m3pc",
  "key": "total",
  "period": "full_game",
  "line": 224.5,
  "outcomes": [
    { "id": "sel_1f8s2ld0q9w4ze", "name": "Over", "side": "over",
      "point": 224.5, "price": -108 },
    { "id": "sel_0p3n7ty5h2c6vb", "name": "Under", "side": "under",
      "point": 224.5, "price": -112 }
  ],
  "suspended": false
}

Example of a market's shape. The values are illustrative, not live prices.

Computed for you

The same board of current prices feeds all of these, after stale, suspended and already-started prices are dropped. A book never helps set its own fair price.

How the numbers are worked out

  • +EV

    /v1/ev

    Each price against a weighted consensus of the other price families, with the margin removed. Rows carry the fair probability, EV percent, Kelly fraction and the books that set the price.

  • Arbitrage

    /v1/arbitrage

    Two-way pairs across different price families, with the stake split for each leg. A wide gap between the times the legs were read is flagged.

  • Middles

    /v1/middles

    Over the lower total and under the higher, or two spreads that leave a gap. Each row gives the window and what it costs to hold both legs.

  • Low holds

    /v1/holds

    The lowest combined margin on each two-way market, taking the best price on each side.

  • Exchange depth

    /v1/smart-money

    An exchange price with known depth, beside the best sportsbook price on the other side. It reports depth, not trade flow.

  • Pick'em edges

    /v1/dfs

    A fair chance for each pick'em line from the sharp books' prices, against what that pick must hit to break even on that app.

REST and a stream

REST answers are JSON with a request id, the credits used and paging details. Rows that don't fit on a page are reported, so a short answer is never mistaken for a complete one.

The stream sends a snapshot, then a delta when a read changes something. Its rate follows how often each venue is read, not a fixed tick. A sequence number shows you any gap.

curl -s "https://unerring-api.liam-banks2004.workers.dev/v1/ev?league=nba&min_ev=2" \
  -H "Authorization: Bearer $UNERRING_KEY"
const ws = new WebSocket("wss://unerring-api.liam-banks2004.workers.dev/v1/stream");

ws.onopen = () => ws.send(JSON.stringify({ type: "auth", api_key: key }));

ws.onmessage = ({ data }) => {
  const message = JSON.parse(data);
  if (message.type === "welcome") {
    ws.send(JSON.stringify({ type: "subscribe", leagues: ["nba"], markets: ["main"] }));
  }
  // snapshot, delta, event, heartbeat, pong, error
};

Coverage is measured

A book's name in our list says nothing about whether we have its prices. Each book has a state worked out from prices actually seen, and a reason where it isn't feeding.

See every book and its state

Feeding
Its prices were seen recently and it is on the current board.
Stale
Its prices have been seen, but not recently, or it is no longer on the board.
No data
We expect prices from it and have never seen any.
Not expected
No online prices to collect: a retail venue, a closed app, a salary-cap contest or something that isn't a book.

Plans

A request costs 0 to 3 credits, whatever the size of the answer. Errors cost nothing. A stream costs 1 credit to connect and 1 for each minute it stays open.

Plan Per 30 days Credits Requests a minute Stream sockets Includes
Sandbox $0 50, one time 20 0 Pre-game odds, props, history
Edge $49.99 150,000 300 0 Sandbox, plus +EV, arbitrage, middles, holds, exchange depth, pick'em, futures
Sharp $199.99 Unlimited 1,200 0 Same as Edge
Syndicate $249.99 Unlimited 3,000 10 Edge, plus live events and the stream
Enterprise Not listed Unlimited 6,000 50 Same as Syndicate

Paid checkout gives 30 days of access per payment and does not renew automatically. An API key and account are required first; the operator currently issues both. The futures endpoint currently returns an empty list.

Plans are priced in USD. Operated by VyrexCode (Vyrex Software & Development). Review our Terms and Privacy Policy. For billing or refund enquiries, contact support.