{"version":"0.1","count":50,"limit":50,"entries":[{"date":"2026-05-19","title":"Historical match coverage endpoint + per-source hint header","tags":["feature","docs"],"tag_labels":["api","historical","transparency"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"/v1/meta/api-key-check now exposes Stripe subscription state + last-request","tags":["feature","fix"],"tag_labels":["api","billing"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"The-odds-api v4 alias now works for WebSocket, not just REST","tags":["fix","feature"],"tag_labels":["api","compat"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"/dashboard/billing 500 fixed (4 customer reports)","tags":["fix"],"tag_labels":["dashboard"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"/mesh: live public observability dashboard","tags":["feature","docs"],"tag_labels":["dashboard","transparency"],"summary":"New page at /mesh polls /v1/meta/mesh-status, /v1/meta/source-stack, and /v1/meta/isp-reachability every 30 seconds and renders the live state of the residential ingest layer: which nodes are contributing, what sources, which books we track with their protection stacks, and per-ISP reachability. No auth.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"/v1/meta/source-stack: per-book ingest transparency","tags":["feature","docs"],"tag_labels":["api","transparency"],"summary":"For every upstream sportsbook we track (DK, FD, Caesars, BetMGM, Pinnacle, Novig, PrizePicks, bet365, Unibet US, Winamax, Sporttrade, Bwin, Pick6, Bovada, plus FDJ ParionsSport as a documented decommissioned brand) the endpoint returns the observed bot-protection vendor (Akamai, Cloudflare, AWS WAF, Imperva, DataDome), our routing strategy (residential_mesh / browser_session / passthrough), typical refresh seconds, regions, market coverage, and known_limitations. Public, no auth, 1h cache.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"/v1/meta/mesh-status: live per-node ingest telemetry","tags":["feature","docs"],"tag_labels":["api","transparency"],"summary":"For every node that has posted to /v1/node/ingest since the worker booted: posts in last hour and last 24h, bytes uploaded, distinct source names contributed, status bucket (active / active_recent / stalled_minor / stalled_major / offline). Plus an aggregate roll-up at the top: nodes_active, nodes_offline, total_posts_24h, distinct_sources_covered. Source-of-truth transparency for the residential mesh.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"/v1/meta/isp-reachability: per-ISP reachability snapshot","tags":["feature","docs"],"tag_labels":["api","transparency"],"summary":"For each of nine major US residential and business ISPs (Spectrum, Comcast, Verizon FiOS, AT&T, Cox, CenturyLink, Frontier, T-Mobile Home Internet, Starlink) returns observed request counts in the past 24h, last-seen timestamp, status bucket, and documented filter history with workarounds. Also classifies the visitor's own IP. Public, no auth. Lets a customer whose ISP is on the filter list verify whether other customers on the same ISP are reaching us right now.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"Multi-node residential ingest mesh: DK + Pixel hot-reload","tags":["feature","source"],"tag_labels":["infrastructure","draftkings"],"summary":"DraftKings eventgroups (MLB, NBA, NFL, NHL) are now in the mesh rotation. The Pixel watchdog refreshes its config every five minutes from the tailnet bridge, so adding a new source URL to the canonical config propagates to running nodes without a manual re-install. GH Actions egress also fetches DK alongside Bovada for ASN diversity.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"Daily closing-line CSV downloads","tags":["feature"],"tag_labels":["api","historical"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"Source-quality timeline: /v1/status/history + /status/history (HTML)","tags":["feature","docs"],"tag_labels":["api","transparency"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"Probable starting pitchers now on /v1/sports/baseball_mlb/odds","tags":["feature","source"],"tag_labels":["api","mlb"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"commence_time on /v1/sports/{sport}/ev","tags":["fix"],"tag_labels":["fix"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"WebSocket reference clients + reconnect cookbook","tags":["docs","feature"],"tag_labels":["docs","websocket"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"ProphetX + Sporttrade SLA reclassified (exchange_slow)","tags":["fix","docs"],"tag_labels":["fix","sla"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"prop_closing_lines storage reclaimed (17 GB to 1.36 GB)","tags":["fix","feature"],"tag_labels":["fix","perf"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"Public SLA visibility: /v1/meta/per-book-sla + sla_by_source on /v1/status","tags":["feature","docs"],"tag_labels":["api","transparency"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-19","title":"WebSocket heartbeat now carries upstream freshness","tags":["feature"],"tag_labels":["websocket"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-19"},{"date":"2026-05-18","title":"Table tennis added as a first-class sport (Bovada coverage)","tags":["feature","source"],"tag_labels":["sport","bovada"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-18"},{"date":"2026-05-18","title":"Multi-node ingest mesh: residential + cloud-region nodes feeding the collector","tags":["feature","infra"],"tag_labels":["freshness","infra"],"summary":"The collector now accepts authenticated POSTs from a fleet of small ingest nodes (residential Pixel, GitHub Actions runners, $4/mo DigitalOcean droplets in NYC1/SFO3/AMS3) via POST /v1/node/ingest. Nodes coordinate a round-robin slot rotation through Redis so they don't double-fetch; effective freshness for shared targets like Bovada is the base interval divided by the live node count. New /dashboard/admin/coordinator-stats surfaces per-node heartbeat age, last-fetch timestamps, slot-claim share, and active-slot count for the operator. Customer-visible effect: faster updates on books that geofence Hetzner's egress IP.","url":"https://parlay-api.com/changelog#2026-05-18"},{"date":"2026-05-18","title":"Caesars player props (deep events) re-enabled via dedicated sidecar","tags":["feature","source"],"tag_labels":["source","caesars"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-18"},{"date":"2026-05-18","title":"Closing-line table bloat fixed: ~5x faster CLV lookups","tags":["fix","feature"],"tag_labels":["fix","perf"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-18"},{"date":"2026-05-16","title":"parlayapi-mcp 0.2: keyless live previews, source quality, and OpenClaw install path","tags":["feature","docs"],"tag_labels":["mcp","agents"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-16"},{"date":"2026-05-13","title":"Removed per-second rate limits on all paid tiers","tags":["feature"],"tag_labels":["policy"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-13"},{"date":"2026-05-13","title":"parlay-api.com migrated off Cloudflare for the /v1/* path","tags":["infra"],"tag_labels":["infra"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-13"},{"date":"2026-05-13","title":"New API hostname: api.parlay-api.com (recommended for trading bots and high-volume callers)","tags":["infra","breaking"],"tag_labels":["infra","action recommended"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-13"},{"date":"2026-05-13","title":"Iter-75 batch deploy: parlay fuzzy SGP, utility calculators, middles finder, sandbox completeness","tags":["feature","perf","docs"],"tag_labels":["feature","perf","docs"],"summary":"Comprehensive restart-batch deploy from the autonomous-test review loop. 11 fixes + 5 new endpoints, all shipped via zero-downtime rolling worker restart.","url":"https://parlay-api.com/changelog#2026-05-13"},{"date":"2026-05-13","title":"Kalshi crypto prediction markets: BTC / ETH / SOL with historical replay","tags":["feature","source"],"tag_labels":["feature","source"],"summary":"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).","url":"https://parlay-api.com/changelog#2026-05-13"},{"date":"2026-05-13","title":"WebSocket docs suite: 7 new pages + rewritten reference","tags":["docs","feature"],"tag_labels":["docs","feature"],"summary":"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:","url":"https://parlay-api.com/changelog#2026-05-13"},{"date":"2026-05-07","title":"Migration guide page (/from-the-odds-api) + OG images for social shares","tags":["feature","docs"],"tag_labels":["feature","docs"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-07"},{"date":"2026-05-07","title":"parlayapi-mcp: standalone MCP server (8 tools, native Claude Desktop integration)","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-07"},{"date":"2026-05-07","title":"Agent-friendly signup endpoints: /v1/agent/signup, /v1/agent/magic-link, /v1/agent/checkout-link","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-07"},{"date":"2026-05-07","title":"Magic-link login (/auth/magic?sid=X) - passwordless dashboard access","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-07"},{"date":"2026-05-06","title":"PrizePicks mobile/WebView capture: fully autonomous, 2,800+ props per 15-min run","tags":["feature","source"],"tag_labels":["feature","source"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-06"},{"date":"2026-05-06","title":"baseball_mlb endpoint: three bug fixes from one Reddit DM","tags":["fix"],"tag_labels":["fix"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-06"},{"date":"2026-05-06","title":"Operational: nightly Postgres backups, Docker auto-prune, watchdog rescue","tags":["fix"],"tag_labels":["fix"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-06"},{"date":"2026-05-01","title":"MCP server published, AI-agent discovery surfaces shipped","tags":["feature","docs"],"tag_labels":["feature","docs"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-01"},{"date":"2026-05-01","title":"Public no-auth try-it endpoint","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-01"},{"date":"2026-05-01","title":"Historical archive coverage page (1.156M rows, 263 sports, 17 sources)","tags":["feature","source"],"tag_labels":["feature","source"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-01"},{"date":"2026-05-01","title":"Soccer historical_odds gap closed (28 days, +122k rows)","tags":["fix","source"],"tag_labels":["fix","source"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-01"},{"date":"2026-05-01","title":"Daily Pinnacle snapshot to historical_odds","tags":["feature","source"],"tag_labels":["feature","source"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-01"},{"date":"2026-05-01","title":"Welcome email on signup with quickstart code","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-01"},{"date":"2026-05-01","title":"SMTP failover: Brevo primary, Gmail backup","tags":["fix"],"tag_labels":["fix"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-01"},{"date":"2026-05-01","title":"CRITICAL fix: 227 users had broken API keys, all rotated + apology bonus credits","tags":["fix"],"tag_labels":["fix"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-05-01"},{"date":"2026-04-30","title":"Affiliate program: 25% recurring","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-04-30"},{"date":"2026-04-29","title":"Real /docs page (curated, separate from Swagger)","tags":["docs"],"tag_labels":["docs"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-04-29"},{"date":"2026-04-29","title":"Public live-stats dashboard","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-04-29"},{"date":"2026-04-29","title":"Outbound webhooks (Pro+)","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-04-29"},{"date":"2026-04-29","title":"Umami self-hosted analytics live at /_analytics","tags":["feature"],"tag_labels":["feature"],"summary":"Self-hosted Umami via /_analytics reverse proxy. No third-party scripts. Public dashboards stay private; we get acquisition / behavior data internally.","url":"https://parlay-api.com/changelog#2026-04-29"},{"date":"2026-04-25","title":"WebSocket streaming (Pro+)","tags":["feature"],"tag_labels":["feature"],"summary":"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.","url":"https://parlay-api.com/changelog#2026-04-25"}],"related":{"html_url":"/changelog","rss_url":"/changelog.rss","api_info_url":"/v1/meta/api-info"},"note":"Newest entries first. Source-of-truth is static/changelog.html (human-edited, git-versioned). The HTML, RSS, and JSON surfaces are parsed from the same file and guaranteed in sync."}