How Soccer Odds APIs Work (With Real Examples)
Learn how Soccer Odds APIs organise matches, bookmakers, markets, selections and prices, with practical examples for live odds, historical movements and market integration.

A Soccer Odds API connects an application to structured betting-market data. Instead of manually collecting prices from multiple websites, developers can retrieve pre-match odds, live odds, bookmaker markets, historical snapshots, market status and settlement information through one documented interface.
This guide explains how Soccer Odds APIs work with practical examples. It covers fixtures, bookmakers, markets, selections, decimal, fractional and American formats, live price changes, historical odds, market suspension, settlement, normalisation, caching, security and production integration.
What Is a Soccer Odds API?
A Soccer Odds API returns machine-readable betting data for soccer fixtures. The data is normally organised around a hierarchy of matches, bookmakers, markets, selections and prices.
Match
└── Bookmaker
└── Market
└── Selection
├── Price
├── Odds format
├── Status
├── Live or pre-match
└── Updated timestamp
For example, one match may have several bookmakers. Each bookmaker may offer markets such as match winner, both teams to score, over or under goals and correct score. Each market contains selections with current prices.
Core Soccer Odds Data Model
| Entity | Purpose | Example |
|---|---|---|
| Match | The soccer fixture being priced | North City vs United Athletic |
| Bookmaker | The source offering the price | Example Sportsbook |
| Market | The question being priced | Match Winner |
| Selection | One possible market outcome | Home, Draw or Away |
| Price | The odds assigned to the selection | 1.84 |
| Status | Whether the market is available | Open, suspended, closed or settled |
| Timestamp | When the price was last updated | 2026-08-06T10:30:18Z |
Pre-Match vs Live vs Historical Odds
| Odds type | When it is used | Typical application |
|---|---|---|
| Pre-Match Odds | Before kickoff | Match previews and pre-event comparison |
| Live Odds | While the match is in progress | In-play sportsbook and trading interfaces |
| Historical Odds | Previously recorded prices | Research, analytics and model development |
| Settlement Data | After the market is completed | Reconciliation and historical records |
How Pre-Match Odds Work
Pre-match odds are published before kickoff. They can change as new information becomes available, including line-ups, injuries, weather, team news and market activity.
Illustrative Request
GET /v1/soccer/matches/match_74021/odds
Authorization: Bearer YOUR_API_KEY
Accept: application/json
Illustrative Pre-Match Response
{
"data": {
"match_id": "match_74021",
"status": "scheduled",
"starts_at": "2026-08-06T18:00:00Z",
"bookmakers": [
{
"bookmaker_id": "bookmaker_12",
"name": "Example Sportsbook",
"markets": [
{
"market_id": "market_match_winner",
"name": "Match Winner",
"status": "open",
"is_live": false,
"outcomes": [
{
"selection_id": "home",
"name": "North City",
"price": 1.84,
"price_format": "decimal"
},
{
"selection_id": "draw",
"name": "Draw",
"price": 3.45,
"price_format": "decimal"
},
{
"selection_id": "away",
"name": "United Athletic",
"price": 4.20,
"price_format": "decimal"
}
]
}
]
}
],
"updated_at": "2026-08-06T10:30:18Z"
}
}
How Live Soccer Odds Work
Live odds are updated while a match is in progress. Prices may change after goals, cards, penalties, substitutions, VAR decisions and changes in match time or statistics.
A market may be suspended around an important event while the bookmaker recalculates its prices.
Illustrative Live Response
{
"data": {
"match_id": "match_74021",
"match_status": "live",
"minute": 67,
"score": {
"home": 2,
"away": 1
},
"bookmakers": [
{
"bookmaker_id": "bookmaker_12",
"markets": [
{
"market_id": "market_match_winner",
"status": "open",
"is_live": true,
"outcomes": [
{
"selection_id": "home",
"price": 1.36
},
{
"selection_id": "draw",
"price": 4.80
},
{
"selection_id": "away",
"price": 10.50
}
]
}
]
}
],
"updated_at": "2026-08-06T19:24:12Z"
}
}
Why Live Markets Become Suspended
Live markets can be temporarily suspended when an event may significantly change the probability of an outcome.
- A goal is scored
- A penalty is awarded
- A red card is shown
- A VAR review begins
- The match reaches a critical stage
- The data connection becomes uncertain
- The bookmaker closes the market
Illustrative Suspended Market
{
"market_id": "market_match_winner",
"status": "suspended",
"is_live": true,
"suspended_at": "2026-08-06T19:24:05Z",
"reason": "important_match_event"
}
Common Soccer Betting Markets
Match Winner
Home win, draw and away win selections.
Double Chance
Home or draw, away or draw, or either team to win.
Both Teams to Score
Yes or no selections for whether both teams score.
Over and Under Goals
Total-goal lines such as over or under 2.5.
Asian Handicap
Handicap selections using quarter, half and whole-goal lines.
Correct Score
Individual scoreline selections where supported.
First Goalscorer
Player selections for the first goal where line-ups are supported.
Cards and Corners
Team or match totals for supported cards and corner markets.
Half-Time and Full-Time
Combined first-half and final-result selections.
Odds Formats Explained
Decimal Odds
Decimal odds show the total return for each unit staked, including the original stake.
Decimal odds: 2.50
Stake: 10
Total return:
10 × 2.50 = 25
Profit:
25 - 10 = 15
Fractional Odds
Fractional odds show the potential profit relative to the stake.
Fractional odds: 3/2
Stake: 10
Profit:
10 × 3 / 2 = 15
Total return:
15 + 10 = 25
American Odds
Positive American odds show the profit from a stake of 100. Negative American odds show the stake required to win 100.
Positive odds: +150
Stake: 100
Profit: 150
Negative odds: -200
Stake required to win 100: 200
Convert Between Odds Formats
Decimal to Fractional
fractional value = decimal odds - 1
Example:
2.50 - 1 = 1.50
1.50 = 3/2
Decimal to American
If decimal odds are 2.00 or greater:
American = (decimal - 1) × 100
If decimal odds are below 2.00:
American = -100 / (decimal - 1)
JavaScript Format Conversion
function decimalToAmerican(decimalOdds) {
if (!Number.isFinite(decimalOdds) || decimalOdds <= 1) {
throw new Error('Decimal odds must be greater than 1.');
}
if (decimalOdds >= 2) {
return Math.round((decimalOdds - 1) * 100);
}
return Math.round(-100 / (decimalOdds - 1));
}
Implied Probability
Decimal odds can be converted into a basic implied probability.
Implied probability = 1 / decimal odds
Example:
1 / 2.50 = 0.40
Implied probability:
40%
The combined implied probabilities of all selections may exceed 100% because the prices can include bookmaker margin.
Understanding Bookmaker Margin
Illustrative Match Winner Prices
Home: 2.00
Draw: 3.50
Away: 4.00
Implied Probabilities
Home:
1 / 2.00 = 50.00%
Draw:
1 / 3.50 = 28.57%
Away:
1 / 4.00 = 25.00%
Total:
103.57%
The amount above 100% is commonly used as a simple indication of the market’s built-in margin, though exact pricing interpretation can be more complex.
Why Stable IDs Matter
Bookmakers may use different labels for the same market. Teams and players may also appear with abbreviations or alternative names.
Do not compare:
"Match Result"
"1X2"
"Full Time Result"
using text labels alone.
Instead compare:
market_id = "market_match_winner"
Recommended Stored Identifiers
- Match ID
- Competition ID
- Bookmaker ID
- Market ID
- Selection ID
- Team or player ID where relevant
Normalise Markets Across Bookmakers
An odds comparison tool needs a canonical internal model so equivalent markets can be compared safely.
function normaliseOutcome({
match,
bookmaker,
market,
outcome,
updatedAt
}) {
return {
matchId: match.id,
bookmakerId: bookmaker.id,
marketId: market.id,
selectionId: outcome.id,
line: outcome.line ?? null,
price: Number(outcome.price),
format: outcome.format ?? 'decimal',
status: market.status,
isLive: Boolean(market.is_live),
updatedAt
};
}
Example Bookmaker Comparison
| Bookmaker | Home | Draw | Away | Updated |
|---|---|---|---|---|
| Example Sportsbook A | 1.84 | 3.45 | 4.20 | 10:30:18 |
| Example Sportsbook B | 1.88 | 3.40 | 4.10 | 10:30:16 |
| Example Sportsbook C | 1.82 | 3.55 | 4.25 | 10:30:20 |
The best displayed price should be selected only after confirming that the market, selection, settlement rules and timestamp are equivalent.
Historical Odds and Price Movement
Historical odds can show how a selection changed from its opening price to its latest or closing price.
Suggested Snapshot Record
{
"match_id": "match_74021",
"bookmaker_id": "bookmaker_12",
"market_id": "market_match_winner",
"selection_id": "home",
"price": 1.84,
"price_format": "decimal",
"is_live": false,
"market_status": "open",
"captured_at": "2026-08-06T10:30:18Z"
}
Illustrative Price Movement
| Time | Home Price | Market Stage |
|---|---|---|
| Opening | 2.05 | Pre-match |
| 24 hours before kickoff | 1.95 | Pre-match |
| One hour before kickoff | 1.84 | Pre-match |
| After home goal | 1.40 | Live |
| After equaliser | 2.10 | Live |
Request Soccer Odds in JavaScript
const matchId = 'match_74021';
const response = await fetch(
`/api/soccer/matches/${encodeURIComponent(matchId)}/odds`
);
if (!response.ok) {
throw new Error(`Odds request failed: ${response.status}`);
}
const payload = await response.json();
for (const bookmaker of payload.data.bookmakers) {
for (const market of bookmaker.markets) {
if (market.status !== 'open') {
continue;
}
console.log(bookmaker.name, market.name, market.outcomes);
}
}
Request Soccer Odds in Python
import requests
match_id = "match_74021"
response = requests.get(
(
"https://api.example.com/v1/soccer/"
f"matches/{match_id}/odds"
),
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Accept": "application/json",
},
timeout=15,
)
response.raise_for_status()
odds = response.json()
Request Soccer Odds in PHP
<?php
$matchId = 'match_74021';
$url = sprintf(
'https://api.example.com/v1/soccer/matches/%s/odds',
rawurlencode($matchId)
);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_KEY',
'Accept: application/json',
],
CURLOPT_TIMEOUT => 15,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($body === false) {
throw new RuntimeException(curl_error($ch));
}
curl_close($ch);
if ($status < 200 || $status >= 300) {
throw new RuntimeException(
'Soccer odds API returned HTTP ' . $status
);
}
$data = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
Polling Live Odds
When WebSocket odds streaming is not available, a backend may poll live odds at a controlled interval.
let liveOddsTimer;
function startLiveOddsPolling(matchId) {
stopLiveOddsPolling();
liveOddsTimer = setInterval(async () => {
try {
await loadLiveOdds(matchId);
} catch (error) {
console.error(error);
}
}, 15000);
}
function stopLiveOddsPolling() {
if (liveOddsTimer) {
clearInterval(liveOddsTimer);
liveOddsTimer = undefined;
}
}
Use the confirmed provider rate limits and update guidance rather than copying the example interval directly.
Streaming Live Odds With WebSocket
Illustrative Subscription
const socket = new WebSocket(
'wss://stream.example.com/v1/soccer'
);
socket.addEventListener('open', () => {
socket.send(JSON.stringify({
action: 'authenticate',
token: 'SHORT_LIVED_ACCESS_TOKEN'
}));
socket.send(JSON.stringify({
action: 'subscribe',
channel: 'soccer_odds',
match_ids: ['match_74021']
}));
});
Illustrative Odds Update Event
{
"event_id": "odds_event_77192",
"type": "odds_update",
"match_id": "match_74021",
"bookmaker_id": "bookmaker_12",
"market_id": "market_match_winner",
"selection_id": "home",
"old_price": 1.84,
"new_price": 1.76,
"status": "open",
"is_live": true,
"updated_at": "2026-08-06T19:24:12Z"
}
Handle Duplicate Odds Events
A reconnect may replay events. Store unique event IDs so the same price update is not applied twice.
processed_odds_events
event_id unique
match_id
bookmaker_id
market_id
selection_id
old_price
new_price
processed_at
Cache Soccer Odds Correctly
| Data | Suggested cache approach |
|---|---|
| Bookmakers and market definitions | Longer cache with periodic refresh |
| Upcoming pre-match odds | Moderate cache |
| Live odds | Short cache or event-driven update |
| Suspended markets | Refresh according to provider guidance |
| Settled markets | Long cache after final confirmation |
Show Price Freshness
Every displayed price should have an update timestamp. A stale price should not be presented as current.
function isPriceStale(updatedAt, maximumAgeMs) {
const updatedTime = new Date(updatedAt).getTime();
if (!Number.isFinite(updatedTime)) {
return true;
}
return Date.now() - updatedTime > maximumAgeMs;
}
The allowed age should follow the product requirement and confirmed provider behaviour.
Handle Market Settlement
Settlement data records the final result of a supported betting market.
Illustrative Settlement Response
{
"market_id": "market_match_winner",
"status": "settled",
"settled_at": "2026-08-06T20:00:11Z",
"outcomes": [
{
"selection_id": "home",
"result": "won"
},
{
"selection_id": "draw",
"result": "lost"
},
{
"selection_id": "away",
"result": "lost"
}
]
}
Do not invent settlement rules. Use the provider’s documented market and outcome definitions.
Odds API Security
- Keep permanent API credentials on your backend
- Use HTTPS and WSS in production
- Validate match, bookmaker, market and selection IDs
- Rate-limit public application endpoints
- Do not trust prices submitted by the browser
- Log authentication and subscription failures
- Rotate exposed credentials
- Restrict access to authorised users and applications
Common Sportsbook Integration Pattern
Soccer Odds API
|
v
Backend ingestion service
|
+-- Authentication
+-- Market normalisation
+-- Freshness validation
+-- Duplicate protection
+-- Historical snapshots
|
v
Internal odds store
|
+-- Sportsbook interface
+-- Odds comparison page
+-- Trading dashboard
+-- Analytics pipeline
+-- Affiliate widgets
Common Soccer Odds API Mistakes
Comparing Markets by Name Alone
Use stable market and selection identifiers.
Displaying Suspended Prices as Active
Always check market status before rendering an actionable price.
Ignoring Update Timestamps
Show freshness and avoid presenting stale odds as live.
Mixing Pre-Match and Live Prices
Store and display them as separate market states.
Overwriting Historical Prices
Store timestamped snapshots when your licence permits historical storage.
Assuming Every Bookmaker Uses the Same Rules
Confirm market definitions and settlement terms before comparison.
Exposing the API Key in Frontend Code
Keep permanent private credentials on the server.
Legal and Responsible-Gambling Considerations
Soccer betting products can be subject to licensing, age restrictions, geographic limitations, advertising rules and responsible-gambling requirements.
- Confirm the laws in every target jurisdiction
- Obtain qualified legal advice
- Review provider display and redistribution rights
- Use approved bookmaker attribution
- Apply age and geographic controls where required
- Avoid guaranteed-profit or guaranteed-win claims
- Provide responsible-gambling information where relevant
Soccer Odds API FAQs
What does a Soccer Odds API provide?
Depending on coverage, it can provide pre-match odds, live odds, bookmaker markets, historical prices, market status and settlement results.
What is the difference between pre-match and live odds?
Pre-match odds are available before kickoff. Live odds update while the match is in progress.
Which odds format should I store?
Store the provider’s original format and value. Many systems also normalise prices to decimal for internal calculations.
Can I compare multiple bookmakers?
Yes, when equivalent markets and selections are matched through stable IDs and the commercial terms permit comparison.
How often do live odds update?
Update timing depends on the provider, competition, bookmaker, market and delivery method. Use documented timestamps and service guidance.
Can I store historical soccer odds?
Only when the provider’s licence and selected plan permit storage and redistribution.
What happens when a market is suspended?
Treat the price as temporarily unavailable and do not present it as an active selection.
Do soccer odds guarantee an outcome?
No. Odds represent market prices and implied assessments, not guaranteed results.
Integrate Soccer Odds Into Your Product
Start with stable match, bookmaker, market and selection IDs. Preserve timestamps, handle suspended markets correctly and use secure server-side API access.
Build Cricket Products With Reliable API Data
Access live scores, fixtures, ball-by-ball updates, statistics, odds, predictions and historical cricket data through one developer-friendly API.
Get API Access