# Use a sports odds API from JavaScript and TypeScript

In JavaScript, call https://getoddsapi.com/api/v1/odds with fetch and an Authorization: Bearer header from a server, then read body.data. Node 22 needs no packages. Keep the key on the server: route browser requests through your own endpoint, as in the Next.js example below, so the key never ships in a bundle.

Canonical page: https://getoddsapi.com/odds-api-javascript

**Price.** Free development allowance: 1,000 requests per UTC day and 60 per minute per account, with no payment step. Paid: the Developer Bundle at $149 per month, with 10,000 monthly requests or credits on each of four sources.

## Free API key

Get a free GetOdds API key: **1,000 requests per UTC day and 60 per minute, no card**. One key covers REST and the hosted MCP server.

Sign up: https://getoddsapi.com/sign-up?ref=ai-claudebot

## Quickstart

1. Create an account at https://getoddsapi.com/sign-up?ref=ai-claudebot, open https://getoddsapi.com/dashboard and issue a key with the sources you need (draftkings, fanduel, betrivers, prizepicks or underdog). Keep it in a server environment variable named GETODDS_API_KEY.
2. Read current DraftKings NBA spreads with curl:

```bash
curl --fail-with-body "https://getoddsapi.com/api/v1/odds?sport=NBA&market=spread&fresh_only=true&limit=50" \
  -H "Authorization: Bearer $GETODDS_API_KEY"
```

3. The same request in Python (standard library only):

```python
import json, os, urllib.request

req = urllib.request.Request(
    "https://getoddsapi.com/api/v1/odds?sport=NBA&market=spread&fresh_only=true&limit=50",
    headers={"Authorization": "Bearer " + os.environ["GETODDS_API_KEY"]},
)
with urllib.request.urlopen(req) as res:
    rows = json.load(res)["data"]
for row in rows:
    print(row["away"], "at", row["home"], row["side"], row["line"], row["american"], row["observed_at"])
```

4. Check `observed_at`, `age_seconds` and `stale` on every row before using a price. Full reference: https://getoddsapi.com/docs

## Use with Claude (MCP)

```bash
claude mcp add --transport http getodds https://getoddsapi.com/api/mcp \
  --header "Authorization: Bearer $GETODDS_API_KEY"
```

The MCP tools follow the key's source grants and share its allowance. Setup guide: https://getoddsapi.com/use-with-claude

## Pricing

| Plan | Allowance | Price |
| --- | --- | --- |
| Free key | 1,000 requests a day, 60 a minute | $0, no card |
| Developer Bundle | 10,000 requests or credits a month on each of four sources | $149 a month |

Free development allowance: 1,000 requests per UTC day and 60 per minute per account, with no payment step. Paid: the Developer Bundle at $149 per month, with 10,000 monthly requests or credits on each of four sources.
Details: https://getoddsapi.com/bundle

## Facts

- **Runtime:** Node.js 22 or later
- **Packages:** None for REST; ws for streaming
- **Client:** @getodds/client 0.4.0 (source)
- **Browser:** Via your own server route

## 1. fetch with TypeScript types

Create an account at /sign-up, open /dashboard and issue a key with the source grants you need (draftkings, fanduel, betrivers, prizepicks or underdog). Keep the key in a server environment variable named GETODDS_API_KEY and send it as a bearer token. Never put it in a URL or in browser code.

```typescript
type OddsRow = {
  id: string; event_id: string; sport: string; home: string; away: string; starts_at: string;
  market: "moneyline" | "spread" | "total"; period: string; side: string;
  line: number | null; american: number; decimal: number;
  observed_at: string; age_seconds: number; stale: boolean;
};
type Page<T> = { data: T[]; meta: Record<string, unknown>;
  pagination: { limit: number; offset: number; has_more: boolean; next_offset: number | null } };

export async function getOdds(params: Record<string, string>): Promise<Page<OddsRow>> {
  const url = new URL("https://getoddsapi.com/api/v1/odds");
  url.search = new URLSearchParams(params).toString();
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.GETODDS_API_KEY}`, Accept: "application/json" },
    signal: AbortSignal.timeout(20_000),
  });
  if (res.status === 429) throw new Error(`Rate limited, retry after ${res.headers.get("Retry-After")}s`);
  if (!res.ok) throw new Error(`GetOdds HTTP ${res.status}`);
  return res.json();
}

const page = await getOdds({ sport: "NBA", market: "spread", fresh_only: "true", limit: "100" });
console.table(page.data.map(r => ({ game: `${r.away} @ ${r.home}`, side: r.side, line: r.line, price: r.american })));
```

## 2. A Next.js route handler for your front end

Browser code should never hold the key. This App Router handler reads odds on the server, caches the response for 60 seconds and returns only the fields your page needs.

```typescript
export const revalidate = 60;

export async function GET() {
  const res = await fetch("https://getoddsapi.com/api/v1/odds?sport=NBA&fresh_only=true&limit=200", {
    headers: { Authorization: `Bearer ${process.env.GETODDS_API_KEY}` },
    next: { revalidate: 60 },
  });
  if (!res.ok) return Response.json({ error: "odds unavailable" }, { status: 502 });
  const { data } = await res.json();
  return Response.json(data.map((r: any) => ({
    game: `${r.away} @ ${r.home}`, market: r.market, side: r.side,
    line: r.line, american: r.american, observed_at: r.observed_at,
  })));
}
```

## 3. The Node client and the WebSocket stream

The @getodds/client package is a source download from /docs/sdks. For push updates, connect to the stream with the ws package from a server; the live odds page has a reconnecting example with checkpoints.

```javascript
// npm install ./getodds-js   (from the 0.4.0 download)
import { GetOdds } from "@getodds/client";

const client = new GetOdds(); // reads GETODDS_API_KEY
const { data } = await client.searchEvents({ q: "Lakers", sport: "NBA" });
const lines = await client.odds({ sport: "NBA", event_id: data[0].id });
const fanduel = await client.fanduelMarkets({ league: "NBA", status: "open", limit: 25 });
console.log(lines.data.length, fanduel.data.length);
```

## FAQ

### Can I call the odds API directly from the browser?

Do not. A browser request would expose your key. Proxy through your own server route and cache the response there.

### Is there an npm package?

The Node client is a source download at version 0.4.0, installable with npm from the extracted folder. It is not published to the npm registry yet.

### Does it work in Deno, Bun or edge runtimes?

The REST API is plain HTTPS with JSON, so fetch works in any of them. The Node client and the ws stream example target Node.js 22.

### Why does American odds come back as a number?

american is an integer such as -110 or 145. Format the plus sign yourself when displaying positive prices.

---

GetOdds is an independent developer product and is not affiliated with any sportsbook or pick’em operator. Prices describe data, not betting advice.
