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.
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.
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.
Call /v1/odds inside a server component or app/api route handler, reading the key from process.env so it stays off the client.
Add next: { revalidate: <seconds> } to the fetch to control how often odds refetch — lower for live, higher for pregame.
Call the API in server components or route handlers so the x-api-key header never ships to the browser.
Tune freshness against request volume with Next.js next: { revalidate } — short for live odds, long for pregame.
It is REST over HTTPS, so the App Router native fetch is all you need — nothing to add to package.json.
American odds under canonical event IDs arrive in one schema, ready to render without per-book adapters.
Moneyline, spread, and total plus per-sport player props across every major US league.
The stable JSON contract maps cleanly onto your own TypeScript interfaces, so the data layer stays typed end to end.
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 }
] }
]
}
]
}
]
}| Concern | How it works |
|---|---|
| Server-side fetch | Call the API in server components or route handlers; the key stays off the client |
| Caching | Use the fetch revalidate option to tune freshness vs request volume |
| API key | Read from a server-only env var, never exposed to the browser |
| Types | The normalized JSON shape maps cleanly to your own TypeScript types |
Render moneyline, spread, and total lines server-side for fast, indexable pages with your key hidden.
Trim and reshape the API response for your client from an app/api route so the browser never sees the key.
Use next: { revalidate } to balance freshness against request volume on player-prop and price-comparison views.
Render the per-outcome fairOdds, bestOdds, and avgOdds summary to flag value without a client-side normalization layer.
Cache pregame lines with a long revalidate window for cheap, cacheable marketing or preview pages.
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.
In a server-only env var (e.g. ML_API_KEY) read inside a server component or route handler, never a NEXT_PUBLIC_ variable.
Use the Next.js fetch option next: { revalidate: <seconds> } to cache responses; lower for live odds, higher for static views.
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.
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.
NFL, NBA, MLB, NHL, NCAAF, and NCAAB, each with moneyline, spread, and total game lines plus per-sport player props.
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.
Yes — the free tier covers personal and commercial use with every endpoint, and fetch caching keeps most read-heavy pages well within its limits.
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
Free tier to start, one API key, normalized responses across every league and sportsbook.