Live SSE stream (up to 10 symbols per connection)
https://api.skylit.ai/v1/streamA Server-Sent Events (text/event-stream) feed of live per-strike
heatmaps. Two wire formats:
- v2 (default with
symbols=, orformat=v2): up to 10 symbols on one connection, camelCase events matchingSymbolHeatmap, resumable withLast-Event-ID. - v1 (default with
symbol=): the original single-symbol format, unchanged.
v2 events
Every event names its symbol (except connection-level events).
| Event | id: | Payload |
|---|---|---|
connected | — | {format:"v2", symbols, metric, creditsRemaining, creditsPerMinute, maxDurationSeconds} |
resumed | yes | Only when Last-Event-ID was sent. See Resume. |
snapshot | yes | StreamSnapshot (= SymbolHeatmap + lagged). Once per symbol on connect, then on every board change. |
velocity | yes | StreamVelocity: per-node velocity for the stream's metric, when it changes (checked every ~3s). |
symbol_unavailable | — | {symbol, reason: "no_live_board" | "expiration_not_found", message}; a snapshot follows once a board exists. |
credits | — | {remaining, charged} after each per-minute debit. |
closed | — | {reason: "insufficient_credits" | "account_suspended" | "key_revoked" | "monthly_cap_reached" | "credit_check_failed"}; stream ends. key_revoked: an API key on the account was revoked after this stream opened (streams opened on another still-valid key close too; reconnect to continue). monthly_cap_reached: the account's monthly spend cap was reached. |
reconnect | yes | {reason: "max_duration" | "server_shutdown"}; stream ends, reconnect with Last-Event-ID. |
: ping | — | SSE comment every 15s so idle proxies (CloudFront: 60s) keep the connection. |
Snapshots differ from /v1/heatmap in two ways: spot is the board's
own spot, and strikes carry no velocityPct (use the velocity
event). Within a symbol, asOf never goes backwards; a board already
sent is never re-sent.
Event ids (resume cursor). The id: is the connection's position
in every symbol, not just the event's: a comma-separated list of
SYMBOL:asOfUnixMs, e.g. SPY:1790000000123,QQQ:1790000000456.
asOfUnixMs is the board's publish timestamp, identical on every
server, so a cursor resumes on any pod. Per symbol it never decreases
and strictly increases with each snapshot for that symbol.
Resume. Reconnect with header Last-Event-ID: <last id> (browsers'
EventSource does this automatically) or ?lastEventId=. The server
keeps no event history: boards are full state, so it sends the
resumed event and then a fresh snapshot for every symbol that has a
live board, whether or not it changed. Per symbol status is:
unchanged (no board was published during the gap — nothing missed),
advanced (at least one board was published; intermediate boards are
not replayed, only the latest), unknown (symbol not in the
cursor), or unavailable (no live board right now). gapCovered is
true only if every symbol is unchanged; stateRestored is true when
every symbol received a current snapshot. Velocity is not replayed; the
latest reading is re-sent when this server has one.
Backpressure. A client that reads slower than boards are published
is never queued behind: each symbol holds at most one pending board, a
newer board replaces it, and the board that is finally sent carries
lagged: true. A client that stops reading for 30s is disconnected.
Pricing (v2). N = number of symbols. N credits on connect
(charged before the SSE upgrade, so an under-funded client gets a clean
402), then N credits per minute open — 1 credit ($0.001) per symbol
per minute, i.e. $0.06 per symbol-hour, plus $0.001 per symbol to open.
Minutes are charged in advance and a partial minute is not refunded.
Limits. At most 10 symbols per connection (more → 400). At most
25 symbols per customer per server across all open streams (a v1
stream counts as 1); over it → 429 stream_limit_reached with
Retry-After: 2 (a just-closed stream frees its symbols within about
a second). v1 also keeps its 5-streams cap. Each server streams a
bounded number of distinct symbols across all customers (default
20); a v2 stream that would add a new symbol beyond that gets 503
stream_capacity with Retry-After: 5 — retry (you may land on
another server). Symbols already being streamed are always admitted.
Streams end after 1 hour with reconnect.
v1 events (single symbol, unchanged)
connected {symbol, creditsRemaining}, initial_data,
snapshot_update, velocity_update (internal PascalCase board shape),
credits, closed, reconnect, and a : keepalive comment every
30s. 1 credit to open + 1 per minute. v1 rejects expirations.
OpenAPI cannot fully model an event stream. See docs/api-credits.md.
Authorization
Authorization: Bearer <your API key>Required. A missing header returns 401; an invalid, revoked or expired key returns 403.
Query parameters
symbolsstringComma-separated tickers, up to 10 (e.g.
SPY,QQQ,IWM). Selects format v2 by default. Unknown symbols →404.symbolstringSingle ticker. Selects the legacy v1 format unless
format=v2. Sendsymbolorsymbols, not both.formatstringWire format. Defaults to
v2withsymbols=andv1withsymbol=.v1is single-symbol only.v1v2lastEventIdstringv2 resume cursor, for clients that cannot set the
Last-Event-IDheader. The header wins if both are sent.metricstringdefaultgammaWhich Greek exposure to return per strike.
gammavannamaxStrikesdefault92Maximum number of strikes around spot to return: an integer from 1 to 1000, or
allfor every strike the snapshot lists (SPXW lists about 730). Values above 1000 return400 invalid_parameter; they are never silently reduced. Values below 1 are treated as 1. The single-symbol stream (/v1/stream?symbol=) accepts at most 400 and noall.maxExpirationsdefault5How many of the nearest expirations to net into each strike's
value: an integer from 1 to 60, orall. Values above 60 return400 invalid_parameter. Ignored whenexpirationsis set.includeEmptybooleandefaultfalseBy default, an interior strike whose every returned cell is below 50 in absolute value (listed but effectively untraded) is left out, judged on the selected metric alone. So gamma and vanna for the same instant can return different strike lists. The outermost strikes are never removed.
truekeeps every strike in the window, so the list is the snapshot's own contiguous ladder and is identical for gamma and vanna. Not supported on the single-symbol stream (symbol=).expirationsstringv2 only — same meaning as on
/v1/heatmap. Rejected with400on v1.layoutstringdefaultnetv2 only —
matrixadds the per-expiration grid to each snapshot, as on/v1/heatmap.netmatrix
Headers
Last-Event-IDstringv2 resume cursor — the last
id:received.
Responses
- 200
An SSE stream of heatmap events.
- 400
Request validation failed.
- 401
Missing API key (
unauthorized), sent by the gateway. - 402
Out of credits (
insufficient_credits). - 403
Unknown, revoked or expired key (
forbidden, from the gateway), or an admin-suspended account (account_suspended). - 404
Unknown symbol, no data available, or none of the requested
expirationsexist for the symbol (code: expiration_not_found). - 429
Per-minute rate limit exceeded.
- 503
Heatmap data is temporarily unavailable.
Response fields
Returns string.
Last updated