Odds API quickstart: live lines in under 10 minutes with cURL, Python and JS

By the propzapi team · Last updated July 2026 · 7 min read

Odds API quickstart: get a key and fetch live sports odds in under ten minutes, 2026.

You don't need a tutorial series to pull live odds. You need one key and one request.

To fetch live sports odds, get a free key from a live sports odds API, then send one authenticated GET. With propzapi you POST once to /v1/register for a key with 750 free credits and no card, then call /v1/odds with a league filter and your key in an X-API-Key header. Ten minutes from now you'll have live lines printing in your terminal, in cURL, Python or JavaScript.

This is a copy-paste quickstart, nothing more. Every snippet is a working call against the real API. I use propzapi because it's what I build, and because you can start with no signup form and no credit card.

Step 1: get a free key

Send one POST and you have a key. No form, no card, no email. /v1/register mints a key with 750 free credits a month and hands it straight back. Keep it server-side and send it as an X-API-Key header on every request from here on.

curl -X POST https://api.propzapi.com/v1/register
# → { "api_key": "pk_live_…", "plan": "free", "credits": 750 }

That's the whole signup. If you'd rather manage keys and billing in a UI, the dashboard does that too, but for getting a line into your terminal, the register call is faster.

Three steps: POST to register for a key, GET odds with the key, receive JSON. Under ten minutes end to end.
Key, request, JSON. That's the entire path.

Step 2: your first request in cURL

One GET to /v1/odds returns live odds as JSON. Filter to a league, pass your key in the header, and add -i so you can see the X-Credits-Cost header that tells you exactly what the call charged. No SDK required to prove it works.

curl "https://api.propzapi.com/v1/odds?league=NBA&market=h2h" \
  -H "X-API-Key: pk_live_…" -i
# -i prints headers too, so you can see X-Credits-Cost

The response is a tree of events, each holding the books that price it, each book holding its markets and priced outcomes. Learn this shape once and every endpoint reads the same.

{
  "count": 1,
  "data": [
    {
      "event_id": "401766…",
      "league": "NBA",
      "home_team": "Boston Celtics",
      "away_team": "New York Knicks",
      "commence_time": "2026-10-21T23:30:00Z",
      "status": "upcoming",
      "books": [
        { "book": "DraftKings", "markets": [
          { "market": "h2h", "outcome": "Celtics", "price": -145 },
          { "market": "h2h", "outcome": "Knicks", "price": 124 }
        ]}
      ]
    }
  ]
}
The response tree: an event contains books, each book contains markets, each market contains priced outcomes.
Event, then book, then market, then price. Game odds all read this way.

Step 3: Python

Use the official client or raw requests, both work. The Python client is one pip install, mints a key, and reads the credit cost for you. If you'd rather not add a dependency, plain requests against the same URL does the identical thing. Either way you have live odds in a handful of lines.

The quickest path is the client.

pip install propzapi
from propzapi import Propzapi, register

key = register()["api_key"]          # free key, no card
client = Propzapi(key)

odds = client.odds(league="NBA", market="h2h")
print(len(odds), "events, this call cost", client.last_credits_cost)

No dependency? Raw requests is just as short, and calling raise_for_status() means a bad key or an empty balance fails loudly instead of silently.

import requests

r = requests.get(
    "https://api.propzapi.com/v1/odds",
    params={"league": "NBA", "market": "h2h"},
    headers={"X-API-Key": "pk_live_…"},
    timeout=15,
)
r.raise_for_status()                 # fail loud on 401/402/429
data = r.json()["data"]
print(len(data), "events, cost", r.headers["X-Credits-Cost"])

Step 4: JavaScript and Node

Native fetch is all you need, no package to install. In Node 18+, Deno or the browser, register for a key and GET the odds endpoint with your key in the header. Check res.ok so a 401 or 402 throws instead of parsing as data, and read X-Credits-Cost off the response headers.

// native fetch, no dependency (Node 18+, Deno, browser)
const key = (await (await fetch(
  "https://api.propzapi.com/v1/register", { method: "POST" }
)).json()).api_key;

const res = await fetch(
  "https://api.propzapi.com/v1/odds?league=NBA&market=h2h",
  { headers: { "X-API-Key": key } }
);
if (!res.ok) throw new Error(`propzapi ${res.status}`);
const { count, data } = await res.json();
console.log(count, "events, cost", res.headers.get("X-Credits-Cost"));
cURL, Python and JavaScript all send the same authenticated GET to the odds endpoint and get back the same JSON.
Same key, same endpoint, same JSON. The language is just the wrapper.

Step 5: filter by league and market

Three query params narrow the response: league, market, and limit. Ask for one market to keep the call light, or omit it for all game markets. On /v1/odds a market is h2h, spreads, totals or player_props; a value that isn't valid returns a 400 with the allowed options and doesn't cost a credit, so a typo never bills you.

ParamValuesNotes
leagueNBA, NFL, MLB, NHL, EPL, MLS…The most common filter
marketh2h, spreads, totals, player_propsOmit for all game markets
limit1 to 100 (default 25)Bounded, so 0 or negatives are rejected
Query params league and market narrow the odds response; a bad market returns a free 400 rather than a silent empty result.
Filters narrow the call. A bad market is a free 400, not a silent empty at full price.

Step 6: pull player props in one call

Player props sit on their own endpoint, /v1/props, and come back already grouped per player: each object carries the player, the market, the line, and every book's over and under prices side by side. No string-parsing a name out of an outcome, no pairing two rows yourself. Filter to one market like player_points or player_passing_yards, or leave market off for every prop on the slate. Props are the markets most odds APIs cover thinly, and here they come back as clean JSON in one call.

curl "https://api.propzapi.com/v1/props?league=NBA&market=player_points" \
  -H "X-API-Key: pk_live_…"

Market names are player_<stat>: player_points, player_rebounds, player_assists for the NBA; player_passing_yards, player_receptions for the NFL; player_strikeouts for MLB. The full props walkthrough lives in the NFL player props model guide.

What to know before you build

Three things save you time later: read the cost header instead of guessing, cache between polls, and let bad requests fail loudly. Every call returns X-Credits-Cost and X-Credits-Remaining, so spend is a number you log, not a mystery. Poll live markets fast and pre-match slow, with a short cache in front. And a 401, 402 or 429 should throw in your code, not parse as empty data.

StatusMeaning
400Bad parameter (e.g. an unknown market). Free, not charged.
401Missing or invalid key
402Out of credits
429Rate limited
Every response carries X-Credits-Cost and X-Credits-Remaining headers, so the cost of each call is visible, not guessed.
Every call tells you what it cost and what's left. No pricing table to memorize.

That's the quickstart. For the full endpoint reference the docs have cURL, Python and JS side by side, the complete odds API guide covers the fundamentals, and if you're wiring this into an assistant there's an MCP server so an agent can pull odds as a tool call.

Frequently asked questions

How do I get a live sports odds API key?
Send one POST to /v1/register. No signup form, no card, no email required. You get back a key and 750 free credits a month immediately. Put the key in an X-API-Key header on every request. You can also sign up in the dashboard if you want to manage keys and billing, but for a quickstart the register call is the fastest path.
What does one odds call cost?
It is metered by market, and you never have to guess. Every response returns the exact cost of that call in an X-Credits-Cost header, and your remaining balance in X-Credits-Remaining. A single market is the lightest call; all game markets or player props cost more. Read the header instead of tracking a table.
Which markets can I request?
On /v1/odds: h2h (moneyline), spreads, totals, or player_props. Leave market off for all game markets together. On /v1/props: one player market like player_points or player_passing_yards. A market that isn't valid returns a 400 with the allowed values, and it doesn't cost a credit, so a typo never bills you.
Do I need an SDK?
No. The API is plain REST and JSON, so cURL, Python requests, or native fetch all work with no dependency. There is an official Python client (pip install propzapi) if you want typed methods and the credit cost read for you, but every example here also works with raw HTTP.
How fresh are the odds?
Live and pre-match lines, normalized across books. Poll on a short interval for live markets and a longer one pre-match, and cache between pulls so you are not repeating calls. The response tells you each call's cost, so you can tune polling against your credit budget precisely.

Run the first call now

Don't read another paragraph. Paste the register command, copy the key it returns into the cURL call above, and watch live NBA lines print. Then swap league=NBA for your sport and market=h2h for the market you care about. You're building, not reading, and it took under ten minutes.

Get a free key Read the docs