18+ Only  |  Gambling can be addictive — please gamble responsibly  |  Gambling Help: 1800 858 858  |  GambleAware
curl · Python · JavaScript

API Examples

Working code samples for every endpoint. Replace YOUR_API_KEY with your key.

List active sports

Returns all sports with active odds coverage. Cost: 1 credit.

curl https://api.puntersedge.online/v1/sports \
  -H "X-API-Key: YOUR_API_KEY"
import requests

r = requests.get(
    "https://api.puntersedge.online/v1/sports",
    headers={"X-API-Key": "YOUR_API_KEY"}
)
print(r.json())
const res = await fetch("https://api.puntersedge.online/v1/sports", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
const data = await res.json();
console.log(data);
Example response (not live data)
[
  {"key": "afl", "title": "AFL", "group": "Australian Rules", "active": true},
  {"key": "nrl", "title": "NRL", "group": "Rugby League", "active": true},
  {"key": "nba", "title": "NBA", "group": "Basketball", "active": true}
]

NRL head-to-head odds

Returns upcoming NRL matches with h2h prices from all bookmakers. Cost: 1 credit.

curl "https://api.puntersedge.online/v1/sports/nrl/odds?markets=h2h" \
  -H "X-API-Key: YOUR_API_KEY"
r = requests.get(
    "https://api.puntersedge.online/v1/sports/nrl/odds",
    params={"markets": "h2h"},
    headers={"X-API-Key": "YOUR_API_KEY"}
)
print(r.json())
const res = await fetch(
  "https://api.puntersedge.online/v1/sports/nrl/odds?markets=h2h",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
Example response (not live data)
[
  {
    "id": "abc123",
    "sport_key": "nrl",
    "sport_title": "NRL",
    "home_team": "Melbourne Storm",
    "away_team": "Penrith Panthers",
    "commence_time": "2026-06-07T09:50:00Z",
    "bookmakers": [
      {
        "key": "sportsbet",
        "title": "Sportsbet",
        "markets": [
          {
            "key": "h2h",
            "outcomes": [
              {"name": "Melbourne Storm", "price": 1.85},
              {"name": "Penrith Panthers", "price": 1.95}
            ]
          }
        ]
      }
    ]
  }
]

Multiple market types

Get h2h and line (spreads) in one call. Cost: 2 credits (1 per market type).

curl "https://api.puntersedge.online/v1/sports/afl/odds?markets=h2h,spreads" \
  -H "X-API-Key: YOUR_API_KEY"
r = requests.get(
    "https://api.puntersedge.online/v1/sports/afl/odds",
    params={"markets": "h2h,spreads"},
    headers={"X-API-Key": "YOUR_API_KEY"}
)

Best-odds comparison + arb detection

Returns the best available price per selection across all bookmakers, and flags any arbitrage opportunities. Cost: 3 credits.

curl "https://api.puntersedge.online/v1/best-odds/afl" \
  -H "X-API-Key: YOUR_API_KEY"
r = requests.get(
    "https://api.puntersedge.online/v1/best-odds/afl",
    headers={"X-API-Key": "YOUR_API_KEY"}
)
// Also a bare array. Each event carries `selections`, already merged across books.
const res = await fetch("https://api.puntersedge.online/v1/best-odds/afl", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
const events = await res.json();

for (const ev of events) {
  console.log(`${ev.home_team} v ${ev.away_team}`);
  for (const sel of ev.selections) {
    console.log(`  ${sel.name} ${sel.best_price} (${sel.best_bookmaker})`);
  }
  if (ev.arb_exists) console.log(`  arb ${ev.arb_profit_pct}%`);
}
Example response (not live data)
[
  {
    "id": "def456",
    "sport_key": "afl",
    "home_team": "Collingwood",
    "away_team": "Carlton",
    "commence_time": "2026-08-22T09:20:00Z",
    "selections": [
      {"name": "Collingwood", "best_price": 1.92, "best_bookmaker": "tab"},
      {"name": "Carlton", "best_price": 2.10, "best_bookmaker": "sportsbet"}
    ],
    "arb_exists": false,
    "arb_profit_pct": -3.8,
    "data_age_seconds": 41,
    "freshest_age_seconds": 3,
    "stale": false,
    "stale_bookmakers": []
  }
]

Sports arbitrage scanner

Scans upcoming markets for true arbitrage and best-odds overlays, returning arb_pct, optimal stakes and per-selection price comparison. Set min_profit_pct=0 to also see value overlays. Cost: 3 credits.

curl "https://api.puntersedge.online/v1/arb/sports?sport_key=nrl&min_profit_pct=0" \
  -H "X-API-Key: YOUR_API_KEY"
r = requests.get(
    "https://api.puntersedge.online/v1/arb/sports",
    params={"sport_key": "nrl", "min_profit_pct": 0},
    headers={"X-API-Key": "YOUR_API_KEY"}
)
for evt in r.json():
    if evt["is_arb"]:
        print(evt["home_team"], "vs", evt["away_team"], evt["arb_pct"], "%")
Example response (not live data)
[
  {
    "sport_key": "nrl",
    "home_team": "Melbourne Storm",
    "away_team": "Penrith Panthers",
    "commence_time": "2026-06-21T09:50:00Z",
    "is_arb": true,
    "arb_pct": 2.84,
    "max_overlay_pct": 3.1,
    "optimal_stakes": [
      {"name": "Melbourne Storm", "stake": 52.7, "bookmaker": "sportsbet", "profit_if_wins": 5.41},
      {"name": "Penrith Panthers", "stake": 47.3, "bookmaker": "neds", "profit_if_wins": 5.39}
    ],
    "selections": [
      {"name": "Melbourne Storm", "best_price": 1.96, "best_bookmaker": "sportsbet",
       "avg_price": 1.88, "overlay_pct": 3.1,
       "all_prices": [{"bookmaker": "sportsbet", "price": 1.96}, {"bookmaker": "tab", "price": 1.90}]}
    ]
  }
]

Best racing price per runner

Returns the best win and place price for every runner across the Australian bookmakers, with the book offering it, a deep link to that book's race page, and the market percentage so you can see the overround.

curl "https://api.puntersedge.online/v1/racing/best-odds?categories=horse" \
  -H "X-API-Key: YOUR_API_KEY"
r = requests.get(
    "https://api.puntersedge.online/v1/racing/best-odds",
    params={"categories": "horse", "min_edge_pct": 1, "verify": 1},
    headers={"X-API-Key": "YOUR_API_KEY"}
)
Example response (not live data)
[
  {
    "race_id": "race_123", "venue": "Rosehill", "race_number": 8, "category": "horse",
    "country": "AU", "start_time": "2026-08-15T05:45:00Z", "race_name": "TAB ROSEBUD",
    "track_condition": "Good (4)", "market_percentage": 106.4, "books_compared": 11,
    "scratchings": [], "data_age_seconds": 41, "freshest_age_seconds": 3, "stale": false,
    "runners": [
      {
        "name": "Chilly Girl", "number": 7, "barrier": 3,
        "jockey": "J Mcdonald", "trainer": "C Waller",
        "best_win":   {"price": 6.5,  "bookmaker": "betright", "age_seconds": 6,  "stale": false},
        "best_place": {"price": 2.15, "bookmaker": "tab",      "age_seconds": 4,  "stale": false}
      }
    ]
  }
]

Historical odds & price movements Standard+

Snapshots over a date range and detected price moves. Available on Standard, Business and Unlimited (and legacy Pro, Growth and Enterprise keys). Free and Hobby get a 403. Cost: 5 credits each.

# Historical h2h snapshots for the last 7 days
curl "https://api.puntersedge.online/v1/sports/afl/odds/history?market=h2h" \
  -H "X-API-Key: YOUR_API_KEY"

# Price movements in the last 24h (min 0.05 drift)
curl "https://api.puntersedge.online/v1/sports/afl/odds/movements?min_delta=0.05" \
  -H "X-API-Key: YOUR_API_KEY"

Next-to-go racing

Returns the next N races with runners and current fixed odds. Cost: 2 credits.

# All racing categories
curl "https://api.puntersedge.online/v1/racing/next-to-go?num_races=5" \
  -H "X-API-Key: YOUR_API_KEY"

# Horse racing only
curl "https://api.puntersedge.online/v1/racing/next-to-go?num_races=5&categories=horse" \
  -H "X-API-Key: YOUR_API_KEY"
r = requests.get(
    "https://api.puntersedge.online/v1/racing/next-to-go",
    params={"num_races": 5, "categories": "horse"},
    headers={"X-API-Key": "YOUR_API_KEY"}
)
// Node 18+ or any modern browser. Returns a JSON ARRAY of races.
const res = await fetch(
  "https://api.puntersedge.online/v1/racing/next-to-go?num_races=5&categories=horse",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const races = await res.json();

for (const race of races) {
  console.log(`${race.venue} R${race.race_number} (${race.category})`);
  for (const runner of race.runners.slice(0, 4)) {
    const best = runner.bookmakers.reduce((a, b) => (b.win_price > a.win_price ? b : a));
    console.log(`  ${runner.name} ${best.win_price} (${best.key})`);
  }
}

Check your usage

Returns credits used and remaining this month. Cost: 0 credits.

curl https://api.puntersedge.online/v1/usage \
  -H "X-API-Key: YOUR_API_KEY"
Example response (not live data)
{
  "plan": "free",
  "credits_limit": 1500,
  "credits_used": 47,
  "credits_remaining": 1453,
  "reset_at": "2026-09-01T00:00:00",
  "usage_by_endpoint": [
    {"endpoint": "/v1/racing/next-to-go", "calls": 20, "credits": 40}
  ]
}

Error responses

# Every error is application/problem+json with the same four keys.

# Missing API key — 401
{"type": "https://puntersedge.online/errors/unauthorized",
 "title": "X-API-Key header required",
 "status": 401,
 "detail": "X-API-Key header required"}

# Invalid API key — 401
{"type": "https://puntersedge.online/errors/unauthorized",
 "title": "Invalid API key",
 "status": 401,
 "detail": "Invalid API key"}

# Monthly credits exhausted — 402  (detail names your plan and limit)
{"type": "https://puntersedge.online/errors/payment-required",
 "title": "Credit limit reached (1500/mo on free plan). Upgrade at puntersedge.online/api",
 "status": 402,
 "detail": "Credit limit reached (1500/mo on free plan). Upgrade at puntersedge.online/api"}

# Plan does not include this endpoint — 403  (historical odds & movements)
{"type": "https://puntersedge.online/errors/forbidden",
 "title": "Historical odds are available on Standard, Business, Unlimited and Enterprise plans only",
 "status": 403,
 "detail": "Historical odds are available on Standard, Business, Unlimited and Enterprise plans only"}

# Unknown sport_key — 404  (the full list of valid keys is returned with it)
{"type": "https://puntersedge.online/errors/not-found",
 "title": "Unknown sport_key 'notasport'. Valid sport_keys: afl, aflw, basketball_other, ... See GET /v1/sports.",
 "status": 404,
 "detail": "Unknown sport_key 'notasport'. Valid sport_keys: ... See GET /v1/sports."}
# The live response spells out every active key (19 as at 2026-08-16). Read them from
# GET /v1/sports rather than hard-coding this list — sports are added without notice.

# Too many requests — 429  (detail is an object here, not a string)
{"type": "https://puntersedge.online/errors/rate-limit",
 "title": "Error",
 "status": 429,
 "detail": {"error": "rate_limit_exceeded",
            "message": "Rate limit exceeded: 30 requests/minute on free plan.",
            "upgrade_url": "https://puntersedge.online/api",
            "retry_after_seconds": 60}}
Get free API key → Swagger docs Postman collection Coverage
This site contains wagering-related analysis and is intended for Australian users aged 18+. Gambling involves risk. Please gamble responsibly.