Odds API for Next.js

Fetch real-time odds in Next.js server components and route handlers, with your API key kept server-side and responses cached. Normalized JSON, no SDK.

Overview

The MoneyLine odds API is a plain REST/HTTPS API, which makes it a natural fit for the Next.js App Router. Because there is no SDK or native module to install, you call it with the same native fetch the App Router already uses — inside a server component or a route handler — so your API key never reaches the browser bundle.

Responses are normalized to American odds under canonical event IDs, so a server component can render moneyline, spread, total, and player-prop markets directly, and a route handler can return a trimmed shape to the client without per-sportsbook parsing. Each event also carries a summary object with no-vig fair odds, the best available price, and the consensus average, so you can surface value without building a normalization layer of your own.

Next.js fetch caching is the other half of the fit. Passing next: { revalidate: <seconds> } to a server-side fetch lets you tune how often odds are refetched: a short window for live in-play screens, a longer window for static pregame pages. That same dial controls your request volume against the API, which keeps you comfortably inside the free tier for most read-heavy pages.

The result is a clean separation of concerns: the server reads odds with a hidden key and a cache policy you control, while the client only ever receives rendered HTML or a slimmed JSON payload. The normalized shape maps cleanly onto your own TypeScript types, so the data layer stays small and predictable as you add leagues, props, or pages.

Get started

  1. 1

    Create a key, store it server-only

    Grab a free API key from the dashboard and put it in a server-only env var like ML_API_KEY — never a NEXT_PUBLIC_ variable.

  2. 2

    Fetch on the server

    Call /v1/odds inside a server component or app/api route handler, reading the key from process.env so it stays off the client.

  3. 3

    Tune freshness with revalidate

    Add next: { revalidate: <seconds> } to the fetch to control how often odds refetch — lower for live, higher for pregame.

Key features

Server-side fetch

Call the API in server components or route handlers so the x-api-key header never ships to the browser.

fetch revalidate caching

Tune freshness against request volume with Next.js next: { revalidate } — short for live odds, long for pregame.

No SDK to install

It is REST over HTTPS, so the App Router native fetch is all you need — nothing to add to package.json.

Normalized JSON

American odds under canonical event IDs arrive in one schema, ready to render without per-book adapters.

Game lines + player props

Moneyline, spread, and total plus per-sport player props across every major US league.

Maps to your types

The stable JSON contract maps cleanly onto your own TypeScript interfaces, so the data layer stays typed end to end.

Supported leagues

NFLNBAMLBNHLNCAAFNCAAB

Supported sportsbooks

DraftKingsFanDuelBetMGMCaesarsESPN BETFanaticsHard Rock BetBetRiversPinnaclebet365 (US)BovadaBetOnline.ag

Example request

Next.js App Router — server component with revalidate

Request

// app/odds/page.tsx (server component)
async function getOdds() {
  const res = await fetch(
    'https://mlapi.bet/v1/odds?league=nba&market=moneyline',
    {
      headers: { 'x-api-key': process.env.ML_API_KEY! },
      next: { revalidate: 60 }, // cache for 60s
    },
  )
  return res.json()
}

export default async function OddsPage() {
  const { data } = await getOdds()
  return (
    <ul>
      {data.map((g) => (
        <li key={g.eventId}>{g.eventId}</li>
      ))}
    </ul>
  )
}

Response

{
  "success": true,
  "data": [
    {
      "eventId": "nba-ev-311286",
      "leagueId": "nba",
      "bookmakers": [
        {
          "bookmakerId": "draftkings",
          "bookmakerName": "DraftKings",
          "markets": [
            { "marketType": "moneyline", "outcomes": [
              { "name": "Boston Celtics", "price": -180 },
              { "name": "Los Angeles Lakers", "price": 155 }
            ] }
          ]
        }
      ]
    }
  ]
}

Next.js integration

ConcernHow it works
Server-side fetchCall the API in server components or route handlers; the key stays off the client
CachingUse the fetch revalidate option to tune freshness vs request volume
API keyRead from a server-only env var, never exposed to the browser
TypesThe normalized JSON shape maps cleanly to your own TypeScript types

Use cases

SSR odds pages

Render moneyline, spread, and total lines server-side for fast, indexable pages with your key hidden.

Route handler proxy

Trim and reshape the API response for your client from an app/api route so the browser never sees the key.

ISR dashboards

Use next: { revalidate } to balance freshness against request volume on player-prop and price-comparison views.

Value & arbitrage screens

Render the per-outcome fairOdds, bestOdds, and avgOdds summary to flag value without a client-side normalization layer.

Static pregame pages

Cache pregame lines with a long revalidate window for cheap, cacheable marketing or preview pages.

Latency & performance

FAQ

How do I use an odds API in Next.js?

Fetch the REST endpoint inside a server component or route handler with your API key from a server-only env var, then use the fetch revalidate option to cache the normalized JSON response.

Where do I put my API key?

In a server-only env var (e.g. ML_API_KEY) read inside a server component or route handler, never a NEXT_PUBLIC_ variable.

How do I control freshness?

Use the Next.js fetch option next: { revalidate: <seconds> } to cache responses; lower for live odds, higher for static views.

Do I need an SDK?

No. It is REST over HTTPS, so the native fetch in the App Router is all you need — there is no SDK or native module to install.

Should I fetch in a server component or a route handler?

Use a server component when you render odds directly on the page, and a route handler when the client needs to refetch or you want to trim the payload before it reaches the browser.

Which leagues and markets can I render?

NFL, NBA, MLB, NHL, NCAAF, and NCAAB, each with moneyline, spread, and total game lines plus per-sport player props.

How does the response map to my types?

Responses come back in one normalized JSON shape with American odds under canonical event IDs, so you can define matching TypeScript interfaces once and reuse them across pages.

Is there a free tier?

Yes — the free tier covers personal and commercial use with every endpoint, and fetch caching keeps most read-heavy pages well within its limits.

Related

Pricing

Free

$0/mo

1K credits/mo

Starter

$29/mo

150K credits/mo

Pro

$149/mo

1.5M credits/mo

Business

$299/mo

5M credits/mo

Enterprise

Custom

Unlimited credits/mo

View full pricing →

Start building in minutes

Free tier to start, one API key, normalized responses across every league and sportsbook.