Options Flow Minute History API - Per-Minute Buckets | FlashAlpha
  1. Trade History

Options Flow Minute History API

Minute option-flow buckets rolled up by underlying, newest first. Each bucket carries buy/sell/mid/net volume, trade count, biggest trade, VWAP, and high/low.

Endpoint

GET /v1/flow/options/{symbol}/history
Auth required (X-Api-Key) Rate Limited: Yes Plan: Alpha+

Parameters

Name In Type Required Default Description
symbol path string required - Underlying symbol
minutes query integer 60 Window size, clamped to 1..10080. Non-numeric values return a 400 problem-details body.
expiry query date - Filter to a single expiration cycle, yyyy-MM-dd. Omit to include all expiries. Invalid values return 400 invalid_expiry. An expiry with no data returns an empty result, not an error.

Request

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://lab.flashalpha.com/v1/flow/options/SPY/history?minutes=120"
import requests

resp = requests.get(
    "https://lab.flashalpha.com/v1/flow/options/SPY/history",
    headers={"X-Api-Key": "YOUR_API_KEY"}
)
resp.raise_for_status()
data = resp.json()
print(f"{data['count']} buckets over {data['minutes']} minutes")
const resp = await fetch(
  "https://lab.flashalpha.com/v1/flow/options/SPY/history",
  { headers: { "X-Api-Key": "YOUR_API_KEY" } }
);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const data = await resp.json();
console.log(data.count + " buckets over " + data.minutes + " minutes");

Try it live

Runs on live market data and uses 1 request from your daily quota.

GET

Response

{
  "symbol": "SPY",
  "expiry": null,
  "minutes": 120,
  "count": 120,
  "lastBucketUtc": "2026-10-30T13:45:00Z",
  "staleSeconds": 50,
  "marketOpen": true,
  "stale": false,
  "error": null,
  "message": null,
  "buckets": [
    {
      "ts": "2026-10-30T13:45:00Z",
      "buyVolume": 525,
      "sellVolume": 310,
      "midVolume": 38,
      "netVolume": 215,
      "tradeCount": 171,
      "biggestTrade": 80,
      "vwap": 1.2874,
      "high": 19.03,
      "low": 0.01
    },
    {
      "ts": "2026-10-30T13:44:00Z",
      "buyVolume": 19342,
      "sellVolume": 13955,
      "midVolume": 2735,
      "netVolume": 5387,
      "tradeCount": 4747,
      "biggestTrade": 622,
      "vwap": 1.6554,
      "high": 117.1,
      "low": 0.01
    }
  ],
  "endpoint_version": "2026.09.30",
  "data_as_of": {
    "node": "fa4",
    "equity_feed": "2026-10-30T13:45:50.795Z",
    "equity_options_feed": "2026-10-30T13:45:50Z",
    "index_feed": "2026-10-30T13:45:50.127Z",
    "index_options_feed": "2026-10-30T13:45:47Z",
    "futures_feed": "2026-10-30T13:45:42.97Z",
    "futures_options_feed": "2026-10-30T13:45:43.095Z",
    "flow_feed": "2026-10-30T13:45:00Z",
    "oi_feed": "2026-10-29T20:00:00Z",
    "macro_feed": "2026-10-29T21:00:20Z"
  }
}

Sending request…

See this endpoint on live data

Send this exact request and the real response shows up here, right next to the example.

Response Fields

Field Type Description
symbolstringUppercase underlying symbol
minutesintegerRequested/effective minute window
countintegerNumber of buckets returned
buckets[]arrayMinute buckets: ts, buyVolume, sellVolume, midVolume, netVolume, tradeCount, biggestTrade, vwap, high, low
expirystring | nullEcho of the ?expiry= filter, or null when no filter was applied
lastBucketUtcstringLast bucket (UTC)
staleSecondsnumberStale seconds
marketOpenbooleanMarket open
stalebooleanStale
errorstring | nullError code when the source reported a problem, otherwise null
messagestring | nullHuman-readable message
endpoint_version, data_as_ofstring, objectResponse envelope, see Response envelope.

Fields of buckets[]

Field Type Description
buckets[].tsstringBucket timestamp (UTC)
buckets[].buyVolumenumberVolume classified as buyer-initiated
buckets[].sellVolumenumberVolume classified as seller-initiated
buckets[].midVolumenumberVolume printed at the mid
buckets[].netVolumenumberBuy volume minus sell volume
buckets[].tradeCountnumberNumber of trades
buckets[].biggestTradenumberLargest single trade size
buckets[].vwapnumberVolume-weighted average price
buckets[].highnumberHigh
buckets[].lownumberLow

Errors

Status Error When
400invalid_expiryexpiry is not a valid yyyy-MM-dd date.
400-A query value has the wrong type, or a required value is missing. The body is an RFC 7807 problem-details object with errors.<param>.
401-Missing or invalid X-Api-Key. The body is empty; check the status code before parsing JSON.
403tier_restrictedYour plan is below Alpha. The body includes current_plan and required_plan.
429Quota exceededDaily quota used up. Retry-After gives the seconds until the reset at 00:00 UTC. Rejected requests (including 403) count toward the quota.
502-Upstream flow data source unavailable.

About

Returns minute-aggregated trade-flow buckets for an underlying's option tape, newest first. VWAP is in premium dollars per contract. minutes requests how far back to look, clamped to a week (10080 minutes).

Common Use Cases

  • Backtest a minute-resolution flow chart - plot each bucket's netVolume over ts to replay how directional pressure built through the session
  • Detect intraday divergence - compare bucketed option netVolume against underlying minute returns to spot flow leading or fading price
  • Scan for volatility events - flag minutes with elevated biggestTrade or tradeCount to pinpoint when activity spiked
  • Overlay premium VWAP - chart per-bucket vwap with high/low to track where premium was actually trading each minute
  • Trigger rolling alerts - sum netVolume across a trailing window of buckets and fire when it crosses a threshold
  • Measure buy/sell balance over time - track the buyVolume/sellVolume split per bucket to see conviction shift intraday

Related reading

Complementary endpoints

Ready to build with FlashAlpha?

Get your free API key and start pulling live options data in 60 seconds.

No credit card required Setup in 60 seconds Secure & reliable