JavaScript and Node.js guide
Last updated 2026-10-30
From Node.js 18 or later, use the built-in fetch with your key in the x-api-key header. Call the API from your server, never from browser code, so the key stays private.
Fetch NBA moneylines
export BETTING_DATA_API_KEY=YOUR_API_KEY node odds.mjs
// Node 18+ (built-in fetch). Never ship your key to a browser.
const API_KEY = process.env.BETTING_DATA_API_KEY;
const BASE = "https://api.bettingdataapi.com";
const url = new URL("/odds/", BASE);
url.search = new URLSearchParams({ sport_key: "basketball_nba", markets: "h2h" });
const resp = await fetch(url, {
headers: { "x-api-key": API_KEY },
signal: AbortSignal.timeout(10000),
});
if (!resp.ok) {
const err = await resp.json().catch(() => ({}));
throw new Error(`HTTP ${resp.status}: ${err.detail ?? "request failed"}`);
}
const body = await resp.json();
for (const event of body.data) {
console.log(event.home_team, "vs", event.away_team, event.start_time);
for (const book of event.books ?? []) {
console.log(" ", book.book, book.market, book.outcomes.map(o => `${o.name} ${o.price}`).join(", "));
}
}
console.log("remaining today:", resp.headers.get("x-ratelimit-remaining"));Handle 429
async function getJson(url, apiKey) {
const resp = await fetch(url, { headers: { "x-api-key": apiKey } });
if (resp.status === 429) {
const wait = Number(resp.headers.get("retry-after") ?? 60);
const { detail } = await resp.json();
throw new Error(`Rate limited for ${wait}s: ${detail}`);
}
if (!resp.ok) throw new Error(`HTTP ${resp.status}: ${(await resp.json()).detail}`);
return resp.json();
}Using it in a web app
Put the call behind your own backend route (for example a Next.js route handler or an Express endpoint) and have the browser call that route. Cache the response for the league's refresh interval so many visitors share one API request. See rate limits.
Next
Try it with a free key
25 requests per day, NFL, NBA and MLB moneylines, no credit card.
Get a free API key