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
support@parlay-api.com if you want a per-fix email digest.
May 2026
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.
- Headers:
x-ratelimit-limit now returns unlimited for paid tiers instead of a per-second number.
- Internal safety: a single key cannot exceed ~10,000 req/s sustained without contacting support to shard traffic. That ceiling is for runaway-retry-loop protection, not a tier feature. If a paid key hits it, the 429 response says exactly that.
- If you were throttling your client to stay under 500 req/s on Scale or 60 on Pro, you can remove that pacing.
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.
- DDoS L7, Bot Fight Mode, BIC, and per-IP edge rate-limit no longer touch /v1/*
- The previous "new hostname api.parlay-api.com" recommendation is moot: parlay-api.com itself is now CF-free. Both hostnames work identically.
- Per-key app-layer rate limits also removed on paid tiers (see above)
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.
- Why: Cloudflare's DDoS L7 layer fires on per-IP bursts to
/v1/* and returns error code: 1027 for 10-30 min. Trader bots can hit this within an hour of normal use. The new hostname routes around Cloudflare entirely.
- Both hostnames keep working:
parlay-api.com still serves marketing, blog, docs, AND /v1/* for low-volume callers. api.parlay-api.com is the same API on a hostname with no CF bot/rate protections in the path. Switch only if you're seeing 1027 blocks.
- What to change: exactly one line.
BASE_URL = "https://api.parlay-api.com". Auth header, endpoints, response shape are unchanged. Valid Let's Encrypt cert, auto-renewing, HTTP/2.
- App-layer rate limits: as of 2026-05-13 (later in the day) we removed per-second rate limits from every paid tier. Free trial keeps a 60 req/s cap for anti-abuse. Burst at any rate, you're metered on monthly credits.
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.
- Parlay /v1/parlay/price:
line_tolerance body param (default 0, max 5) for fuzzy SGP across books that quote different lines. Every leg now returns lines_available: {point: {book: decimal_price}} so callers see alt-line options without a separate /odds call.
- Utility calculators (FREE, no credits): /v1/calc/kelly,
/v1/calc/hedge, /v1/calc/edge, /v1/calc/free-bet. Accept American (-110, +150) or decimal (1.91, 2.5) odds. Math is consistent with /v1/clv's no-vig pair formula.
- /v1/sports/{key}/middles (3 cr): cross-book spread/total middle finder.
min_gap + min_books filters.
- Sandbox completeness: 6 new sandbox endpoints (/arbitrage, /ev, /consensus, /futures, /scores, /events) so integrators can verify response-parsing for every major production endpoint without burning credits.
- /v1/pinnacle-coverage cached 5 min with stale-while-revalidate to 1 hr. Was hitting 20s cold-call timeouts under status-page polling.
- /live/api/search ?limit= param (default 25). Broad queries like q=mlb were timing out at trigram-index scan.
- /live/api/sparkline 500 → 200: SELECT/GROUP BY expression mismatch fixed.
- /v1/sports/{key}/line-movement empty-result envelope: was returning bare []. Now returns count + filters + structured note explaining no-movement vs no-coverage vs malformed event_id.
- /v1/usage ?by_endpoint=true: per-endpoint + per-group credit breakdown for the current period.
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).
GET /v1/prediction-markets/crypto/{asset}: latest snapshot of every open Kalshi market for the asset (btc, eth, sol). Returns yes/no bid+ask, mid-market implied probability, volume, open interest. 1 credit.
GET /v1/historical/prediction-markets/crypto/{asset}?from=&to=&market_ticker=: tick-by-tick replay. Every poll snapshot is preserved (~5 s cadence per market), so a one-hour replay against a single ticker returns ~720 rows. 2 credits.
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:
- /docs/websocket/quickstart · 60-second copy-paste in Node, Python, browser
- /docs/websocket/examples · Production-ready consumers in Node, Python (websockets + aiohttp), Go, Ruby, Java, PHP, C#, Elixir, Rust, plus React hook, Discord bot, Redis pubsub fan-out, Kafka bridge
- /docs/websocket/player-props · NBA / MLB / NHL / WNBA / NFL prop streaming, full market-key matrix, filter-by-player pattern
- /docs/websocket/edge-alerts · +EV alert system with Pinnacle-anchored no-vig math, Discord webhook delivery, stale-line guards, dedupe
- /docs/websocket/troubleshooting · Every close code with the fix, curl smoke test, proxy / VPN / serverless gotchas
- /docs/websocket/sse · Server-Sent Events deep-dive — same feed, plain HTTP, browser
EventSource
- /docs/websocket/migration · Side-by-side mapping from OddsJam / OpticOdds / SharpAPI / The Odds API
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.
PrizePicks mobile/WebView capture: fully autonomous, 2,800+ props per 15-min run
2026-05-06
featuresource
End-to-end PrizePicks projections capture without manual taps. The Pixel runs PrizePicks 24/7; a launchd job on the Mac mini fires every 15 min, runs am start to keep the WebView refreshed (its background traffic exercises PerimeterX, Cloudflare, and DataDome challenges so cookies rotate cleanly), pulls the WebView cookie DB via root, replays cookies against api.prizepicks.com/projections, posts to a new prizepicks_mobile source-webhook translator. NBA + NBA2H sub-league markets land in prop_snapshots.
Failed dead-ends (documented in scripts/README_prizepicks_mobile.md): Playwright + stealth lost to PerimeterX even with a real Chrome binary; undetected-chromedriver is incompatible with Python 3.13; ADB tap at hardcoded coordinates lands in Pixel 4a's Quick Settings gesture zone instead of the WebView; am force-stop + monkey -p relaunch corrupts the WebView until reboot.
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
Three launchd jobs added/repaired. com.parlayapi.pgdump dumps Postgres nightly at 3:15 AM (atomic .tmp + rename, gzip, 7-day rotation, auto-detects external drive when plugged in). com.parlayapi.docker-prune kills dangling images and build cache weekly. com.parlayapi.watchdog was failing silently for weeks (status 126: macOS TCC blocks launchd-spawned bash from reading scripts in ~/Desktop/) - moved script to ~/bin/, watchdog is now actually watching again. Also added restart: unless-stopped to postgres / redis / api containers in the server stack so reboots don't take half the system 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 →