Italian bookmaker odds,
in one API

Normalized odds from dozens of bookmakers — including the Italian books global APIs lack — in a stable JSON format. For your models, bots and tools.

● IT books on a continuous cycle · measured freshness stable event_id · last_update per quote self-serve · no card

GET /api/v1/odds live feed
# one request, all the odds for an event
curl "https://odss-api.com/api/v1/odds?sport=calcio&league=serie%20a" \
  -H "x-api-key: odss_live_..."

{ "count": 118, "offset": 0, "returned": 118, "state": "prematch", "odds": [{
  "event_id": "a3f9c1e07b2d4865", "event": "Inter - Milan",
  "league": "Serie A", "market": "1x2", "commence_time": "2026-08-23T18:45:00Z",
  "bookmakers": [
    { "key":"snai", "outcomes":{"HOME":2.10,"DRAW":3.40,"AWAY":3.60}, "last_update":"2026-07-14T10:32:05Z" },
    { "key":"bet365", "outcomes":{"HOME":2.05,"DRAW":3.50,"AWAY":3.70}, "last_update":"2026-07-14T10:28:12Z" },
    { "key":"leovegas", "outcomes":{"HOME":2.08,"AWAY":3.55}, "suspended":["DRAW"], "last_update":"2026-07-14T10:31:44Z" } ]}]}

Three moves to integrate the odds

01

Create a key

Sign up and generate an odss_live key in a minute. The Free plan is forever, no card required.

02

Call /odds

One endpoint, all cross-book odds by event and market. Filter by sport, league, market and bookmaker.

03

Integrate and sync

Stable event_id to recognize events, last_update for freshness, offset to read the whole schedule.

The moat: Italian books.

The ADM bookmakers global APIs don't have

Dozens of ADM-licensed Italian operators, plus international reference books and exchanges. The list active right now is at /api/v1/bookmakers, with an API key: no brand wall to take on trust. country, playable_it and is_exchange are response fields, not query parameters — the endpoint accepts none.

GET /bookmakerskeycountryplayable_itis_exchange

Stable schema

A public, versioned JSON format: the engine's internal shape never leaks into your code.

Reliable integration

Deterministic event_id for the whole prematch window, ISO last_update per book, offset pagination: no-surprise syncs.

Honest freshness

Italian books run on a continuous cycle and the real freshness is measured and public, per book, on the status page; bet365 arrives via a third-party data provider under a contractual licence, with a cadence of a few minutes. Every quote declares its last_update: no stale numbers dressed up as live.

The honest comparison.

Where we stand vs global APIs and the market average. No names, no promises.

Feature
odss-api
Market average
Italian ADM books
Direct, verifiable coverage (/coverage public, /bookmakers with a key), measured, public freshness (p50/p95 at /status).
Absent: they cover foreign books (US/UK/offshore), no ADM book.
How you pay
Per account: monthly quota + rate/min. More books or markets per event don't add cost.
Per simultaneous book, or markets×regions credits: cost explodes on multi-book.
Cross-book
Deterministic event_id shared by all markets of a fixture: native comparison, no heuristic matching.
Often proprietary odds or non-deterministic matching.
Freshness
ISO last_update in the clear, book by book: you know how recent each leg is.
Often not exposed per single book.
Agent-ready
OpenAPI 3.1, llms.txt, JSON-LD, /.well-known/api-catalog: an agent finds and reads it on its own.
Docs behind login or blocked crawlers, no agentic standard.
Price & onboarding
Public pricing with a Free tier; self-serve configurable Enterprise. A key in a minute.
Sales-gated, opaque Enterprise, or self-serve without Italian books.
Targeted keys
Scopable by sport/league (e.g. a «soccer only» key), with no key-count limit.
Not documented.

Comparison against the average of the global/enterprise providers reviewed (Jul 2026). Our side is verifiable from the public endpoints and the docs.

Bookmakers & leagues

Live numbers, counted from the feed right now — not a catalog inventory.

bookmakers active in the feed

sports priced right now

leagues on the board

The named list of the books active right now is at GET /api/v1/bookmakers, with the country, playable_it, is_exchange and source fields: it requires an API key (the Free one takes a minute, no card). Without a key, GET /api/v1/leagues — the source of the counts above — and GET /api/v1/coverage are public.

Leagues on the board right now

Live data from the feed (public endpoint /api/v1/leagues): for each sport, the leagues currently priced. Names are the values for the league filter.

We don't exclude any league. We track the main ADM bookmakers — the exact list is at /api/v1/bookmakers — and show everything they price: if a book in the feed quotes a match, you see it here too — from the big European leagues to minor divisions and international competitions. What appears depends on season and timing: no matches means bookmakers don't price them, so they don't show. The list below is the schedule at this moment.

Loading the schedule…

The board follows the season: club football is naturally thinner in summer.

Documentation

Base URL https://odss-api.com. Authenticate with the x-api-key: odss_live_… header or Authorization: Bearer. JSON responses, European decimal odds.

GET /api/v1/mock/odds no key needed

Every endpoint has a twin under /api/v1/mock/ that answers right now, with no signup and no quota consumed: same response shape, same parameters, same strict validation as the real feed. The prices are synthetic — mock: true, header X-Odss-Mock: 1, ids prefixed mock_ — they are there to write and test your code, not to bet on.

curl "https://odss-api.com/api/v1/mock/odds?sport=calcio&limit=3"

Available: /mock/odds · /mock/odds/history · /mock/sports · /mock/bookmakers · /mock/leagues · /mock/status · /mock/stream (SSE). The seed parameter makes the payload reproducible: use it in CI instead of burning quota on every run.

On the REAL feed these are public with no key too: /api/v1/leagues, /api/v1/coverage and /api/v1/status.

First call in 3 steps

01

Create a key

Sign up and generate a key in the dashboard. The Free plan is forever.

02

List sports

Verify the key with a call to /sports.

03

Get odds

Call /odds with sport and market: you get cross-book odds.

GET /api/v1/odds example

curl "https://odss-api.com/api/v1/odds?sport=calcio&league=serie%20a&limit=5" \
  -H "x-api-key: odss_live_..."
const r = await fetch(
  "https://odss-api.com/api/v1/odds?sport=calcio&league=serie%20a&limit=5",
  { headers: { "x-api-key": "odss_live_..." } }
);
const { count, odds } = await r.json();
import requests
r = requests.get(
    "https://odss-api.com/api/v1/odds",
    params={"sport": "calcio", "league": "serie a", "limit": 5},
    headers={"x-api-key": "odss_live_..."},
)
data = r.json()  # { count, offset, returned, state, odds: [...] }

GET /api/v1/odds

Current cross-book odds, grouped by event, market and line. Each record lists the bookmakers with their outcomes and the timestamp of their last update.

Parameters

ParameterDescription
sportExact sport filter (e.g. calcio, tennis, basket). Values: see /api/v1/sports.
marketCanonical market: 1x2, ou, btts, dc, ah (Asian handicap), eh (European handicap), moneyline…
bookmakersCSV list of book keys (e.g. snai,bet365). Values: see /api/v1/bookmakers.
leagueCase-insensitive substring filter (e.g. serie a). Values: see /api/v1/leagues.
event_idA single event, by exact id.
stateprematch (default), live (in-play, with current score and minute) or all (both). With live, if the in-play engine is off the list is empty and live_enabled=false. If the key has a feed scope (prematch-only or live-only), a state outside the scope returns 403 and all degrades to the allowed state.
limitRecords per page. Default 500, max 2000.
offsetStart index for pagination. Default 0.

Response fields

FieldDescription
countTotal records matching the filters (across all pages).
offset · returnedEcho of the requested offset and the records actually returned in this page.
odds[].event_idDeterministic event id: identical for every market of the same fixture and stable for the whole prematch window.
odds[].eventNormalized event name (Home - Away).
odds[].sport · leagueSport and league/competition of the event.
odds[].home_team · away_teamThe two teams, when available.
odds[].commence_timeEvent start, ISO 8601 UTC.
odds[].market · line · scope · periodCanonical market, optional line (e.g. 2.5), scope (e.g. team) and period (e.g. 1st half).
odds[].state · score · minutestate = prematch or live. For live: current score (e.g. "1-0") and minute (e.g. "63'"). Same event_id as prematch to correlate the fixture across the two states.
…bookmakers[].keyBookmaker key, with country, playable_it and is_exchange.
…bookmakers[].outcomesOutcome → decimal odds map (e.g. HOME: 2.10).
…bookmakers[].suspendedOutcomes this book prices but is not taking bets on right now. They are not in outcomes (a suspended outcome has no playable price) and are named here instead, so that «the book does not offer this outcome» and «it offers it and is closed right now» stay two distinct facts. Optional field, and its absence means something: if missing, that book's source does not publish the state; [] means it was read and nothing is suspended. Never read an absent field as an empty list.
…bookmakers[].last_updateISO timestamp of that book's last successful odds update.

Pagination

Repeat the call increasing offset by returned, as long as offset + returned < count. The board is live: count may shift slightly between pages.

GET /api/v1/odds?sport=calcio&limit=1000&offset=0
GET /api/v1/odds?sport=calcio&limit=1000&offset=1000
# … finché offset + returned < count

GET /api/v1/sports

The sports currently available in the feed (the values for the sport parameter).

GET /api/v1/bookmakers

The bookmakers active in the feed, with country (ISO 3166-1 alpha-2 code of the licensing country — IT, GB, US, SE… — or world when none is attributed), playable_it (true only for books holding an Italian ADM licence, i.e. playable from Italy: false for every other book in the feed, from sharp references like Pinnacle to the international brands), is_exchange (commission on winnings) and source (direct when we read the book ourselves, partner_feed when its prices reach us through a third-party data provider).

GET /api/v1/leagues public, no key

The current schedule, aggregated: for each sport the priced leagues, with event and bookmaker counts. Useful to discover values for the league filter.

GET /api/v1/stream Pro and Enterprise

Server-Sent Events: a hello event on connect, then odds events with the CHANGED records (same schema as /odds, each with its own state) and the removed ones, within ~10 seconds of the engine detecting them — no polling. Optional sport and state (prematch|live|all) parameters; initial snapshot via GET /odds?state=…. Data cadence stays the engine's (per-book freshness measured on the status page; bet365 via a third-party data provider under a contractual licence): the stream removes polling latency, last_update is authoritative. Max 3 concurrent streams; the connection counts as 1 quota request.

GET /api/v1/odds/history

Odds change history for an event: one row every time a bookmaker moves a price on a group. Filters event_id (required), book, market, from/to (ISO), limit. Newest first: for a started event the first row is its closing line. Honours the key scope.

curl "https://odss-api.com/api/v1/odds/history?event_id=a3f9c1e07b2d4865&book=snai" \
  -H "x-api-key: odss_live_..."

GET /api/v1/middles

Over/Under middles computed from the current feed: OVER on a low line at one book, UNDER on a high line at another. If the total lands inside the window both bets win. Fields middle_window, hit_return_pct, miss_return_pct, safe (no loss even when it misses). Filters: sport, min_return, safe, limit.

Freshness rule: a price older than stale_after_seconds (900s by default) stays in /odds responses with its last_update, but is never paired into a middle: a stale leg probably no longer exists on the bookmaker site. The applied threshold and the number of discarded legs are in the response.

curl "https://odss-api.com/api/v1/middles?sport=calcio&safe=true" \
  -H "x-api-key: odss_live_..."

GET /api/v1/coverage public, no key

How many bookmaker brands have a valid price in the current feed, per region (Italy, USA, UK, world). It does not match the number of entries in /api/v1/bookmakers: that endpoint lists the queryable keys, where dedicated market lanes (e.g. <brand>-corners) count on their own, while here they are folded under the brand.

POST /api/mcp MCP

MCP server (JSON-RPC 2.0) for AI agents and connectors (Claude, ChatGPT…). Auth with the same key (Authorization: Bearer odss_live_… or x-api-key). Tools: get_odds (with state=live), list_sports, list_bookmakers, list_leagues. Only tools/call uses quota; the handshake is free. Stateless: every request is self-contained.

curl -X POST https://odss-api.com/api/mcp \
  -H "Authorization: Bearer odss_live_..." -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"get_odds","arguments":{"sport":"calcio","state":"live","limit":5}}}'

Webhook Enterprise

Register an https URL from the dashboard or via API — POST /api/account/webhooks with your account session (body {url, sport?, state?}; the secret is shown once, max 20 per account) — and receive odds changes via POST: same {changed, removed} payload as the stream. Each delivery is signed: X-Odss-Signature: t=<unix>,v1=<hex> = HMAC-SHA256 of «{timestamp}.{body}» with the webhook secret (verify it, reject old timestamps). https only, redirects not followed; endpoints that repeatedly fail auto-disable. Respond 2xx. One delivery can arrive as several consecutive POSTs, each signed on its own and numbered by the X-Odss-Page: page/total header: every body carries page, pages, changed_total and removed_total, so the first page already tells you how much is coming. Don't rate-limit the endpoint: a rejected page stops the ones after it.

Limits, headers and errors

Every authenticated response includes X-RateLimit-Limit (your plan's monthly quota), X-RateLimit-Remaining and X-RateLimit-Reset (unix seconds when the window reopens; on the monthly-quota 429 the same instant is in the body as retry_at). The quota is a rolling 30-day window.

StatusDescription
400Invalid request: unknown parameter, value outside the allowed set (e.g. state) or missing required parameter (e.g. event_id on /odds/history). The response body says which.
401Missing, invalid or revoked key.
403Out of scope: suspended account, feed outside the key's scope (e.g. live with a prematch-only key) or plan-gated feature (stream: Pro and Enterprise; webhooks: Enterprise).
429Burst: per-minute requests of your plan exceeded. Retry-After: 60 header.
429Monthly quota exhausted: upgrade or wait for the window.
502Feed temporarily unavailable: retry with backoff.

Parameters: no silent failures

On every /api/v1 endpoint a parameter we don't recognize is never ignored: if you write bookmaker instead of bookmakers you get a 400 with the wrong name, the list of the ones allowed on that endpoint and, if it's a typo, a suggestion for the right name. The comparison is exact: even Sport with a capital letter is rejected. The catalog endpoints (/sports, /bookmakers, /leagues, /coverage, /status) accept no parameters. We prefer an error right away over a 200 response with unfiltered data that looks correct: the 400 is deterministic, it should be fixed rather than retried, and it does not use quota.

The same rule applies to the tool arguments on the MCP server (POST /api/mcp): a name that doesn't exist, or a wrong type such as a list where a CSV string is expected, gets a JSON-RPC -32602 error instead of being ignored. The error.data field carries the allowed names, so the agent corrects itself.

curl "https://odss-api.com/api/v1/odds?bookmaker=snai" -H "x-api-key: odss_live_..."

HTTP/1.1 400 Bad Request
{
  "error": "Parametro sconosciuto: \"bookmaker\" (forse intendevi \"bookmakers\"?). Ammessi su questo endpoint: bookmakers, content, event_id, league, limit, market, offset, player, sport, state"
}

Machine-readable · contract & agents

To generate clients, SDKs or use the API from an AI agent: the OpenAPI 3.1 contract and a concise LLM guide are public and always in sync.

FieldDescription
/openapi.jsonOpenAPI 3.1 contract (endpoints, parameters, schemas, x-api-key auth).
/llms.txtMarkdown guide for LLMs (llmstxt.org): summary and links to resources.
/postman_collection.jsonPostman collection: import it and set the x-api-key variable to try the endpoints right away.
/sdk/odss_api.pyOfficial Python SDK (single-file, zero dependencies): typed client with automatic pagination and live support.
/sdk/odss-api.tsOfficial TypeScript SDK (single-file, zero dependencies): types, async iterator and an SSE stream helper.
/.well-known/api-catalogAPI catalog (RFC 9727, JSON linkset).

Usage license

Internal use (models, bots, analysis, backtests) is included in every plan. Redistributing the data — e.g. showing it to your product's end users — requires the Display Redistribution licence (Enterprise add-on, +€120/month), which covers display only. Creating, powering or commercialising surebet/arbitrage services, value betting or equivalents requires the Surebet API instead, the plan that includes the licence to resell the computed surebets: €950/month + VAT, from the site. Redistributing the API or the raw data stays outside every plan: for that, write to [email protected].

The right plan for your volume.

Same coverage on every plan: you only pay for volume. Start free, cancel anytime.

Free

To explore the API. Forever, no card.

0forever
Start free
  • 500 requests / month
  • 30 requests / min
  • Full coverage: every sport and every book in the feed

Hobby

For personal projects and small bots.

19/month
+ VAT
Choose Hobby
  • 10,000 requests / month
  • 60 requests / min
  • Full coverage: every sport and every book in the feed
★ Most chosen

Starter

For bots and production integrations.

79/month
+ VAT
Choose Starter
  • 100,000 requests / month
  • 120 requests / min
  • Full coverage: every sport and every book in the feed

Pro

For platforms and high volumes.

159/month
+ VAT
Choose Pro
  • 500,000 requests / month
  • 600 requests / min
  • Priority support

Enterprise

For platforms, companies and resellers: configure volume, rate and license — the price updates by itself and you activate at checkout, no negotiation.

199/month
+ VAT
+€120

Authorises you to show the data to your product's end users — websites, apps, dashboards, widgets, comparison tools (without it, use stays internal). It does not authorise creating or commercialising surebet/arbitrage services, value betting or equivalent platforms, nor redistributing the API or the raw data: those need a dedicated commercial licence. Read the license →

  • SSE streaming included (/api/v1/stream)
  • Quota and rate configured on your account
  • Automatic activation on payment, cancel anytime

By proceeding you accept the Enterprise & Redistribution License (readable from the link above) in addition to the Terms of service.

Prices shown are exclusive of VAT. Applicable tax is added at checkout based on your country and tax status: 22% for Italy (including businesses with an Italian VAT number); reverse charge, 0% tax, for businesses in other EU Member States with a valid VAT number; outside the scope of Italian VAT for non-EU customers. The total amount you pay is the one shown in the checkout summary, which you confirm before placing your order (§4 of the Terms) · Payments via Stripe · one-click cancellation from the portal · quota is a rolling 30-day window

Three tiers, one engine.

Normalized odds are the first tier. If what you want to sell are the arbitrages themselves, you need a different tier: the surebets already computed, with the right to resell them included in the subscription.

Tier 1 · self-serve

Odds API

Normalized odds and data. From the Free plan to Enterprise, public pricing, instant activation.

Tier 2 · self-serve

Surebet API

The surebets already found and computed by the engine, refreshed every 180 seconds, not just the odds. An API plan at €950/month + VAT, resale licence included.

Tier 3 · under contract

Surebet White Label

The complete platform, under your brand, ready to be commercialised. €2,000/month + VAT.

Resale licence included

Surebet API

For whoever builds a product of their own on top of it. It does not return odds alone: it returns the surebets already identified and computed by our engine, refreshed every 180 seconds. If you have nobody to resell them to, you do not need it: surebett.app is enough.

€950per month, exclusive of VAT. One price only: the licence to resell the computed surebets to your users is included in the subscription. It is an API plan like Starter and Pro — one key, its quota, its rate — monthly, cancelled in one click from the billing portal. If you have a promotional code, you enter it at checkout.

Activated as soon as the payment goes through, cancel in one click from the portal. It is a plan of its own and does not stack on a listed plan: if the account already has a paid one active, it has to be cancelled first. By proceeding you enter into the Surebet API Commercial License, within the limits of the use you declared above, and accept the Terms of service (§5).

  • Event and market
  • Bookmakers involved and the odds of each leg
  • Arbitrage percentage/margin
  • Optimal stakes
  • Odds timestamp and freshness
  • The identifiers needed for integration

The fields listed are those provided where available: the response carries what the engine actually computed for that event. The resale licence is included in the subscription: you may use the computed surebets in a commercial product of your own, aimed at your end users, within the limits of the declared use and of the Terms. It does not cover the White Label, which remains a separate contract.

Platform as a service

Surebet White Label

For companies that do not want to build the platform themselves: the complete Surebet platform, delivered as a service under your own brand.

€2,000per month, exclusive of VAT. Activation and term as per the White Label contract.
Request a White Label demo
  • Surebet engine
  • Data and updates
  • Complete frontend
  • Logo, name and colour customisation
  • Hosting and infrastructure
  • Maintenance and updates

The software, the engine and the source code remain our property and are granted for use under the White Label contract.

The «Display Redistribution» licence of the API plans authorises you to show the odds inside your product: it does not authorise creating or commercialising surebet/arbitrage services, value betting or substantially equivalent platforms, nor redistributing the API or the raw data. Those uses require the Surebet API Commercial License or the White Label contract — see the commercial licences and the Terms, §5.

Frequently asked questions.

Can I use the data in a commercial product (SaaS)?

Internal use — your own models, bots, analysis, tools — is included in every plan. Showing the data to your product's end users requires the Display Redistribution licence (Enterprise add-on): it authorises display only. If what you want to sell are the surebets — arbitrage, value betting or equivalent services — you need the Surebet API, bought from the site like any other API plan: €950/month + VAT, with the licence to resell them included in the subscription and the declared-use form required before payment. If you have nobody to resell to, you do not need it: surebett.app is enough. The complete platform under your own brand remains the White Label, under contract — see Surebet API and White Label.

How often are odds updated?

Italian bookmakers on a continuous cycle — the REAL freshness, measured per book (p50/p95), is public on the status page; bet365 arrives via a third-party data provider under a contractual licence, with a cadence of a few minutes. You don't have to take our word for it: every quote in the response carries its last_update.

Is there a trial of the paid plans?

The Free plan is forever and has the same coverage as the paid plans: it's the best way to verify the data. If you need more volume for an evaluation, write to [email protected].

How is this different from surebett.app?

Same engine, two products: odss-api sells the raw normalized odds to build on; surebett.app is the finished product, with arbitrages already computed and balanced stakes.

Is there an API for the odds of ADM-licensed Italian bookmakers?

Yes: the API exposes the odds of the Italian licensees currently in the feed, filterable with the bookmakers parameter. The list active right now is at GET /api/v1/bookmakers, which requires an API key (the Free one takes a minute, no card); without a key, /api/v1/leagues and /api/v1/coverage are public. Every quote carries its last_update.

Can I export odds to a database or Excel?

Yes: the API returns standard JSON, so it goes straight into Postgres, SQLite, pandas or Google Sheets. With the Python and TypeScript SDKs it takes a few lines; the Free plan (500 requests/month) is enough to try, no card.

How much does a sports odds API cost?

Here: Free 500 requests/month without a card, Hobby €19/month + VAT (10,000), Starter €79/month + VAT (100,000), Pro €159/month + VAT (500,000), Enterprise from €199 + VAT. All amounts are exclusive of VAT: for an Italian consumer 22% is added. Businesses in other EU Member States with a valid VAT number are subject to reverse charge (0% tax); for non-EU customers the supply is outside the scope of Italian VAT. The total is always shown in the checkout summary, which you confirm before the order (§4 of the Terms). Same coverage on every plan: you only pay for volume.

Are the odds real-time?

Italian books run on a continuous cycle and freshness is measured, not promised: p50 and p95 over the last 24h are public on the status page, per book. SSE streaming for push; in-play has its own feed.

Forgot your password?