PULSE API
Programmatic access to live Whatnot market intelligence · Base URL https://pulsemetric.live
402 pro_plan_required. Beyond those the free layer is pages, not endpoints.
The live rankings carry the top 40 categories by live viewers, plus the live viewer total
across every category, counted across the rooms Whatnot's feeds list live in each category. Every category page carries that lane's live viewers, typical
room size, best hour to go live and how crowded it is. Any tracked seller's own public numbers are
open too: peak viewers, average audience while live, viewer-minutes, shows tracked and their strongest
hour. History, momentum, rivals, win-rate and the ranked live-show list are Pro on the page and on the
API alike.1. Versioning & stability
/api/v1/* is the supported programmatic surface and follows an
additive-only stability promise: fields are never removed, renamed, or re-typed
within v1. New fields may appear at any time, so parse tolerantly. The unversioned
/api/* paths serve the web dashboard and behave identically today, but only
/api/v1 carries the compatibility promise. GET /api/v1 returns a
small JSON index pointing back to this page.
2. Authentication
Pro subscribers get an API key (wn_live_…), shown once at checkout and
emailed. Present it one of these ways:
- Recommended:
Authorization: Bearer wn_live_… X-API-Key: wn_live_…?key=wn_live_…, no longer accepted (removed 2026-09-02). Query strings land in proxy logs,Refererheaders and browser history, so a key sent that way should be treated as exposed. A request carrying?key=now gets401 {"error":"api_key_in_query_string"}naming the headers above — refused loudly rather than quietly answered as an anonymous caller. Rotate any key you have used in a URL.
curl -H "Authorization: Bearer wn_live_xxxxxxxx" \
"https://pulsemetric.live/api/v1/top-shows?slug=sports_cards"
No key → you are an anonymous caller: the public
endpoints below work, and every other endpoint returns 402 pro_plan_required
(the body carries upgrade_url). Endpoints are public or Pro; there is no
anonymous teaser tier that serves partial market data. A key that is presented but not
recognized (e.g. rotated away) returns
401 invalid_api_key, so always use the newest key from your last rotation.
Lost it? Email [email protected].
3. Rate limits
- 120 requests / 60 s per IP (all
/api/*traffic). - 240 requests / 60 s per API key (on top of the per-IP bucket).
Over a limit you get 429 with a Retry-After header and body
{"error":"rate_limited","scope":"ip"|"api_key","retry_after":<seconds>}.
Back off for retry_after seconds.
4. Polling guidance
Market data updates once per collection sweep, about once an hour
(the cadence flexes with load). Polling faster than that returns the same data and burns
your budget. GET /api/me returns poll_after_ms, the server's live
back-pressure hint; well-behaved clients wait at least that long between polls.
Most public per-sweep endpoints also carry Cache-Control headers you can honor.
5. Errors
Errors are JSON with a snake_case error code and usually a human-readable
message:
{"error": "seller_not_found", "name": "nosuchseller", "message": "No data for that seller handle."}
| Status | Code | Meaning |
|---|---|---|
| 400 | missing_param, query_too_short, invalid_json… | Bad or missing input; the message names the parameter. |
| 401 | invalid_api_key | A key was presented but not recognized (rotated/typo). |
| 402 | pro_plan_required | Pro endpoint, free caller. Carries upgrade_url + docs_url. |
| 404 | not_found, seller_not_found, unknown_category… | No such endpoint / entity. |
| 429 | rate_limited | Over a rate limit; honor Retry-After. |
| 500 | internal_error | Our bug. Retry later, and email support if it keeps happening. |
| 503 | busy / billing_not_configured | Temporarily unavailable; retry with backoff. |
6. Endpoints (GET)
Two tiers: public no key needed ·
pro requires a Pro API key (else 402).
All paths below also exist under /api/v1/….
Market-wide
| Endpoint | Tier | Returns |
|---|---|---|
/api/health | public | Liveness + snapshot/sweep counts. |
/api/health/deep | public | Ops health: sweep age, last-sweep signals, DB-writable. |
/api/me | public | Caller's tier, account state, and poll_after_ms. |
/api/taxonomy | public | Full category tree (near-static; cached 1 h). |
/api/market-summary | public | Sweep-wide aggregates only: categories, viewers, snapshots, days_tracked. |
/api/pulse | pro | Market-wide viewer sparkline + sweep-over-sweep delta. |
/api/hot-categories | pro | Market heat by category, every lane. |
/api/saturation | pro | Shows-vs-audience saturation index per category. |
/api/category-demand | pro | Items/day sales throughput by category lane. |
/api/category/<slug> | pro | Live on-demand snapshot for any category slug. |
/api/insights | pro | Editorial market insights (unusual audiences, new highs, movers). |
/api/top-shows?slug= | pro | Biggest live audiences now (optionally per category). |
/api/breakout-sellers | pro | Sellers commanding the most audience right now. |
/api/momentum?slug= | pro | Shows with climbing audiences (repeatable slug scopes lanes). |
/api/breaking-out | pro | Shows about to blow up + heating categories. |
/api/category-trends | pro | Category-level momentum trends. |
/api/format-intel?slug= | pro | Show-format leaderboard (what format wins a lane). |
/api/demand-index | pro | Cross-category demand index. |
/api/stats | pro | Dataset meta (snapshots, sweeps, coverage). |
/api/history?slug= | pro | Per-sweep time series for one category. |
/api/best-time?slug= | pro | Best time to go live (by hour + weekday grid). |
/api/go-live-score?slug= | pro | Right-now "should I go live" score. |
/api/reach | pro | Audience reach by hour/day. |
/api/market-share?slug= | pro | Seller market share within a category. |
/api/algo-boosted | pro | Shows the feed ranks above their audience (algorithm favor). |
/api/upcoming | pro | Upcoming scheduled shows from tracked sellers. |
Per-seller
| Endpoint | Tier | Returns |
|---|---|---|
/api/seller-teaser?name= | pro | One personalized stake: top rival, lane, best window, peak. |
/api/seller/<handle>/recap | public | Latest post-show recap as JSON. |
/api/seller/<handle>/scoreboard | public | Personal bests + streak; win_rate_trend is Pro-only. |
/api/sellers?q= | pro | Seller search (min 2 chars) ranked by reach. |
/api/seller?name= | pro | One seller's drill-down: summary, audience history, shows. |
/api/my-report?name= | pro | The full "My Shows" report (never empty for a real handle). |
/api/seller-stats?name= | pro | Latest enriched profile stats (followers, sold count, rating). |
/api/seller-velocity | pro | Fastest-growing tracked sellers. |
/api/seller-rivals?name= | pro | Threat-ranked same-lane rivals + head-to-head win rates. |
/api/seller-cadence?name= | pro | Show cadence/schedule pattern analysis. |
/api/seller-reach?name= | pro | A seller's audience reach profile. |
Unknown-seller behavior
These are intentional and stable, so code against them. They describe an
authenticated call; without a Pro key the Pro rows below answer
402 before they ever look the handle up:
/api/seller?name=…,/api/seller-cadence,/api/seller-reach→ 404{"error":"seller_not_found"}/api/seller-stats?name=…→ 200{}(empty object)/api/seller/<handle>/recap→ 200{"recap": null}/api/seller-teaser?name=…→ 200{"found": false, …}(still carries a market-wide best window)
7. Support
Questions, key re-issues, or a field you wish existed: [email protected].