Feeder gateway WebSocket beta
Read the most recent Starknet blocks, state updates, and the preconfirmed block from the feeder gateway over one authenticated Starkscan WebSocket.
Feeder gateway WebSocket beta
Starkscan serves the Starknet feeder gateway for the most recent blocks over a single WebSocket. It is built for latency-sensitive clients, such as liquidators on lending protocols, that need new blocks, state diffs, and the preconfirmed block as soon as the sequencer publishes them.
Access is operator-issued and mainnet-only. The feeder scope cannot be
created from the API key page or redeemed through an access invite; ask your
Starkscan contact for a feeder key.
Endpoint and auth
wss://api.starkscan.co/v1/SN_MAIN/feeder/ws
X-Starkscan-Api-Key: <feeder_api_key>Connect from a server and send the key as a header. There is no browser or
URL-token form: browsers cannot set the header, and a browser page on an
origin outside Starkscan's allowlist gets 403.
| Status at the upgrade | Meaning |
|---|---|
401 | Missing or unknown key. |
403 | The key has no feeder scope, or a browser origin is not allowlisted. A read or batch key is not enough. |
503 feeder_wss_disabled | Your key is valid but the lane is not enabled in this environment. |
The upstream feeder credential stays on Starkscan's servers. Your key never reaches the upstream, and the upstream credential never reaches you.
Recent data only
The lane serves only recent blocks. A request that names a block number more
than 10 blocks behind the current head fails locally with
feeder_wss_block_outside_recent_window and never reaches the upstream. Read
older blocks, state updates, and classes from
Starkscan RPC instead. Nothing on this lane is cached: every
answer comes from the feeder gateway at request time.
Messages
Every frame is a JSON-RPC 2.0 text message. Send one request per message;
request batches and binary frames are rejected. A request without an id is a
JSON-RPC notification: it runs, for example a feeder_unsubscribe, but gets no
response or error.
Request and response
The method is the feeder endpoint name and params is an object of its query
parameters. The result is the feeder gateway's JSON body, unchanged.
| Method | Parameters |
|---|---|
get_block | blockNumber (required: latest, pending, or a recent number), headerOnly |
get_state_update | blockNumber (required), includeBlock, includeSignature |
get_preconfirmed_block | blockNumber (required), blockIdentifier, knownTransactionCount |
Every request names a block number, so the recency check runs before the
upstream call. Hash-addressed lookups (block hashes, transaction status,
classes) cannot be bounded to recent blocks and are not served here; use
Starkscan RPC, for example starknet_getTransactionStatus, or the
RPC WebSocket beta for transaction-status
subscriptions. Trace, contract-address, public-key, and transaction-submission
endpoints are not served either.
{"jsonrpc":"2.0","id":1,"method":"get_state_update","params":{"blockNumber":"latest","includeBlock":true}}Subscriptions
One shared poller watches the feeder gateway for every connection, so a subscription costs the upstream nothing extra.
| Method | Notification | result |
|---|---|---|
feeder_subscribeNewBlocks | feeder_newBlock | The get_state_update body for each new block, with includeBlock and includeSignature. |
feeder_subscribePreconfirmedBlock | feeder_preconfirmedBlock | A get_preconfirmed_block poll response. |
feeder_unsubscribe | true. Takes {"subscription_id": "..."}. |
Each connection may hold one subscription per stream. A subscribe call returns the subscription id, and every notification carries it:
{"jsonrpc":"2.0","method":"feeder_newBlock","params":{"subscription_id":"9f2c…","result":{"block":{…},"state_update":{…},"signature":{…}}}}New-block notifications start with the first block produced after you
subscribe. If the upstream replaces the head block, you receive the
replacement at the same block_number; key your state by block_hash. If the
chain rolls back to a lower head, you receive the replacement blocks from that
height, even below the block you subscribed at. A reorg while you subscribe
can also deliver a few blocks from just before you subscribed. A block
replaced after the head has moved past it is not re-sent, so check that each
block's parent_block_hash matches the previous block you hold and backfill
from RPC when it does not. If more than 10 blocks pass between notifications,
for example after an upstream outage, only the most recent 10 are sent;
backfill the rest from RPC.
Preconfirmed notifications follow the feeder's own poll protocol. The first
notification is always a full view (it has a status field). Starkscan
sends it immediately if its current view was confirmed by the upstream moments
ago, and otherwise with the next poll. Later
notifications for the same block_identifier are deltas that carry only the
new transactions, transaction_receipts, and transaction_state_diffs;
append them in order. A new full view replaces the block you were tracking.
The preconfirmed stream follows the newest tip. When the tip moves on, the
rest of the earlier block arrives as that block's feeder_newBlock
notification, not as more preconfirmed deltas. If a poll is missed while the
tip advances by more than one block, the skipped blocks also arrive only as
feeder_newBlock notifications. If the upstream moves the tip back to a lower
block and keeps reporting it, Starkscan sends that block as a new full view.
Errors
| Code | data.code | Meaning |
|---|---|---|
-32700 | feeder_wss_parse_error | The frame is not JSON. |
-32600 | feeder_wss_invalid_request | Not a JSON-RPC 2.0 object, or a batch. |
-32601 | feeder_wss_method_not_supported | The method is not served here; data.supportedMethods lists what is. |
-32602 | feeder_wss_invalid_params | Unknown, missing, or malformed parameter. |
-32602 | feeder_wss_already_subscribed / feeder_wss_unknown_subscription | Subscription bookkeeping. |
-32001 | feeder_wss_head_unavailable | Starkscan does not currently know the head, so it cannot check recency. Retry shortly. |
-32002 | feeder_wss_block_outside_recent_window | Read this block from RPC. data gives the head and the oldest block served. |
-32003 | feeder_wss_block_ahead_of_head | The block number is too far ahead of the head. |
-32010 | feeder_wss_upstream_error | The feeder gateway answered with its own error, passed through in data.upstreamError. |
-32011 | feeder_wss_upstream_unavailable | The feeder gateway timed out or failed. Retry with backoff. |
-32011 | feeder_wss_upstream_unverified | Starkscan has not yet confirmed that the feeder gateway serves mainnet. Retry with backoff. |
Connection behavior
- Starkscan sends a WebSocket ping every 30 seconds and closes a connection that sends nothing, not even a pong, for 90 seconds while none of its requests is outstanding.
- Every connection closes after one hour with code
1000. Reconnect: the new upgrade re-checks your key, so a revoked key stops working within an hour. - If your client reads too slowly and falls behind the notification stream,
the server closes with code
1013. Reconnect, resubscribe, and backfill the gap from RPC. - A deploy or restart closes connections with code
1001. Reconnect with backoff. - Up to 16 requests may be outstanding per connection; beyond that the server waits for one to finish before reading the next frame. Requests across all clients also share a bounded number of concurrent upstream calls, so under load a request may wait briefly rather than fail.
There are no per-key message or byte quotas during the beta. Starkscan monitors each key's usage and may introduce limits later.