Changelog

Public log of everything that ships: features, parser fixes, source additions, behavior changes. We update this immediately on deploy. RSS at /changelog.rss.

Want fix-level visibility? Every parser change, source-health flip, and breaking-bug repair lands here within minutes of deploy. Email [email protected] if you want a per-fix email digest.
May 2026

Historical match coverage endpoint + per-source hint header

2026-05-19
apihistoricaltransparency

New endpoint GET /v1/historical/sports/{sport_key}/coverage?dateFrom=&dateTo= returns per-source row counts, first/last date, and priced-row counts for any sport over any window. 1 credit. Lets you pre-flight a source filter before burning credits on /matches: see at a glance that esports_cs2 has 15,379 HLTV rows but only 50 Pinnacle rows over a 16-month window.

Paired change: /v1/historical/sports/{sport_key}/matches now emits an X-Coverage-Hint response header when a source-filtered call returns far fewer rows than another source would. The hint names the better source and links to the coverage endpoint.

/v1/meta/api-key-check now exposes Stripe subscription state + last-request

2026-05-19
apibilling

The validate-without-charging endpoint now returns a subscription block (state, period_end_iso, stripe_subscription_id_prefix, stripe_customer_id_prefix) and a last_request_at_iso timestamp. Customers can self-diagnose the "I paid via Stripe but my key still says free" case: if subscription.state == "none" and tier == "free", the Checkout email didn't link to the account. Lookup is live against Stripe; period_end is read from items[].current_period_end for Stripe API 2026-04-22 (dahlia) compatibility.

The-odds-api v4 alias now works for WebSocket, not just REST

2026-05-19
apicompat

The drop-in compatibility middleware rewrites /v4/* to /v1/* at the ASGI scope layer. It was only handling HTTP scope, so customers porting from TOA who tried wss://parlay-api.com/v4/ws/odds/{sport_key} got a silent 404. Now both http and websocket scopes are rewritten, so wss://parlay-api.com/v4/ws/odds/baseball_mlb?apiKey=YOUR_KEY returns HTTP/1.1 101 Switching Protocols like the /v1 path.

/dashboard/billing 500 fixed (4 customer reports)

2026-05-19
dashboard

The self-serve upgrade page referenced a TierConfig field that no longer existed, so every visit since May 15 returned an Internal Server Error before rendering any upgrade buttons. Four open tickets traced to this exact path. Resolved.

Daily closing-line CSV downloads

2026-05-19
apihistorical

GET /v1/historical/closing-lines.csv?date=YYYY-MM-DD returns a flat-file daily snapshot of closing lines from prop_closing_lines, cached 6h on the server. Filters: optional sport_key= and source=. 1 credit per request. Designed for backtesters who want a CSV instead of the JSON shape of /v1/sports/{sport_key}/closing-lines. The underlying table is now natural-key unique (post-dedup migration), so every row is the latest-snapshot archive for that prop close.

Source-quality timeline: /v1/status/history + /status/history (HTML)

2026-05-19
apitransparency

Pairs with the existing point-in-time /v1/status. JSON at /v1/status/history?window_s=86400, rendered HTML at /status/history. Trailing 24h (configurable up to 7 days) per-source SLA classification timeline backed by a Redis ring buffer the collector samples every 30s. Public, no auth. Lets a customer answer "was the API healthy when my bot was running at 3am?" without contacting support.

Probable starting pitchers now on /v1/sports/baseball_mlb/odds

2026-05-19
apimlb

Each MLB event in the /odds response now includes a probable_pitchers block when MLB Stats API has them on file: home/away pitcher name plus MLB canonical Person ID, venue, and game status. Pitcher prop bettors no longer need a second call to /v1/sports/baseball_mlb/probable-pitchers. Constant-time lookup against the existing hourly cache; zero DB cost.

commence_time on /v1/sports/{sport}/ev

2026-05-19
fix

The EV-finder response now carries commence_time alongside game_date. Lets consumers distinguish "tonight late" (commence_time 03:00Z, game_date next day) from "tomorrow early" (commence_time 17:00Z, same UTC date), which the old game_date-only shape collapsed. Customer report: Educational_Act_5040.

WebSocket reference clients + reconnect cookbook

2026-05-19
docswebsocket

Two reference clients (Python, JS) demonstrate the silent-watchdog + capped exponential backoff + upstream-aware quiet handling pattern. Companion cookbook walks through frame shapes, the three causes of socket silence (connection dead vs market quiet vs upstream degraded), and common anti-patterns. Drops a copy-paste starting point for any new WebSocket integration.

ProphetX + Sporttrade SLA reclassified (exchange_slow)

2026-05-19
fixsla

Their per-tournament guest API requires login + per-tournament event fetches per cycle. Empirical cycle time is 5 to 7 minutes against the public path, not the 10-30s shape the "exchange" SLA class assumes. Both reclassified into a new exchange_slow bucket (120/360/900s). /v1/meta/source-quality and /v1/meta/per-book-sla now reflect the operationally honest thresholds for those two sources.

prop_closing_lines storage reclaimed (17 GB to 1.36 GB)

2026-05-19
fixperf

VACUUM FULL after the dedup migration (38.8M rows -> 2.97M) reclaimed 15.6 GB of disk in 15 seconds. The table no longer carries the bloat that was inflating closing-line lookups; expected p50 latency improvement on /v1/clv/* hot path is around 5x.

Public SLA visibility: /v1/meta/per-book-sla + sla_by_source on /v1/status

2026-05-19
apitransparency

GET /v1/meta/per-book-sla now publishes the freshness thresholds (tight_s / slack_s / stale_s) that classify every source as ok / degraded / breach / stale. Customers building on /v1/meta/source-quality no longer have to reverse-engineer what sla="degraded" means for a specific book. /v1/status also gained a sla_by_source map (per-source classification) and a poller_health block (Pinnacle WAF breaker state + Bovada 429 backoff state) so a customer asking "is the API healthy right now?" gets honest, granular signal instead of a single green/red bit.

WebSocket heartbeat now carries upstream freshness

2026-05-19
websocket

The 5-second heartbeat frame on /v1/ws/odds-fast/{sport_key} now includes an upstream object summarizing source-quality SLAs across all books (worst SLA seen + counts). Two outcomes a customer can now distinguish without leaving the socket: a healthy connection during a quiet market (long quiet_seconds, upstream.worst_sla="ok") vs an active upstream issue (long quiet_seconds, upstream.worst_sla="stale"). Cheap (reads the in-process source-quality cache), so no added latency on the broadcast path.

Table tennis added as a first-class sport (Bovada coverage)

2026-05-18
sportbovada

Table tennis is now a queryable sport_key on the main odds endpoints. Coverage comes from Bovada's public table-tennis lobby, which carries the full live + pre-match slate (typically 100+ events across TT Elite Series, Czech Liga Pro, and weekend internationals). Cadence is tuned for fast settlement: hot poller runs every 0.5s, with per-path 429 backoff so the WAF stays happy.

Caesars player props (deep events) re-enabled via dedicated sidecar

2026-05-18
sourcecaesars

The Caesars deep-events ingest path was a no-op in production for several weeks because the collector image did not ship with the browser binary required to resolve their AWS WAF challenge. That work moved to a new parlayapi-sidecar-caesars-deep container that runs the public lobby and event pages in an anonymous headless browser. Parsed prop tuples flow back through a bounded Redis stream and into buffers.add_props. Caesars player props for NFL / NBA / MLB / NHL are back on the board.

Closing-line table bloat fixed: ~5x faster CLV lookups

2026-05-18
fixperf

The prop_closing_lines archive table was carrying ~10x its real unique-key cardinality because the archival writer's ON CONFLICT clause had no unique constraint to fire against; every hourly cleanup pass appended a fresh row per natural key. A three-phase migration (online-safe natural-key index, batched window-function dedup, unique-constraint attach) plus a writer flip to ON CONFLICT (...) DO UPDATE ... WHERE snapshot_time > ... brings the table down to its real cardinality and changes its steady-state growth from ~50k rows/cleanup to near zero. Expected impact: ~5x faster p50 on the /v1/clv/* closing-line lookup path, ~9 GB freed.

parlayapi-mcp 0.2: keyless live previews, source quality, and OpenClaw install path

2026-05-16
mcpagents

The public MCP server now supports no-key discovery tools for pricing, live sports, live search, the /live best-line preview, source quality, and per-book coverage gates. Paid odds tools still require an explicit API key. The package accepts both PARLAYAPI_KEY and PARLAY_API_KEY, and the MCP landing page now includes OpenClaw setup commands.

Removed per-second rate limits on all paid tiers

2026-05-13
policy

Every paid tier (Starter through Scale) now has no documented rate limit. Burst at any rate your client wants. You are metered on monthly credits, not per-second throughput. Free trial keeps a 60 req/s cap purely for anti-abuse during evaluation. Pricing pages updated to reflect this.

parlay-api.com migrated off Cloudflare for the /v1/* path

2026-05-13
infra

Cloudflare's free-tier DDoS protection was flagging /v1/sports zone-wide when our own internal probes burst at it. We moved the API ingress to a direct path with no CF in the request flow. No URL change for customers. Same hostname, same endpoints, same auth.

See the post-mortem on Reddit if you care about the root cause.

New API hostname: api.parlay-api.com (recommended for trading bots and high-volume callers)

2026-05-13
infraaction recommended

If your client averages above ~30 requests per minute, switch your base URL from https://parlay-api.com to https://api.parlay-api.com. Same origin, same auth, same endpoints, but the request never touches Cloudflare's edge protections.

Iter-75 batch deploy: parlay fuzzy SGP, utility calculators, middles finder, sandbox completeness

2026-05-13
featureperfdocs

Comprehensive restart-batch deploy from the autonomous-test review loop. 11 fixes + 5 new endpoints, all shipped via zero-downtime rolling worker restart.

See the iter-75 summary doc for the full cumulative tally of the 89 fixes shipped during this loop (iter 017 → 073).

Kalshi crypto prediction markets: BTC / ETH / SOL with historical replay

2026-05-13
featuresource

Two new endpoints expose Kalshi crypto prediction-market prices, separated from the sports prediction-market surface because these markets trade 24/7 and have crypto-specific fields (price-ladder strikes, hourly resolution windows, no team / kickoff).

Filter by market_type: direction_15m, direction_1h, direction_daily, price_at_or_above, price_range, or all. Direction-binary markets (the headline "will BTC be higher in 15 min?" product) are surfaced when Kalshi lists them; the always-on coverage right now is Kalshi's hourly price ladders (KXBTC and KXBTCD families, $50 strike increments).

Behind the scenes: new crypto_market_snapshots table, new kalshi_crypto_poller collector task that discovers open markets every 5 min and polls each every 5 s. Historical retention matches everything else on the platform (append-only snapshot table).

WebSocket docs suite: 7 new pages + rewritten reference

2026-05-13
docsfeature

Full WebSocket documentation overhaul. The main reference at /docs/websocket is rewritten to match deployed reality (Business+ tier, push_mode coalesce envelope, three accepted auth forms, all four URL aliases). Seven new sub-pages cover the use cases customers actually have:

Migration guide page (/from-the-odds-api) + OG images for social shares

2026-05-07
featuredocs

New /from-the-odds-api page: one-line code diff (you change a base URL, your code keeps working), endpoint compatibility table, sport-key reference, bookmaker key superset list, pricing comparison, honest "what to know" section. Aliased at /from-toa and /migrate-from-the-odds-api. Both /vs-toa and the migration page now ship 1200x630 OG images so Twitter/LinkedIn shares render properly.

Also synced /compare/odds-api with the latest /vs-toa numbers (was stuck at "22 sources vs 7," now correctly shows 26+).

parlayapi-mcp: standalone MCP server (8 tools, native Claude Desktop integration)

2026-05-07
feature

Drop-in MCP server installable via uvx parlayapi-mcp or pip install parlayapi-mcp. Eight tools: signup (auth-less, returns API key + magic-link), checkout-link (Stripe upgrade URL), magic-link (passwordless login), list_sports, get_odds, get_props, best_line, account_info. Configure in claude_desktop_config.json or Cursor's .cursor/mcp.json with one block. Wheel + sdist build clean, ready for PyPI.

Agent-friendly signup endpoints: /v1/agent/signup, /v1/agent/magic-link, /v1/agent/checkout-link

2026-05-07
feature

JSON-only signup that returns api_key plus a magic-link claim URL plus a Stripe checkout URL plus an instructions_for_agent string an LLM can relay to the user verbatim. Idempotent on email (existing accounts return only the login URL, never leak the api_key). Uses an auto-generated random password the user never sees; they access via magic links until they choose to set one. Rate-limited 5/IP/hour.

Designed so a Claude/GPT agent helping a user "build a betting bot with ParlayAPI" can complete signup in a single HTTP call, no form-fill, no email-verify gate before the first request.

Magic-link login (/auth/magic?sid=X) - passwordless dashboard access

2026-05-07
feature

New route that consumes a server-issued session token from the URL, sets the cookie, redirects to the dashboard. Used by the agent-signup flow (claim URL is a magic link) and available standalone via /v1/agent/magic-link. Optional checkout_tier query param chains the redirect into Stripe Checkout for one-click upgrade.

baseball_mlb endpoint: three bug fixes from one Reddit DM

2026-05-06
fix

Pinnacle and Bovada placeholder events: daily aggregate markets ("Home Runs (13 Games)" vs "Away Runs (13 Games)") were stored as fake events under baseball_mlb. Now filtered via SQL denylist on team-name patterns.

335,338 futures props leaking into game-prop responses: the include_futures param on get_props() was declared but never applied in SQL. Underdog and FanDuel ingest season-long futures (Aaron Judge total HR for season, etc.) with empty home_team/away_team. Default is now strict; opt back in via ?include_futures=true.

DraftKings phantom duplicate events: DK writes team names as "WAS Nationals" / "ARI Diamondbacks" (3-letter prefix + last word) and stores game_date in ET-local while every other US book uses UTC. Same matchup hashed to two different event_ids, surfaced as duplicate API events. Fixed via _resolve_event_id() that normalizes via the existing alias map and tries +/-1 day fallback before creating a new event. Verified live: 15-game slate, 0 duplicates, every game merged across 6-7 books.

Operational: nightly Postgres backups, Docker auto-prune, watchdog rescue

2026-05-06
fix

Automated nightly Postgres backups (atomic dump, gzip, 7-day rotation, with an off-box copy when available), a weekly Docker prune of dangling images and build cache, and a repaired watchdog that had been failing silently for weeks. Also added restart: unless-stopped to the postgres / redis / api containers so reboots don't take half the stack down.

MCP server published, AI-agent discovery surfaces shipped

2026-05-01
featuredocs

Shipped a stand-alone MCP server (pip install parlay-api-mcp) with 10 tools wrapping the API. Repo: github.com/JacobiusMakes/parlay-api-mcp. Public manifest at /mcp/manifest.json with copy-paste config for Claude Code, Cursor, Continue, Devin.

Also added /llms.txt, /llms-full.txt, /agents.json, /.well-known/ai-plugin.json for AI-agent discovery. Updated /sitemap.xml to auto-include blog and compare slugs. /robots.txt now explicitly allows GPTBot, ClaudeBot, anthropic-ai, PerplexityBot, Google-Extended.

Public no-auth try-it endpoint

2026-05-01
feature

New /v1/try/{sport_key}/odds returns live moneyline data with no API key. Capped at 60 reqs/hour per IP via Redis, restricted to MLB, NBA, NFL, NHL, EPL, UFC. Landing page got a "Try it now" button that hits this endpoint inline.

Historical archive coverage page (1.156M rows, 263 sports, 17 sources)

2026-05-01
featuresource

New /historical-coverage public page rendering live coverage stats from /v1/historical/coverage (also public, no auth). Headline numbers: 1.156M rows, 263 sport_keys, 17 distinct sources, 99.6% score coverage, 267,173 games with 2+ sources, 137,200 with 5+ sources.

Added draftkings_espn as a second free historical source for US sports (NFL, NBA, MLB, NHL, NCAAF, NCAAB, WNBA, MLS) via the ESPN public scoreboard + summary endpoints. Independent of our live Pinnacle snapshot, so backtesters can cross-reference.

Soccer historical_odds gap closed (28 days, +122k rows)

2026-05-01
fixsource

Refreshed football-data.co.uk CSVs across all 37 leagues. Max game_date moved from 2026-04-03 to 2026-04-30 across soccer_* keys. New sources captured that weren't in the archive before: betmgm, pinnacle_close, bet365_close, betfair_exchange_close. Now refreshed weekly Tuesday 11:00 UTC.

Daily Pinnacle snapshot to historical_odds

2026-05-01
featuresource

New cron at 10:00 UTC daily promotes our live odds_snapshots (Pinnacle game-line moneylines across 200+ sport_keys) into historical_odds with both opening-line proxy (pinnacle_open) and closing-line proxy (pinnacle). Forward-going US-sport archive that grows automatically.

Welcome email on signup with quickstart code

2026-05-01
feature

Every new signup now gets a same-second email with their actual API key embedded plus a 4-line curl quickstart. Solves the "dashboard might be flaky, did I get a real key?" pause many users had.

SMTP failover: Brevo primary, Gmail backup

2026-05-01
fix

Hit Gmail's 500/day cap during a batch send. Switched primary outbound SMTP to Brevo (300/day free + auto-fallback to Gmail if Brevo fails). Tested via persistent SMTP+STARTTLS connection with 600ms pacing. No more truncated batch sends.

CRITICAL fix: 227 users had broken API keys, all rotated + apology bonus credits

2026-05-01
fix

From 2026-04-17 onward, three of our key-creation paths stopped writing key_plaintext; the dashboard was rendering the first 8 chars of the bcrypt hash instead of the actual key. Any code using what users saw on the dashboard returned 401. Fix: write key_plaintext on create, render plaintext on read, bulk-rotate every affected user's key, send apology email with the new key + 2,000 bonus credits each. 8 of the 227 affected users started using their new keys within 4 hours of the email landing.

Affiliate program: 25% recurring

2026-04-30
feature

Affiliates earn 25% of every paid month from anyone they refer, recurring as long as that user stays paid. Eligible tiers: Starter, Pro, Business. Payouts processed monthly on the 1st via Stripe Connect.

Real /docs page (curated, separate from Swagger)

2026-04-29
docs

Replaced the Swagger-only docs experience with a curated long-form quickstart at /docs, with full reference still at /docs/swagger and ReDoc at /redoc. Lots of code examples in cURL, Python, JavaScript.

Public live-stats dashboard

2026-04-29
feature

New /live-stats page shows our actual live throughput, source health, and freshness in real time. No "trust us" required. Useful as a status surface while we build a proper status page.

Outbound webhooks (Pro+)

2026-04-29
feature

Pro+ users can configure webhook endpoints that receive HMAC-SHA256-signed POSTs when arbs, +EV bets, or line moves cross thresholds you set. Stripe-style signing scheme.

Umami self-hosted analytics live at /_analytics

2026-04-29
feature

Self-hosted Umami via /_analytics reverse proxy. No third-party scripts. Public dashboards stay private; we get acquisition / behavior data internally.

April 2026

WebSocket streaming (Pro+)

2026-04-25
feature

wss://parlay-api.com/ws/odds/{sport_key} and wss://parlay-api.com/ws/live/{sport_key} push initial snapshot followed by change-detected diff frames. Sub-second updates. Auth: ?apiKey= on the connect URL.

Drop-in compatibility for the-odds-api.com (/v4 alias)

2026-04-22
feature

If your code already targets the-odds-api's /v4/* URL pattern, change the host. Our /v4/* endpoints alias to /v1/* with the same JSON shape.

Prediction-market endpoints: Kalshi + Polymarket

2026-04-20
featuresource

/v1/prediction-markets/{sport_key} returns Kalshi event-contract and Polymarket prices in standard American/decimal odds format, normalized to the same schema as sportsbook prices. Cross-reference for prediction-market vs sportsbook arbitrage.

21+ source aggregation: DraftKings, FanDuel, BetMGM, Caesars, BetRivers, Fanatics, Hard Rock, Pinnacle, Bet365, Bovada, BetWay, Betr, Fliff, ParlayPlay, PrizePicks, Underdog, Sleeper, Pick6, Novig, ProphetX, Kalshi, Polymarket

2026-04-17
source

Public launch with 21 live sources covering moneyline / spread / total / player props / DFS / exchanges / prediction markets across 38+ sports. Updated every 30-60 seconds.

Initial release

2026-04-15
feature

ParlayAPI v1.0. Free tier (1,000 req/mo), Starter $19, Pro $99, Business $499, Enterprise $2,499. REST + (later) WebSocket. Full pricing →