Unusual Whales API - Ticker Flow endpoints
Layer mapping: L1 LOAD-BEARING. Five endpoints under
TickerController that surface per-ticker flow at different cuts:
recent feed, per-expiry rollup, per-strike rollup, per-strike
intraday timeseries, and the per-ticker flow-alerts feed.
For SPY hunter, these are the SPY-scoped equivalents of the
cross-market endpoints in uw-api-option-trade and uw-api-tide.
They live at /api/stock/SPY/... instead of the controllers covered
elsewhere.
1. Endpoint matrix
| # | Path | Purpose |
|---|---|---|
| 1 | GET /api/stock/{ticker}/flow-recent | Recent flow records (rolling feed) |
| 2 | GET /api/stock/{ticker}/flow-alerts | Per-ticker flow-alerts feed (SAME as uw-api-option-trade /flow-alerts filtered to one ticker) |
| 3 | GET /api/stock/{ticker}/flow-per-expiry | Flow rolled up by expiry |
| 4 | GET /api/stock/{ticker}/flow-per-strike | Flow rolled up by strike (daily) |
| 5 | GET /api/stock/{ticker}/flow-per-strike-intraday | Flow per strike at minute granularity |
2. Base contract
| Property | Value |
|---|---|
| Base URL | https://api.unusualwhales.com |
| Auth | Authorization: Bearer <token> header |
| Response envelope | { "data": [...] } |
| Status codes | 200, 422, 500 |
| Numeric format | Strings - coerce to float |
3. GET /api/stock/{ticker}/flow-recent
Recent flow records for a ticker (rolling feed).
Query parameters (inferred from sibling endpoints): date,
limit, newer_than, older_than, min_premium.
Use: baseline per-ticker feed. For SPY, lower-priority than the more-aggregated /per-strike endpoints because per-trade SPY flow is huge.
4. GET /api/stock/{ticker}/flow-alerts
Per-ticker version of the uw-api-option-trade /flow-alerts
feed. Same record shape (9 rule names, cluster aggregation), just
pre-filtered to one ticker.
Use: for SPY hunter, prefer this over the global
/api/option-trades/flow-alerts?ticker_symbol=SPY - identical
results, simpler URL.
5. GET /api/stock/{ticker}/flow-per-expiry
Flow rolled up by expiry.
Query parameters (inferred): date.
Response per row (inferred): expiry, call_premium, put_premium,
call_volume, put_volume, side-split fields.
Use (L1): “what expiries are getting the flow today on SPY?“. 0DTE typically dominates SPY flow - quantify that dominance.
6. GET /api/stock/{ticker}/flow-per-strike
Flow rolled up by strike, daily summary.
Query parameters (inferred): date.
Response per row (likely same shape as #7 below, just one row per strike rather than per timestamp).
Use (L1): end-of-day positioning summary by strike.
7. GET /api/stock/{ticker}/flow-per-strike-intraday (LOAD-BEARING)
Flow per strike at minute granularity through the trading day. This is the load-bearing endpoint of the family.
Query parameters:
| Param | Type | Required | Default | Notes |
|---|---|---|---|---|
date | date | no | last trading date | - |
filter | enum | no | NetPremium | NetPremium, Volume, Trades |
Response per row:
| Field | Type | Description |
|---|---|---|
strike | decimal | Option strike |
ticker | string | Underlying |
timestamp | ISO 8601 | Minute timestamp |
date | date | Trading day |
call_premium, call_premium_ask_side, call_premium_bid_side | decimal | Call $ by aggressor side |
call_volume, call_volume_ask_side, call_volume_bid_side | int | Call contracts by side |
call_trades | int | Call trade count |
put_premium, put_premium_ask_side, put_premium_bid_side | decimal | Put $ by side |
put_volume, put_volume_ask_side, put_volume_bid_side | int | Put contracts by side |
put_trades | int | Put trade count |
Why it’s load-bearing. Per-strike, per-minute, with ASK/BID splits = the SPY hunter sees:
- Which strikes are getting flow right now (gamma walls forming in real time, not just yesterday’s static positioning).
- At which side (ask = aggressive buy, bid = aggressive sell).
- In calls vs puts (directional thesis).
Derived features:
| Feature | Definition |
|---|---|
spy_atm_strike_call_ask_premium_1m | Latest minute, ATM strike, call premium hitting ask |
spy_otm_call_ask_premium_5m_sum | 5-min rolling sum, OTM call ask-side $ |
spy_strike_with_max_net_premium | Strike currently leading the flow |
spy_pinning_strike_estimate | Strike with highest call+put activity (likely pin) |
The ask-side OTM call premium feature is the canonical contrarian fade target per 2026-05-22-uw-historical-findings: when this spikes, treat as fade signal, not confirmation.
8. Cross-endpoint workflow for SPY hunter
RTH every minute:
-> GET /api/stock/SPY/flow-per-strike-intraday?filter=NetPremium
(load-bearing - the primary minute-level feed)
-> GET /api/stock/SPY/flow-alerts?newer_than=...&max_dte=0&min_premium=10000
(the pre-classified cluster feed for SPY)
Session start:
-> GET /api/stock/SPY/flow-per-expiry
(which expiries dominate today)
-> GET /api/stock/SPY/flow-per-strike?date=T-1
(yesterday's end-of-day positioning by strike)
9. Nautilus integration shape
- Custom data classes:
UWFlowPerStrikeMinute,UWFlowAlertCluster,UWFlowPerExpiryDay. - Polling Actor:
UWTickerFlowActorpolls /flow-per-strike-intraday (every minute) + /flow-alerts (every 30s). - Signal Actor computes per-strike + per-side derived features.
10. Known gaps
- /flow-recent response schema not fully fetched - first fetch needs to confirm. Probably duplicates /api/option-contract/{id}/flow but at ticker scope.
- /flow-per-expiry and /flow-per-strike response schemas inferred from sibling shape.
- No streaming/WebSocket for any of these - polling only.
11. Source URLs
https://api.unusualwhales.com/docs/operations/PublicApi.TickerController.flow_alertshttps://api.unusualwhales.com/docs/operations/PublicApi.TickerController.flow_per_expiryhttps://api.unusualwhales.com/docs/operations/PublicApi.TickerController.flow_per_strikehttps://api.unusualwhales.com/docs/operations/PublicApi.TickerController.flow_per_strike_intradayhttps://api.unusualwhales.com/docs/operations/PublicApi.TickerController.flow_recent
cortana-north-star uw-api-option-trade uw-api-option-contract uw-api-gex-greeks uw-api-tide 2026-05-22-uw-historical-findings 2026-05-15-mk3-setup-hunter-architecture