DocsGuidesView as Markdown

Tokens, quotes and rate limits

How a call is priced, how filters lower the price, and how to handle a 402 or a 429.

A call is priced from the request

Each account has one token pool: a paid plan's resets every month, and the free plan gives 50,000 tokens for 14 days. A call's price comes from the product and the filters you send, never from the size of the reply, except a historical odds day file, priced per MB. GET /v2/pricing publishes the table, and /pricing on the site explains it with worked examples.

On standard, dutching and raw, each filter narrows the price: every sport, bookmaker, exchange or market you name carries points, and the price is multiplied by the named points over 100, never above 1. On dutching and raw the bookmakers and exchanges you name count together as one filter. The four smaller products cost the same whatever you filter. The result is rounded up, and a call never costs less than 1 token.

On raw, one price covers the whole walk: each page pays its share of the query's price. An updatedSince no more than 120 s back pays 10% of that price.

Quote before a big call

Add quote=true to any data request. It returns the price instead of the odds and costs nothing. A quote checks your key and parameters but not your balance, so a quote can succeed where the real call returns 402 (or 503 if the product isn't ready).

A free quote

curl --compressed -s -H "Authorization: Bearer $ODDSRELAY_KEY" \
  "https://api.oddsrelay.io/v2/odds/standard?region=uk&sports=soccer&quote=true"
# {"cost": …, "remaining": …, "rate_card": "…"}

What is free

Discovery (/v2/sports, /v2/events, /v2/bookmakers, /v2/regions), /v2/usage, /v2/pricing, the historical odds files list (/v2/historical/files), quotes, 304 replies, replies with no events, and every refusal.

Read the token headers

Every reply to a valid key carries X-Tokens-Cost. X-Tokens-Used, X-Tokens-Remaining, X-Tokens-Limit and X-Tokens-Reset come with it whenever the balance is known; Remaining and Limit read unlimited on an unlimited account.

On a 402

402 insufficient_tokens means the price is above the balance, and nothing was served or spent. The body carries cost, remaining, resets_at (on the free plan's window or a trial, its end when that comes first), plan, rate_card, quote and, except on a custom Enterprise plan, upgrade_url. Narrow the filters or change plan. On a paid plan, waiting for resets_at also works; on the free plan's window it does not, because no tokens follow its end. Retrying the same call won't help, and a 402 never carries Retry-After.

On a 429

429 too_many_requests means the account's rate limit, per 10 seconds or per minute, or its cap on requests in flight. 429 too_many_from_address is the per-address limit before authentication. 429 too_many_downloads is the historical odds download cap: one file download at a time per account. Wait for the Retry-After seconds, then retry.

Our edge also limits each address and the whole service. Its 429s carry Retry-After with an empty body and no code, as does its 502. Handle an empty-bodied 429 the same way, and back off on a 502.

From the blog

Every parameter: API reference.