Heatseeker/API Reference/Heatmap

Live SSE stream (up to 10 symbols per connection)

GEThttps://api.skylit.ai/v1/stream

A Server-Sent Events (text/event-stream) feed of live per-strike heatmaps. Two wire formats:

  • v2 (default with symbols=, or format=v2): up to 10 symbols on one connection, camelCase events matching SymbolHeatmap, resumable with Last-Event-ID.
  • v1 (default with symbol=): the original single-symbol format, unchanged.

v2 events

Every event names its symbol (except connection-level events).

Eventid:Payload
connected—{format:"v2", symbols, metric, creditsRemaining, creditsPerMinute, maxDurationSeconds}
resumedyesOnly when Last-Event-ID was sent. See Resume.
snapshotyesStreamSnapshot (= SymbolHeatmap + lagged). Once per symbol on connect, then on every board change.
velocityyesStreamVelocity: 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.
reconnectyes{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

  • symbolsstring

    Comma-separated tickers, up to 10 (e.g. SPY,QQQ,IWM). Selects format v2 by default. Unknown symbols → 404.

  • symbolstring

    Single ticker. Selects the legacy v1 format unless format=v2. Send symbol or symbols, not both.

  • formatstring

    Wire format. Defaults to v2 with symbols= and v1 with symbol=. v1 is single-symbol only.

    v1v2
  • lastEventIdstring

    v2 resume cursor, for clients that cannot set the Last-Event-ID header. The header wins if both are sent.

  • metricstringdefault gamma

    Which Greek exposure to return per strike.

    gammavanna
  • maxStrikesdefault 92

    Maximum number of strikes around spot to return: an integer from 1 to 1000, or all for every strike the snapshot lists (SPXW lists about 730). Values above 1000 return 400 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 no all.

  • maxExpirationsdefault 5

    How many of the nearest expirations to net into each strike's value: an integer from 1 to 60, or all. Values above 60 return 400 invalid_parameter. Ignored when expirations is set.

  • includeEmptybooleandefault false

    By 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. true keeps 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=).

  • expirationsstring

    v2 only — same meaning as on /v1/heatmap. Rejected with 400 on v1.

  • layoutstringdefault net

    v2 only — matrix adds the per-expiration grid to each snapshot, as on /v1/heatmap.

    netmatrix

Headers

  • Last-Event-IDstring

    v2 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 expirations exist 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

Was this page helpful?