# Sports Betting Odds API — Pinnacle, DraftKings & Arbitrage (`lergassy/sports-odds-api`) Actor

Moneyline, spread and total odds per book — Pinnacle sharp lines with the risk limit it accepts, DraftKings, Kalshi — plus arbitrage and value bets calculated across books, opening lines, props and futures. NFL, NBA, MLB, NHL, college, soccer, UFC, tennis. No API key.

- **URL**: https://apify.com/lergassy/sports-odds-api.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Sports, Agents, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 odds rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

**Sports Betting Odds API** returns betting odds as clean rows instead of a sportsbook page: the moneyline, spread and total for every game, **per book — including Pinnacle, the sharp line the rest of the market prices against, with the risk limit it will accept on each market** — with the **opening line, the current line and how far it has moved**; **arbitrage and value bets worked out across the books for you**; **player and game props**; **futures** such as the Super Bowl or Premier League winner; and the **traded win probability from Kalshi**, the regulated prediction market, for the same games. It covers 28 leagues — NFL, college football, NBA, WNBA, college basketball, MLB, NHL, the Premier League, LaLiga, Bundesliga, Serie A, Ligue 1, Champions League, Europa League, MLS, Liga MX, ATP and WTA tennis, UFC, Formula 1 and more — with prices in American, decimal, fractional or implied-probability format, plus the vig-free "fair" probability of every outcome. No API key, no proxy, no browser: a week of NFL and Premier League odds is about ten seconds.

![Sports betting odds API output: moneyline and spread per book with Pinnacle, DraftKings and Kalshi side by side](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/sports-odds-api/sports-odds-api-output-table.png)

Choose the leagues and a date range, pick the markets and sources, and click Start. Export as JSON, CSV or Excel, run it on a schedule to build a line-movement history, or call it from the API and AI agents.

### What is Sports Betting Odds API?

It is an **odds API** for people who need prices as data: odds-comparison sites and Telegram or Discord bots, fantasy and betting-model builders, dashboards and newsletters, researchers studying market efficiency, and AI agents that get asked "what's the line on the Chiefs game" or "who is favoured tonight and by how much". The licensed odds feeds charge hundreds of dollars a month and cap requests; the free tiers of odds APIs run out after a few hundred calls. This Actor reads the same public feeds the sportsbook and ESPN pages use and charges a fraction of a cent per row.

Five things set it apart from a plain odds scraper:

- **The sharp line, with limits.** Pinnacle is the book professional bettors price against, and this Actor carries it next to DraftKings. Every Pinnacle row also carries `limitUsd` — how much the book will actually accept on that market. No other odds feed on Apify publishes it, and it is the most honest confidence signal in betting data: a book willing to take $10,000 on a spread and $3,000 on the total is telling you which number it trusts.
- **Arbitrage and value, already calculated.** With two books on the same market the Actor emits `edge` rows: **arbitrage** — the best price on each side, taken from whichever book offers it, when together they guarantee a profit, with the stake split for each leg; and **value** — any price paying more than Pinnacle's vig-free probability says the outcome deserves, with the exact edge in percent. This is the job most buyers were writing themselves on top of an odds feed.
- **Opening lines and movement.** Every DraftKings row carries the opening line and price next to the current one, plus `lineMovement`, `homePriceMovement` and `awayPriceMovement`. You can see that a spread opened at −3.5 and is now −2.5 without keeping your own history.
- **Sportsbook and prediction market side by side.** Kalshi's game contracts are matched to the same games, so a row shows what the sportsbook charges and what traders actually pay for each side, with volume and open interest — and the value calculation runs across both, so a contract trading below the sharp line shows up as an edge like any other price.
- **Probabilities, not just prices.** Every row includes decimal odds, the implied probability and the fair probability with the bookmaker's margin (`overround`) removed — the number a model wants.

### What data does it return?

#### Odds mode — game lines

One row per game × market × book (or one nested row per game, see below).

| Field | Example |
|---|---|
| `league`, `leagueName`, `sport`, `week` | nfl · National Football League · football · 1 |
| `eventId`, `dkEventId`, `game`, `startTime`, `status`, `statusDetail` | 401872656 · 34118042 · New England Patriots at Seattle Seahawks · 2026-09-10T00:20Z · scheduled · Wed, September 9th at 8:20 PM EDT |
| `homeTeam`, `homeTeamId`, `awayTeam`, `awayTeamId`, `homeScore`, `awayScore`, `venue` | Seattle Seahawks · 26 · New England Patriots · 17 · 0 · 0 · Lumen Field |
| `book`, `bookType`, `source`, `sourceUrl` | DraftKings · sportsbook · draftkings · https://sportsbook.draftkings.com/event/34118042 |
| `limitUsd`, `pinnacleMatchupId` — Pinnacle rows only | 10000 · 1630877993 |
| `market`, `line` | spread · −3.5 (total: 44.5; moneyline: null) |
| `homePrice`, `awayPrice`, `drawPrice`, `overPrice`, `underPrice` | −105 · −115 · null · … in the format you chose |
| `homeDecimal`, `awayDecimal`, `overDecimal`, `underDecimal` | 1.952 · 1.87 |
| `homeImpliedProbability`, `awayImpliedProbability`, `overImpliedProbability`, `underImpliedProbability` | 0.5122 · 0.5349 |
| `homeFairProbability`, `awayFairProbability`, `overround` | 0.4892 · 0.5108 · 0.0471 |
| `favorite` | home · away · pick |
| `openLine`, `openHomePrice`, `openAwayPrice`, `openOverPrice`, `openUnderPrice` | −3.5 · −111 · −111 |
| `lineMovement`, `homePriceMovement`, `awayPriceMovement` | 0 · 0.052 · −0.03 (in decimal-odds points) |
| Kalshi rows: `homeLastTradeProbability`, `awayLastTradeProbability`, `homeBid`, `homeAsk`, `awayBid`, `awayAsk`, `volumeUsd`, `openInterest`, `kalshiEventTicker` | 0.63 · 0.39 · 0.62 · 0.63 · 0.38 · 0.39 · 912,726 · 560,237 · KXNFLGAME-26SEP09NESEA |
| `oddsFormat`, `scrapedAt` | american · 2026-09-06T09:33:06Z |

Soccer moneylines carry `drawPrice`. Spread is the run line in MLB and the puck line in NHL. Switch on **Alternate spreads and totals** for every alternate line DraftKings offers, as `alternate-spread` and `alternate-total` rows.

**Nested layout** (`outputFormat: "nested"`): one row per game with `markets.moneyline.books[]`, `markets.spread.books[]`, `markets.total.books[]`, the `best` price per outcome across books, `favorite`, the sportsbook's fair `homeWinProbability`/`awayWinProbability` and Kalshi's `marketHomeWinProbability`/`marketAwayWinProbability`.

#### Edge rows — arbitrage and value

Emitted alongside the prices when two or more sources cover the same market, unless you switch **Find arbitrage and value bets** off. `kind` says which of the two a row is.

| Field | Arbitrage | Value |
|---|---|---|
| `kind` | arbitrage | value |
| `market`, `line` | moneyline · null | total · 49.5 |
| `profitPercent` | 1.84 — guaranteed return backing every outcome at its best price | — |
| `legs` | `[{side: home, book: Pinnacle, decimal: 2.16, stakePercent: 45.4}, …]` | — |
| `side`, `book`, `decimal`, `impliedProbability` | — | away · DraftKings · 4.60 · 0.2174 |
| `fairProbability`, `sharpBook`, `edgePercent` | — | 0.2302 · Pinnacle · 5.892 |
| `booksCount` | 3 | 3 |

A worked example from a real run: Pinnacle priced the Jacksonville away side at +319, which after removing the book's 3.66% margin is a true 23.02% chance. DraftKings paid +360 on the same side — 4.60 in decimal. Multiply: 0.2302 × 4.60 = 1.0589, so that bet pays 5.892% more than the sharp line says it is worth. That is the `edgePercent` on the row.

Arbitrage is genuinely rare, so an empty `arbitrage` list is the normal answer, not a fault.

#### Props mode

One row per selection: `category` (Passing Props, TD Scorers, Batter Props, Player Points…), `market` (Drake Maye Passing Yards O/U), `marketType`, `player`, `playerId`, `team`, `playerStat` (DraftKings' season average shown next to the line), `selection` (Over / Under / 150+ / Anytime), `outcomeType`, `line`, `price`, `decimal`, `american`, `impliedProbability`, `sourceUrl`.

#### Futures mode

One row per selection: `category` (Futures, Awards, Wins, Playoffs, Division Specials…), `event` (NFL 2026/27 Season), `market` (Winner, MVP, Regular Season Wins), `selection` (LA Rams, Josh Allen, Over 10.5), `line`, `price`, `decimal`, `impliedProbability`.

#### Prediction-markets mode

One row per Kalshi contract: `series`, `eventTicker`, `event`, `marketTicker`, `outcome` (Seattle), `probability` (last trade, 0–1), `yesBid`, `yesAsk`, `noBid`, `noAsk`, `previousProbability`, `decimal` and `price` (the equivalent odds), `volume`, `openInterest`, `openTime`, `closeTime`, `result`, `url`. Any Kalshi series works, not only the ones mapped to leagues: pass `KXUCLGAME`, `KXATPMATCH`, `KXF1RACE`…

#### Leagues mode

Every league DraftKings prices right now, with `id`, `name` and `sport` — useful to see what is in season.

### How much does it cost?

Pricing is **pay per row**, nothing else: platform usage is close to zero because there is no browser and no proxy, and error rows are free.

| Row | Price |
|---|---|
| Odds row (game × market × book) | $0.003 — 1,000 rows for $3 |
| Edge row — arbitrage or value | $0.003, billed as an odds row |
| Nested game row (all books and markets inside) | $0.008 |
| Prop selection | $0.0015 |
| Futures selection | $0.0015 |
| Prediction-market contract | $0.0015 |

A full NFL week — 16 games × 3 markets × DraftKings, Pinnacle and Kalshi, plus the edges between them — is about 120 rows, or $0.36. The whole NFL prop board for one game is roughly 1,500 rows. Larger monthly plans get 10–30 % off.

### How to get sports betting odds

1. Choose **🏆 Leagues** — one or several.
2. Set **📅 Days ahead** (default: the coming week) or exact **From** / **To** dates.
3. Keep **What to get** on *Odds* for game lines, or switch to *Props*, *Futures*, *Prediction markets* or *Leagues*.
4. Leave at least two **📚 Sources** on — Pinnacle and DraftKings by default — so the arbitrage and value rows have something to compare.
5. Pick **Markets** and **Sources**, the **Odds format** and the **Row layout**. Leave **Opening lines and movement** on unless you want the fastest possible run.
6. Click **Start** and export, or read the dataset through the API.

### ⬇️ Input

![Sports betting odds API input: leagues, markets, sources, odds format and the arbitrage switch](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/sports-odds-api/sports-odds-api-input-form.png)

```json
{
  "mode": "odds",
  "leagues": ["nfl", "epl"],
  "daysAhead": 7,
  "markets": ["moneyline", "spread", "total"],
  "books": ["draftkings", "espn", "kalshi"],
  "oddsFormat": "american",
  "outputFormat": "flat",
  "includeOpeningLines": true
}
```

#### One game per row with the best price

```json
{ "mode": "odds", "leagues": ["nba"], "daysAhead": 1, "outputFormat": "nested", "oddsFormat": "decimal" }
```

#### Passing props for this week's NFL games

```json
{ "mode": "props", "leagues": ["nfl"], "daysAhead": 6, "propCategories": ["Passing", "Receiving"], "maxPropsPerGame": 400 }
```

#### Super Bowl and division winners

```json
{ "mode": "futures", "leagues": ["nfl"], "futuresCategories": ["Futures", "Division"] }
```

#### Kalshi contracts for Champions League games

```json
{ "mode": "prediction-markets", "kalshiSeries": ["KXUCLGAME"] }
```

#### Every alternate line for the Sunday slate

```json
{ "mode": "odds", "leagues": ["nfl"], "dateFrom": "2026-09-13", "dateTo": "2026-09-13", "books": ["draftkings"], "includeAlternateLines": true }
```

### ⬆️ Output

```json
{
  "type": "odds",
  "sport": "football",
  "league": "nfl",
  "leagueName": "National Football League",
  "eventId": "401872656",
  "dkEventId": "34118042",
  "game": "New England Patriots at Seattle Seahawks",
  "startTime": "2026-09-10T00:20Z",
  "status": "scheduled",
  "homeTeam": "Seattle Seahawks",
  "awayTeam": "New England Patriots",
  "week": 1,
  "book": "DraftKings",
  "bookType": "sportsbook",
  "market": "spread",
  "line": -3.5,
  "homePrice": -105,
  "awayPrice": -115,
  "homeDecimal": 1.952,
  "awayDecimal": 1.87,
  "homeImpliedProbability": 0.5122,
  "awayImpliedProbability": 0.5349,
  "homeFairProbability": 0.4892,
  "awayFairProbability": 0.5108,
  "overround": 0.0471,
  "favorite": "home",
  "openLine": -3.5,
  "openHomePrice": -111,
  "openAwayPrice": -111,
  "homePriceMovement": 0.052,
  "awayPriceMovement": -0.03,
  "lineMovement": 0,
  "source": "draftkings",
  "sourceUrl": "https://sportsbook.draftkings.com/event/34118042",
  "oddsFormat": "american",
  "scrapedAt": "2026-09-06T09:33:06.078Z"
}
```

The same game's Kalshi row has `book: "Kalshi"`, `bookType: "prediction-market"`, the odds implied by the ask price, and `homeLastTradeProbability: 0.63`, `volumeUsd: 912726`. A source that cannot be read arrives as a `type: "error"` row with the URL and the reason, never as a silently missing game.

### Use cases

#### Finding arbitrage and value

The reason the Actor carries more than one book. Turn on **Find arbitrage and value bets**, set the smallest edge you care about, and the run returns `edge` rows on top of the prices: guaranteed-profit combinations with the stake split per leg, and prices that beat Pinnacle's vig-free line with the exact edge in percent. Nothing to compute on your side.

#### Line shopping

`best` inside a nested game row names the book paying most on each outcome, so a bettor placing a single wager knows where to place it. In flat output the same answer is one sort on `homeDecimal` within a market.

#### Odds comparison and alerts

Run every 15 minutes, keep the rows, and alert when `lineMovement` crosses a threshold or when the sportsbook's fair probability and Kalshi's traded probability disagree by more than a few points.

#### Betting models and fantasy tools

Feed `homeFairProbability`, the total and the props into a model; the vig is already removed. Props rows include DraftKings' displayed season average for the player, so you can compare the line with the number the book is anchoring on.

#### Content, dashboards and newsletters

"Lines for Sunday" tables, favourites of the day, biggest movers since open — straight from the flat rows into Google Sheets, Notion or a chart.

#### Research

Collect closing lines and opening lines for a season, or the sportsbook-versus-prediction-market spread, without paying for a licensed feed.

#### AI agents

An agent that answers "what's the spread on Cowboys–Eagles" or "which underdog has the most support on Kalshi" gets one small, typed row per fact.

### Integrations and sports odds API

Run it from the [Apify API](https://docs.apify.com/api/v2), the JavaScript and Python clients, a schedule, or a webhook, and push results to Google Sheets, Slack, Discord or a database through **n8n**, **Make** or **Zapier**. The [Apify MCP server](https://mcp.apify.com) exposes it to Claude, ChatGPT and other agents as a tool.

One call returns the rows, ready for a script:

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("lergassy/sports-odds-api").call(run_input={
    "mode": "odds", "leagues": ["nfl"], "books": ["pinnacle", "draftkings"],
    "includeEdges": True, "minEdgePercent": 2,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row.get("type") == "edge":
        print(row["game"], row["side"], row["book"], row["edgePercent"], "%")
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('lergassy/sports-odds-api').call({ leagues: ['epl'], outputFormat: 'nested' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].markets.moneyline.best);
```

### 🤖 For AI Agents & LLM Apps

Compact reference for agents calling this Actor through the Apify MCP server or the Apify API (`lergassy/sports-odds-api`).

**Purpose:** betting odds for a game or a slate — moneyline, spread, total per book, opening line and movement, implied and fair probabilities, Kalshi win probability — plus player props, futures and raw prediction-market contracts, for 28 leagues across American football, basketball, baseball, hockey, soccer, tennis, MMA and motorsport. Use it for "what's the line", "who is favoured", "has the spread moved", "what are the passing props", "odds to win the Super Bowl".

**Minimal input:**

```json
{ "mode": "odds", "leagues": ["nfl"], "daysAhead": 7 }
```

**Output:** one flat row per game × market × book — `league`, `game`, `startTime`, `status`, `homeTeam`, `awayTeam`, `book`, `bookType`, `market` (moneyline | spread | total | alternate-spread | alternate-total), `line`, `homePrice`, `awayPrice`, `drawPrice`, `overPrice`, `underPrice` (in `oddsFormat`), `homeDecimal`…, `homeImpliedProbability`…, `homeFairProbability`…, `overround`, `favorite`, `openLine`, `openHomePrice`, `openAwayPrice`, `lineMovement`, `homePriceMovement`, `sourceUrl`. Kalshi rows add `homeLastTradeProbability`, `volumeUsd`, `openInterest`. Props rows: `category`, `market`, `player`, `selection`, `line`, `price`, `impliedProbability`. Futures rows: `category`, `market`, `selection`, `price`. Prediction-market rows: `event`, `outcome`, `probability`, `yesBid`, `yesAsk`, `volume`.

**Behaviors an agent should know:**

- Dates are UTC; `daysAhead` counts from today. Default is the coming 7 days. Finished games are dropped unless `includeFinished` is true.
- `oddsFormat` changes only the `*Price` fields. `*Decimal` and `*ImpliedProbability` are always present, so compare books on decimals.
- `line` is from the home team's perspective for spreads (−3.5 means the home side is favoured by 3.5) and the total for over/under rows; it is null for moneylines.
- `favorite` on a moneyline row is the side with the shorter price; on a spread row it follows the sign of `line`.
- Movement fields compare DraftKings' current line and price with its opening ones; they are null when the opening line is unknown (Kalshi, books without an ESPN entry, or `includeOpeningLines: false`).
- Kalshi prices are the ask (what you would pay); `*LastTradeProbability` is the last trade. Kalshi lists most NFL, NBA, MLB, NHL, top-league soccer, tennis and UFC games, not every college game.
- Sportsbook coverage is DraftKings first-hand plus whatever providers ESPN carries for the game. Leagues DraftKings does not price (tennis, golf) return Kalshi and ESPN rows only.
- Props and futures come from DraftKings and need the league to be on its board; off-season leagues return nothing. `propCategories` filters by category name substring; `maxPropsPerGame` caps rows per game.
- `eventId` values come from this Actor's own rows (or the [Sports Scores & Schedules API](https://apify.com/lergassy/sports-scores-api)); do not invent them.
- No proxy is used and none is needed; a source that fails returns an `error` row.

### ❓ FAQ

#### What is arbitrage and how does the Actor find it?

Arbitrage is when the best price on each side of the same market, taken from whichever book offers it, together pay more than they cost. Add the implied probabilities of the best prices: if they sum to less than 1, backing every outcome in the right proportion returns a profit whatever happens. The Actor does that sum on every market it prices at two or more books and emits an `edge` row with `kind: "arbitrage"`, the profit in percent, and the stake share for each leg. It is genuinely rare, so an empty result is the normal one.

#### What is a value bet and why measure it against Pinnacle?

Every book's prices add up to more than 100% — the margin. Strip the margin proportionally and you get the book's own opinion of the true probability. Pinnacle runs the tightest margin in the market and moves its line on sharp money rather than on public sentiment, which is why it is the reference the industry prices against. When another book pays more than Pinnacle's vig-free probability says an outcome deserves, that difference is the value, and the Actor reports it as `edgePercent`.

Worked from a real run: Pinnacle had the Jacksonville away side at +319 with a 3.66% margin, so the vig-free probability is 23.02%. DraftKings paid +360 — 4.60 decimal. 0.2302 × 4.60 = 1.0589, so that price pays 5.892% more than the sharp line says it is worth.

#### What is the risk limit and why does it matter?

`limitUsd` on a Pinnacle row is how much the book will actually accept on that market. It is the most honest confidence signal in betting data: a book willing to take $10,000 on a spread and $3,000 on the total is telling you which of its own numbers it trusts. No other odds feed on Apify publishes it.

#### Which books are included?

DraftKings directly, plus every provider ESPN shows for a game (DraftKings and, for some soccer games, Bet365) with its opening line, plus Kalshi. More sportsbooks are added as their public feeds prove stable; ask in the Issues tab for one you need.

#### Are the odds live during the game?

Yes when the source updates them: DraftKings' feed carries in-play lines for games that have started, and Kalshi contracts trade until the game ends. Run the Actor again to refresh.

#### How do I get line-movement history?

Every run already shows open versus current. For a full history, schedule the Actor every 15–60 minutes and keep the datasets; each row carries `scrapedAt`.

#### Is this legal?

The Actor reads public, unauthenticated endpoints that the sportsbook, ESPN and Kalshi web pages call themselves and returns factual prices. It places no bets, needs no account and stores no personal data. Whether you may use odds data commercially depends on your jurisdiction and purpose; this is not legal advice.

#### Why is a game missing from DraftKings rows?

DraftKings publishes lines for the next few days only (MLB: the current day). Games further out have Kalshi rows if a contract exists, and ESPN rows once ESPN carries a line.

#### Can I use it with the Apify API or an MCP server?

Yes. The Actor is pay-per-event with limited permissions, so agents can run it through the Apify MCP server without extra setup.

### Your feedback

Found a league or a market you need, or a row that looks wrong? Open an issue in the **Issues** tab and it will be looked at within a day.

### You might also like

- [Sports Scores & Schedules API](https://apify.com/lergassy/sports-scores-api) — scores, schedules, standings, rosters and box scores for the same leagues.
- [Tennis Scores & Stats API](https://apify.com/lergassy/tennis-scores-api) — every ATP, WTA, Challenger and ITF match with statistics, head-to-head and rankings.
- [Prediction Markets API](https://apify.com/lergassy/prediction-markets-api) — Polymarket and Kalshi markets beyond sports.

# Actor input Schema

## `mode` (type: `string`):

<b>Odds</b> — moneyline, spread and total for every game, per book, with opening lines and movement. <b>Props</b> — player and game props from DraftKings for every game. <b>Futures</b> — championship, division, award and season-win markets. <b>Prediction markets</b> — Kalshi game contracts with traded probabilities. <b>Leagues</b> — every league DraftKings currently prices, with ids.

## `leagues` (type: `array`):

One or more leagues. Odds, props and Kalshi contracts are matched game by game. You can also type any ESPN league path such as <code>soccer/eng.2</code> for the game list (DraftKings and Kalshi prices then depend on whether they carry that league).

## `daysAhead` (type: `integer`):

Games from today up to this many days ahead (ignored when dates are set below). 0 = today only.

## `dateFrom` (type: `string`):

<code>YYYY-MM-DD</code>, UTC. Optional.

## `dateTo` (type: `string`):

<code>YYYY-MM-DD</code>, UTC. Optional; at most 60 days after the start.

## `markets` (type: `array`):

Odds mode: which game lines to output. Spread is the run line in MLB and the puck line in NHL; soccer moneylines carry a draw price.

## `books` (type: `array`):

<b>Pinnacle</b> — the sharp reference book the rest of the market prices against, with the risk limit it will accept on each market. <b>DraftKings</b> — live prices straight from the sportsbook feed. <b>ESPN</b> — every provider ESPN carries for the game (DraftKings, Bet365 where present) with opening lines. <b>Kalshi</b> — regulated prediction market: the traded probability of each side winning, volume and open interest. Two or more sources unlock the arbitrage and value rows below.

## `oddsFormat` (type: `string`):

How the <code>homePrice</code>/<code>awayPrice</code>/<code>overPrice</code>… fields are written. Decimal odds and implied probabilities are always included as separate fields.

## `outputFormat` (type: `string`):

<b>Flat</b> — one row per game × market × book, spreadsheet-friendly. <b>Nested</b> — one row per game with all books inside and the best price per outcome.

## `includeOpeningLines` (type: `boolean`):

Fetch the opening line and price for each game (one extra request per game) and compute how far the line and prices have moved.

## `includeAlternateLines` (type: `boolean`):

Add DraftKings' alternate lines as extra rows (market <code>alternate-spread</code> / <code>alternate-total</code>).

## `includeFinished` (type: `boolean`):

Odds mode: keep games that are already final (closing lines, if a source still carries them). Prediction-markets mode: keep settled contracts.

## `includeEdges` (type: `boolean`):

Adds <b>edge</b> rows on top of the prices: <b>arbitrage</b> — the best price on each side, taken from whichever book offers it, when together they guarantee a profit; <b>value</b> — a book paying more than Pinnacle’s vig-free probability says the outcome deserves. Needs at least two sources.

## `minEdgePercent` (type: `integer`):

Prices move by a tick constantly, so anything under half a percent is noise a bettor would pay away in the spread. Raise it to see only the big disagreements.

## `eventIds` (type: `array`):

ESPN event ids (the <code>eventId</code> field of any row, or the number in an ESPN game URL). Leave empty for every game in the date range.

## `propCategories` (type: `array`):

Props mode: keep only categories whose name contains one of these, e.g. <code>Passing</code>, <code>TD Scorers</code>, <code>Points</code>, <code>Batter</code>. Empty = every player and game prop category (this can be thousands of rows per game).

## `maxPropsPerGame` (type: `integer`):

Stop after this many prop rows for one game.

## `futuresCategories` (type: `array`):

Futures mode: keep only categories whose name contains one of these, e.g. <code>Futures</code>, <code>Awards</code>, <code>Wins</code>, <code>Playoffs</code>. Empty = every futures-type category.

## `kalshiSeries` (type: `array`):

Prediction-markets mode: series tickers to pull directly, e.g. <code>KXNFLGAME</code>, <code>KXUCLGAME</code>, <code>KXATPMATCH</code>. Leagues selected above are added automatically.

## `maxItems` (type: `integer`):

Stop after this many rows in the run.

## `concurrency` (type: `integer`):

How many requests run at once.

## `proxyConfiguration` (type: `object`):

Not needed: every source answers Apify's own servers directly. Set only if a source starts refusing.

## Actor input object example

```json
{
  "mode": "odds",
  "leagues": [
    "nfl",
    "nba",
    "mlb",
    "epl"
  ],
  "daysAhead": 7,
  "markets": [
    "moneyline",
    "spread",
    "total"
  ],
  "books": [
    "draftkings",
    "pinnacle",
    "espn",
    "kalshi"
  ],
  "oddsFormat": "american",
  "outputFormat": "flat",
  "includeOpeningLines": true,
  "includeAlternateLines": false,
  "includeFinished": false,
  "includeEdges": true,
  "minEdgePercent": 1,
  "maxPropsPerGame": 500,
  "maxItems": 5000,
  "concurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `rows` (type: `string`):

Odds mode: one row per game × market × book with prices in the chosen format, decimal odds, implied and fair probabilities, opening line and movement (or one nested row per game with best prices). Props/futures: one row per selection. Prediction markets: one row per Kalshi contract.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "leagues": [
        "nfl",
        "nba",
        "mlb",
        "epl"
    ],
    "books": [
        "draftkings",
        "pinnacle",
        "espn",
        "kalshi"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/sports-odds-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "leagues": [
        "nfl",
        "nba",
        "mlb",
        "epl",
    ],
    "books": [
        "draftkings",
        "pinnacle",
        "espn",
        "kalshi",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("lergassy/sports-odds-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "leagues": [
    "nfl",
    "nba",
    "mlb",
    "epl"
  ],
  "books": [
    "draftkings",
    "pinnacle",
    "espn",
    "kalshi"
  ]
}' |
apify call lergassy/sports-odds-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lergassy/sports-odds-api"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/7TU8FpT0XXh3lg4hw/builds/vuxqWILJyqGvI8v6n/openapi.json
