Novibet Odds API
The ArbPlay Novibet odds API serves Novibet's own JSON over HTTPS: one live file covering every in-play sport, including esports, and pre-match files for soccer, basketball and tennis about 5 days ahead, most with a Sportradar match id. Live odds refresh about every 1–3 seconds, pre-match about every 4–7.
Novibet is a Greek-licensed online bookmaker. The data comes from Novibet's Greek website.
Key facts
| Bookmaker | Novibet (Greece) |
|---|---|
| Company key | novibet |
| Files | 4: site_live_novibet.json and site_pregame_novibet_{soccer,basketball,tennis}.json |
| Live coverage | Every in-play sport in one file, one view per sport: soccer, basketball, tennis, table tennis, volleyball, American football, baseball, handball, ice hockey, cricket, darts, rugby, League of Legends, Counter-Strike, Dota 2 |
| Pre-match coverage | Soccer and basketball about 5 days ahead; tennis about 2 days |
| Refresh | Live about every 1–3 s, pre-match about every 4–7 s |
| Odds format | Decimal (price, plus the display string oddsText) |
| Cross-bookmaker id | Sportradar match id: sportradarMatchId (pre-match), liveData.sportradarMatchId (live) |
| Schema | A one-element array: [0].betViews[] → pre-match items[] or live competitions[].events[] → markets[].betItems[] |
| Market codes | SOCCER_MATCH_RESULT, SOCCER_UNDER_OVER, SOCCER_DOUBLE_CHANCE, SOCCER_BOTH_TEAMS_TO_SCORE, SOCCER_FIRST_HALF_RESULT… |
| Access | RapidAPI, Zyla API Hub or JoJ API listing, or a direct X-API-Key from ArbPlay |
Files and what's inside
Every file is Novibet's own JSON, served unchanged inside the API envelope. Refresh: live files about every 1–3 s, pre-match files about every 4–7 s.
| File | What's inside | Refresh |
|---|---|---|
site_live_novibet.json | Every live event, one bet view per sport (betViewKey, e.g. SOCCER_MATCH), grouped by competition; live stats in liveData | ≈1–3 s |
site_pregame_novibet_soccer.json | Pre-match soccer: match result, goals over/under, double chance, first-half result, BTTS, corners | ≈4–7 s |
site_pregame_novibet_basketball.json | Pre-match basketball (moneyline, handicap, totals) | ≈4–7 s |
site_pregame_novibet_tennis.json | Pre-match tennis | ≈4–7 s |
Pre-match markets by sport
| Sport | Markets |
|---|---|
| Soccer | Match result, over/under goals (full time and first half), double chance, first-half result, both teams to score, corners, cards |
| Basketball | Winner (no draw), handicap and over/under for the match, the first half and the first quarter |
| Tennis | Match winner, set 1 and set 2 winner, games over/under and games handicap (match and per set) |
Every bookmaker compared: sports and markets per bookmaker.
Field map: where each value lives
Paths start at data[0].betViews[].
| Value | Live files | Pre-match files |
|---|---|---|
| Event id | competitions[].events[].betContextId | items[].eventBetContextId |
| Teams | additionalCaptions.competitor1, .competitor2 | additionalCaptions.competitor1, .competitor2 |
| League | competitions[].caption | items[].competitionCaption |
| Country / region | competitions[].regionCaption | items[].regionCaption |
| Sport | betViews[].betViewKey | betViews[].betViewKey |
| Start time | — (in-play) | items[].startDateTime (ISO) or startDateTimeUnix |
| Market | markets[].betTypeSysname | markets[].betTypeSysname |
| Selection, price | markets[].betItems[].code, .price | markets[].betItems[].code, .price |
| Line | betItems[].instanceCaption (e.g. 3.5) | betItems[].instanceCaption |
| Sportradar id | liveData.sportradarMatchId | items[].sportradarMatchId |
| Link | path (on novibet.gr) | path |
| Status | betItems[].isAvailable (false = not available) | betItems[].isAvailable |
| Live score | liveData.homeGoals, .awayGoals | — |
Real sample
An abridged record from site_pregame_novibet_soccer.json: real values, most fields left out so the structure is readable. The downloads below keep every field.
[
{
"betViews": [
{
"betViewKey": "SOCCER_MATCH",
"items": [
{
"eventBetContextId": 48269323,
"competitionCaption": "Club Friendlies",
"regionCaption": "World",
"startDateTime": "2026-09-26T20:30:00+00:00",
"sportradarMatchId": 74967988,
"path": "matches/atletico-nacional-chapecoense-sc",
"additionalCaptions": {
"competitor1": "Atletico Nacional",
"competitor2": "Chapecoense SC"
},
"markets": [
{
"betTypeSysname": "SOCCER_MATCH_RESULT",
"betItems": [
{
"code": "1",
"price": 2.15
},
{
"code": "X",
"price": 3.8
},
{
"code": "2",
"price": 2.65
}
]
}
]
}
]
}
]
}
]
- site_live_novibet.sample.json — one live soccer, basketball and tennis event
- site_pregame_novibet_soccer.sample.json — trimmed to a few events
Each download is a complete GET /v1/data/{filename} response cut down to a few events, with every id reference still resolving. All samples are listed in samples/index.json.
Extract match-result (1X2) odds in Python
This function is tested against the samples on this page. Pass it the parsed JSON response.
def match_result(payload):
"""(event, 1, X, 2) rows from a Novibet file (live or pre-match)."""
rows = []
for view in (payload["data"] or [{}])[0].get("betViews", []):
# pre-match views list `items`; the live file nests events under competitions
events = view.get("items") or [e for c in view.get("competitions", []) for e in c["events"]]
for ev in events:
teams = ev.get("additionalCaptions") or {}
name = f'{teams.get("competitor1")} - {teams.get("competitor2")}'
for market in ev.get("markets", []):
if market["betTypeSysname"] == "SOCCER_MATCH_RESULT":
odds = {b["code"]: b["price"] for b in market["betItems"]}
rows.append((name, odds.get("1"), odds.get("X"), odds.get("2")))
return rows
Fetch Novibet odds
With a direct key
# 1. which files can this key read?
curl -sS --compressed -H "X-API-Key: YOUR_API_KEY" \
https://api.arbplay.app/v1/files
# 2. download one file (JSON envelope: company, file, updated_at, data)
curl -sS --compressed -H "X-API-Key: YOUR_API_KEY" \
https://api.arbplay.app/v1/data/site_pregame_novibet_soccer.json -o site_pregame_novibet_soccer.json
import requests # pip install requests
resp = requests.get(
"https://api.arbplay.app/v1/data/site_pregame_novibet_soccer.json",
headers={"X-API-Key": "YOUR_API_KEY"}, # gzip is negotiated automatically
timeout=60,
)
resp.raise_for_status()
payload = resp.json()
print(payload["updated_at"], payload["file"])
for event, home, draw, away in match_result(payload): # the function above
print(f"{event}: {home} / {draw} / {away}")
// Node 18+ (server-side: the API sends no CORS headers)
const res = await fetch("https://api.arbplay.app/v1/data/site_pregame_novibet_soccer.json", {
headers: { "X-API-Key": process.env.ARBPLAY_API_KEY },
});
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).detail}`);
const { company, file, updated_at, data } = await res.json();
console.log(file, "updated", updated_at);
Through a marketplace
On RapidAPI, Zyla API Hub or JoJ API you call the marketplace's gateway with that marketplace's key. The two endpoints and the JSON they return are the same; copy the base URL and path from the listing.
| Marketplace | Your key goes in | Base URL and full path |
|---|---|---|
| RapidAPI | X-RapidAPI-Key and X-RapidAPI-Host | Endpoints tab of the listing |
| Zyla API Hub | Authorization: Bearer <access key> | Code sample on the listing |
| JoJ API | X-JoJAPI-Key (or Authorization: Bearer) | Code sample on the listing |
Freshness, gaps and caveats
- Refresh: live files about every 1–3 s, pre-match files about every 4–7 s. Every response carries
updated_atand aLast-Modifiedheader; sendIf-Modified-Sinceto get304 Not Modifiedwhen nothing changed. - The live file has no start times — events are already in play.
- Market names live in
betViews[].marketCaptions(e.g.SOCCER_MATCH_RESULT→ "Full Time Result"); each market only carries itsbetTypeSysname. - Over/under items carry
codeO/Uand the line ininstanceCaption(e.g.3.5).
Get Novibet odds API access
- RapidAPI — Novibet odds listing
- Zyla API Hub — Novibet odds listing
- JoJ API — Novibet odds listing
- Contact ArbPlay for a direct key to
https://api.arbplay.app - Before you buy: direct keys for several bookmakers, trial keys, rate limits and data rights
Plans and quotas are set on each marketplace listing. More in the API reference and the API hub.
Frequently asked questions
Is this the official Novibet API?
No. ArbPlay is independent and is not affiliated with or endorsed by Novibet or its operator. It collects the odds Novibet publishes on its public website and serves them unchanged as JSON for informational use. ArbPlay does not place bets.
Which Novibet files can I download?
Four: site_live_novibet.json, which holds every in-play sport in one file, and site_pregame_novibet_soccer.json, site_pregame_novibet_basketball.json and site_pregame_novibet_tennis.json. Call GET /v1/files to list the files your key can read.
How often are Novibet odds updated?
During active hours live files are rewritten about every 1 to 3 seconds and pre-match files about every 4 to 7 seconds. Every response carries updated_at and a Last-Modified header, and If-Modified-Since returns 304 when nothing changed.
Can I match Novibet events with other bookmakers?
Yes. Pre-match events carry sportradarMatchId and live events carry liveData.sportradarMatchId. Stoiximan, Superbet, OPAP and Bwin expose the same Betradar/Sportradar match id, so you can join on it.
How far ahead do Novibet pre-match files go?
Soccer and basketball reach about 5 days ahead and tennis about 2 days.
How do I get access to the Novibet odds API?
Subscribe to the Novibet listing on RapidAPI, Zyla API Hub or JoJ API and call it with that marketplace's key; plans and quotas are set on each listing. For a direct key to https://api.arbplay.app (header X-API-Key), contact ArbPlay.
ArbPlay is independent and not affiliated with or endorsed by Novibet or its operator. Odds are collected from publicly available bookmaker odds and served unchanged for informational use; ArbPlay does not place bets. 21+.
Other bookmakers: Stoiximan · Fonbet · Superbet · Elabet · OPAP · Bwin. Machine-readable: /openapi.json · /llms.txt. Guide: Greek bookmaker odds API.