# Filters and tokens

> How a call is priced, how filters make it cheaper, and what to do on a 402 or a 429.

## A call is priced from the request

Each account has one token pool a month. A call's price comes from the board and the filters you send, never from the size of the reply. 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 add up into one venue filter. The four smaller boards cost the same whatever you filter.

## Quote before a big call

Add quote=true to any data request. It returns the price instead of the board and costs nothing. It runs the checks that come before the price (key, region, scope, parameters, filters), but not the balance and not whether the board is ready: if cost is above remaining the real call would be refused 402, and a board that isn't ready answers the real call 503.

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, 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 a trial, the trial's end when that comes first), `plan`, `rate_card`, `quote` and, except on a custom Enterprise plan, `upgrade_url`. Narrow the filters, wait for `resets_at`, or change plan. 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 flood cap, 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. Wait for the Retry-After seconds, then retry.

The front door in front of the API also caps 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.

Source: https://oddsrelay.io/docs/guides/filters-and-tokens · the API contract: https://api.oddsrelay.io/v2/openapi.json
