Odds from 35 books. One shape, one API.

Moneylines, spreads and totals from every sportsbook, exchange and prediction market we carry, plus player props from some of those sportsbooks, in one JSON response.

GET/v1/sports/americanfootball_nfl/odds?markets=h2h,spreads
curl "https://oddslink.app/v1/sports/americanfootball_nfl/odds?markets=h2h,spreads" \
  -H "X-API-Key: ok_live_..."
200 OKresponse.json
[
  {
    "id": "nfl:falcons-panthers:2026-09-20",
    "sport_key": "americanfootball_nfl",
    "sport_title": "NFL",
    "commence_time": "2026-09-20T17:00:00Z",
    "home_team": "Atlanta Falcons",
    "away_team": "Carolina Panthers",
    "bookmakers": [
      {
        "key": "betmgm",
        "title": "BetMGM",
        "last_update": "2026-09-18T18:08:20Z",
        "markets": [
          {
            "key": "h2h",
            "last_update": "2026-09-18T18:08:20Z",
            "outcomes": [
              {
                "name": "Atlanta Falcons",
                "price": 124
              },
              {
                "name": "Carolina Panthers",
                "price": -148
              }
            ]
          },
          {
            "key": "spreads",
            "last_update": "2026-09-18T18:08:14Z",
            "outcomes": [
              {
                "name": "Atlanta Falcons",
                "price": 100,
                "point": 2.5
              },
              {
                "name": "Carolina Panthers",
                "price": -120,
                "point": -2.5
              }
            ]
          }
        ]
      },
      {
        "key": "fanduel",
        "title": "FanDuel",
        "last_update": null,
        "markets": [
          {
            "key": "h2h",
            "last_update": null,
            "outcomes": [
              {
                "name": "Atlanta Falcons",
                "price": 120
              },
              {
                "name": "Carolina Panthers",
                "price": -142
              }
            ]
          },
          {
            "key": "spreads",
            "last_update": null,
            "outcomes": [
              {
                "name": "Atlanta Falcons",
                "price": -102,
                "point": 2.5,
                "size": {
                  "kind": "posted_limit",
                  "amount": 5000
                }
              },
              {
                "name": "Carolina Panthers",
                "price": -118,
                "point": -2.5,
                "size": {
                  "kind": "posted_limit",
                  "amount": 5000
                }
              }
            ]
          }
        ]
      }
    ],
    "unmatched_bookmakers": [
      "betano"
    ]
  }
]

How it works

Flat monthly plans

A free plan, then flat plans from $9.99 to $99.99 a month. Each one is a set number of requests; the price never moves with what you use.

  1. $0Free1,000 requests a month
  2. $9.99Starter20,000 requests a month
  3. $24.99Growth100,000 requests a month
  4. $49.99Scale500,000 requests a month
  5. $99.99Business5,000,000 requests a month

Every book, every plan

The free plan sees the same 35 books as the top plan. What grows is how much you can ask for, not what you're allowed to see.

Plain, nested JSON

Fixture, then books, then markets, then outcomes: each outcome a price, and a point where the market has one. American or decimal odds, chosen per call.

Freshness where we measure it

A price that falls behind its book's measured update rhythm is removed, not left on the board. Not every book is measured yet; /v1/bookmakers says which.

Timestamped, never guessed

Every price carries last_update: when its book last confirmed it, or null where we don't measure that yet. Never an estimate.

Only odds count as requests

Listing sports, books, markets and upcoming fixtures is free. One odds call is one request, whatever comes back. Refused when spent, never a surprise bill.

35 books, one response shape

Sportsbooks, exchanges and prediction markets, all priced through the same fields.

  • DraftKings, Sportsbook
  • FanDuel, Sportsbook
  • Caesars, Sportsbook
  • bet365, Sportsbook
  • BetMGM, Sportsbook
  • BetRivers, Sportsbook
  • Kalshi, Prediction Market
  • Polymarket, Prediction Market
  • 1xBet, Sportsbook
  • 888sport, Sportsbook
  • Bally Bet, Sportsbook
  • bet105, Sportsbook
  • Betano, Sportsbook
  • Betfair, Exchange
  • BetOnline, Sportsbook
  • BetUS, Sportsbook
  • Betway, Sportsbook
  • Bovada, Sportsbook
  • Fanatics Markets, Prediction Market
  • Fliff, Sportsbook
  • Hard Rock, Sportsbook
  • MyBookie, Sportsbook
  • Novig, Exchange
  • Pinnacle, Sportsbook
  • ProphetX, Exchange
  • ReBet, Sportsbook
  • SBOBET, Sportsbook
  • Shuffle, Sportsbook
  • Sky Bet, Sportsbook
  • SportBet, Sportsbook
  • Stake, Sportsbook
  • sx.bet, Exchange
  • theScore Bet, Sportsbook
  • Thunderpick, Sportsbook
  • Unibet, Sportsbook
  • Sportsbook
  • Exchange
  • Prediction Market

Every sport, every market shape we carry

One set of markets, applied the same way whichever sport you ask about.

Sports

  • NFL
  • NCAAF
  • NBA
  • WNBA
  • MLB
  • NHL
  • Soccer
  • MMA

Markets

  • Moneyline
  • Spreads
  • Totals
  • Period markets (1st half, F5, ...)
  • Alternate lines
  • Team totals
  • Player props

11 endpoints, nothing else to learn

The whole surface, plus account endpoints for your keys and usage. Only calls that return prices count against your plan; looking around is free.

  • GET/v1/sportsfreeList every sport and league we carry
  • GET/v1/bookmakersfreeList every book we carry
  • GET/v1/marketsfreeList every market key and which period it carries
  • GET/v1/sports/{sport}/eventsfreeList a sport's fixtures, no prices
  • GET/v1/sports/{sport}/odds1 requestList a sport's fixtures with prices
  • GET/v1/sports/{sport}/events/{id}/odds1 requestOne fixture's prices, any market including periods and alternates
  • GET/v1/sports/{sport}/props1 requestPlayer props across a sport's fixturesGrowth (100K requests a month) and up
  • GET/v1/sports/{sport}/events/{id}/props1 requestPlayer props for one fixtureGrowth (100K requests a month) and up
  • GET/v1/historical/sports/{sport}/events/{id}/odds1 requestThe full recorded price series for one fixtureScale (500K requests a month) and up
  • GET/v1/historical/sports/{sport}/events/{id}/openers1 requestEach book's opening line for one fixtureScale (500K requests a month) and up
  • GET/v1/historical/sports/{sport}/events/{id}/closing1 requestEach book's closing line for one fixtureScale (500K requests a month) and up

Copy, paste, run

Five common calls in five languages. The key always travels in the X-API-Key header.

GET/v1/sports/americanfootball_nfl/odds?markets=h2h,spreads
curl "https://oddslink.app/v1/sports/americanfootball_nfl/odds?markets=h2h,spreads" \
  -H "X-API-Key: ok_live_..."
200 OKresponse.json
[
  {
    "id": "nfl:falcons-panthers:2026-09-20",
    "sport_key": "americanfootball_nfl",
    "sport_title": "NFL",
    "commence_time": "2026-09-20T17:00:00Z",
    "home_team": "Atlanta Falcons",
    "away_team": "Carolina Panthers",
    "bookmakers": [
      {
        "key": "betmgm",
        "title": "BetMGM",
        "last_update": "2026-09-18T18:08:20Z",
        "markets": [
          {
            "key": "h2h",
            "last_update": "2026-09-18T18:08:20Z",
            "outcomes": [
              {
                "name": "Atlanta Falcons",
                "price": 124
              },
              {
                "name": "Carolina Panthers",
                "price": -148
              }
            ]
          },
          {
            "key": "spreads",
            "last_update": "2026-09-18T18:08:14Z",
            "outcomes": [
              {
                "name": "Atlanta Falcons",
                "price": 100,
                "point": 2.5
              },
              {
                "name": "Carolina Panthers",
                "price": -120,
                "point": -2.5
              }
            ]
          }
        ]
      },
      {
        "key": "fanduel",
        "title": "FanDuel",
        "last_update": null,
        "markets": [
          {
            "key": "h2h",
            "last_update": null,
            "outcomes": [
              {
                "name": "Atlanta Falcons",
                "price": 120
              },
              {
                "name": "Carolina Panthers",
                "price": -142
              }
            ]
          },
          {
            "key": "spreads",
            "last_update": null,
            "outcomes": [
              {
                "name": "Atlanta Falcons",
                "price": -102,
                "point": 2.5,
                "size": {
                  "kind": "posted_limit",
                  "amount": 5000
                }
              },
              {
                "name": "Carolina Panthers",
                "price": -118,
                "point": -2.5,
                "size": {
                  "kind": "posted_limit",
                  "amount": 5000
                }
              }
            ]
          }
        ]
      }
    ],
    "unmatched_bookmakers": [
      "betano"
    ]
  }
]

Three fields worth knowing

They sit beside the prices, so code that doesn't read them can skip them.

When each price was confirmed

last_update

On every book and market: the moment that book last confirmed its prices, or null where we don't measure it. A price that falls behind its book's measured update rhythm is removed.

{ "key": "totals_f5",
  "last_update": "2026-09-21T16:42:07Z" }

Size carries its kind

size.kind

A posted limit, a resting exchange depth and a contract count aren't the same number. Each outcome says which one it's giving you, and says nothing when the book publishes none.

{ "kind": "resting_depth",
  "amount": 1200 }

Missing books are named

unmatched_bookmakers

A book that reached us but couldn't be matched to this fixture is listed in the response instead of silently missing.

"unmatched_bookmakers": ["betano"]

Start reading odds in one request.

Free plan: 1,000 requests a month, every book.