API
DailyAmbush Public API — Soccer Odds
Read-only, API-key-authenticated. Two endpoints: a quick per-match summary and a granular multi-book, multi-market feed. This page is public and safe to share with an AI tool — it contains no credentials.
Need a key? Log in and visit My Account → API Access to generate one.
Quick start
Send your key as a Bearer token on every request:
curl -H "Authorization: Bearer da_live_your_key_here" \ "https://dailyambush.com/api/public/v1/soccer/odds?date=2026-08-16&days=3"
Endpoint 1 — /soccer/odds (per-match summary)
One row per match: moneyline, spread, total, and BTTS, whichever are available.
| Method | GET |
|---|---|
| URL | https://dailyambush.com/api/public/v1/soccer/odds |
| Auth | Authorization: Bearer <api_key> header |
| Rate limit | 60 requests / minute (some accounts are unlimited by arrangement) |
Query parameters
| Param | Default | Notes |
|---|---|---|
date | today | YYYY-MM-DD, start of the date range |
days | 3 | Range length from date, max 30 |
league_id | — | Filter to one league |
page | 1 | Pagination |
per_page | 100 | Max 200 |
Example response
{
"data": [
{
"match_id": 123456,
"match_date": "2026-08-16",
"match_time": "20:00:00",
"status": "scheduled",
"league_id": 47,
"league_name": "Premier League",
"league_country": "England",
"home_team": "Arsenal",
"away_team": "Chelsea",
"home_score": null,
"away_score": null,
"ml_h": -120, "ml_d": 260, "ml_a": 340,
"spread_h": -0.25, "spread_h_odds": -120, "spread_a_odds": 100,
"total_over": 2.5, "total_over_odds": 115, "total_under_odds": -160,
"btts_yes": -115, "btts_no": -110,
"last_odds_update": "2026-08-16 11:26:04"
}
],
"meta": {
"date_from": "2026-08-16", "date_to": "2026-08-19",
"league_id": null, "page": 1, "per_page": 100, "total": 42
},
"error": null
}
Coverage (as of 2026-08-16):
ml_h / ml_d / ml_a (moneyline)
and spread_* / total_* are populated on most upcoming matches. btts_* is
populated on a minority of matches so far — treat it as sparse, not guaranteed. Coverage is actively expanding on
the ingestion side; always check for null rather than assuming a field is present, and use
last_odds_update to judge freshness.
Field notes
- Odds are American format (e.g.
-120,340). ml_h/ml_d/ml_a— moneyline home / draw / away.spread_his the home spread line;spread_h_odds/spread_a_oddsare the juice on each side.total_overis the total line;total_over_odds/total_under_oddsare the juice on each side.btts_yes/btts_no— both-teams-to-score market. Populated on a minority of matches so far.- Null odds fields mean that market wasn't available as of
last_odds_update— not an error. match_timeis Eastern time.- A small number of fixtures may show an unexpected
league_name(e.g. mislabeled under a catch-all competition) while the upstream matching corrects itself over time — not an API bug, the fixture data itself is still accurate.
Endpoint 2 — /soccer/markets (granular, multi-book)
One row per (match, market, bookmaker, outcome) — correct score, alternate spreads/totals, halftime/fulltime,
corners, double chance, and more. Much denser than /soccer/odds: roughly 90 rows per match, so scope
requests with match_id and/or market rather than pulling everything at once.
| Method | GET |
|---|---|
| URL | https://dailyambush.com/api/public/v1/soccer/markets |
| Auth | Authorization: Bearer <api_key> header |
| Rate limit | 60 requests / minute (some accounts are unlimited by arrangement) |
Query parameters
| Param | Default | Notes |
|---|---|---|
date | today | YYYY-MM-DD, start of the date range |
days | 3 | Range length from date, max 30 |
league_id | — | Filter to one league |
match_id | — | Filter to one match (get this from /soccer/odds first) |
market | — | Filter to one market key — see the list below |
page | 1 | Pagination |
per_page | 200 | Max 200 |
Market keys (GET /soccer/markets/types returns this list live)
| Key | What it is |
|---|---|
correct_score | Exact final score |
alternate_spreads | Spread at lines other than the primary one |
alternate_totals | Total goals at lines other than the primary one |
alternate_totals_corners | Total corners, alternate lines |
corners_1x2 | 3-way corner count (most/fewest/tie) |
halftime_fulltime | Combined HT/FT result |
h2h_h1 | Moneyline, first half only |
spreads_h1 | Spread, first half only |
totals_h1 | Total, first half only |
btts | Both teams to score |
btts_h1 | Both teams to score, first half only |
double_chance | Two-outcome combined bet (e.g. home-or-draw) |
draw_no_bet | Moneyline with the draw refunded |
team_totals | Individual team's goal total |
Example response
{
"data": [
{
"match_id": 718,
"match_date": "2026-08-21",
"match_time": "15:00:00",
"league_id": 4,
"league_name": "English Premier League",
"home_team": "Arsenal",
"away_team": "Coventry City",
"market": "alternate_spreads",
"bookmaker": "DraftKings",
"outcome": "Arsenal",
"description": null,
"line": -1.75,
"price": -155,
"scraped_at": "2026-08-16 11:25:27"
}
],
"meta": {
"date_from": "2026-08-16", "date_to": "2026-08-19",
"league_id": null, "match_id": null, "market": null,
"page": 1, "per_page": 200, "total": 1287
},
"error": null
}
Field notes
outcomeis the selection this row prices — a team name, "Over"/"Under", "Yes"/"No", etc., depending onmarket. Forcorrect_scorespecifically, it's a compound string like"Espanyol:2|Levante:0"(home:score|away:score) rather than a plain label — parse on:and|.lineis the number attached to the bet (spread, total, corner count); null for markets with no line (e.g.btts).priceis the American odds for that outcome.- Coverage window is rolling — only fixtures inside the current scrape horizon (roughly the next 48h, wider on weekends) have rows here at all. Older/farther-out matches will simply return zero rows until they enter that window.
- Row volume per match varies enormously by market —
correct_scorealone can be ~47 rows,bttsas few as 2.
Errors
| Status | Meaning |
|---|---|
400 | Unrecognized market value (markets endpoint only) |
401 | Missing, malformed, or invalid/revoked API key |
429 | Rate limit exceeded |
This is a stable, versioned contract (/v1/) — breaking changes will ship as /v2/, not silently.