curl --request GET \
--url https://api.routeur.app/v1/stream \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.routeur.app/v1/stream"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.routeur.app/v1/stream', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.routeur.app/v1/stream"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}"retry: 3000\n\nevent: ready\ndata: {\"topics\":[\"trades\",\"leads\"],\"heartbeat_seconds\":15,\"reconnect_after_seconds\":2917,\"replay_window_seconds\":3600}\n\nid: 90412\nevent: trade\ndata: {\"venue\":\"kalshi\",\"id\":\"d9b1c2e4\",\"market_id\":\"KXNFLSPREAD-26SEP14DENKC-KC21\",\"outcome\":\"yes\",\"taker_action\":\"buy\",\"price_usd\":\"0.1800\",\"quantity\":\"250\",\"notional_usd\":\"45.00\",\"executed_at\":\"2026-09-14T18:02:11Z\",\"block\":false,\"recorded_at\":\"2026-09-14T18:02:40Z\"}\n\n: heartbeat\n\nid: 90467-0\nevent: lead\ndata: {\"graph_run\":812,\"relation\":\"contradicts\",\"cross_venue\":true,\"left\":{\"venue\":\"kalshi\",\"id\":\"KXNFLSPREAD-26SEP14DENKC-KC21\",\"title\":\"Kansas City wins by over 20.5 points?\",\"rules_hash\":\"9f2c61d0a4be\"},\"right\":{\"venue\":\"polymarket\",\"id\":\"nfl-den-kc-2026-09-15-spread-away-1pt5\",\"title\":\"Spread: Broncos (-1.5)\",\"rules_hash\":\"0c77e1b9d2aa\"},\"legs\":[{\"venue\":\"kalshi\",\"market_id\":\"KXNFLSPREAD-26SEP14DENKC-KC21\",\"side\":\"no\",\"ask_usd\":\"0.83\"},{\"venue\":\"polymarket\",\"market_id\":\"nfl-den-kc-2026-09-15-spread-away-1pt5\",\"side\":\"no\",\"ask_usd\":\"0.14\"}],\"cost_usd\":\"0.97\",\"gross_edge_usd\":\"0.03\",\"estimated_fee_usd\":\"0.01\",\"net_edge_usd\":\"0.02\",\"issues\":[\"settle differently across venues\"]}\n\nevent: reconnect\ndata: {\"reason\":\"lifetime\",\"cursor\":\"90467-0\"}\n"{
"error": {
"code": "invalid_parameter",
"message": "Invalid or unsupported query parameter: limit."
}
}{
"error": {
"code": "api_key_required",
"message": "Send an API key in the X-API-Key header or as a Bearer token."
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}Live stream
Quotes, trades, new relations and leads pushed as they are recorded, as
Server-Sent Events
over one keyed connection. Authenticate as for any request; a browser
EventSource cannot send the key header, so connect from a server.
Topics
quotes: a market’s top-of-book asks changed. Recorded on each crawl of a venue, so quotes arrive in bursts.trades: a public fill was recorded, usually within a minute of execution.recorded_atshows when; a recording backlog can deliver older fills.books: the top of a market’s order book changed (best prices or the size at them), at most once a second per market, with mid, microprice, spread, 5-cent depth and imbalance. Only markets whose book is recorded from the venue feed appear; name them inmarketsto follow a few.relations: relations a finished graph run proved for the first time. A run that finds more than 10,000 new relations (a new graph version) sends onerelations_truncatedevent instead; read them from the REST endpoints.leads: every lead of a finished graph run, up to 1,000, in the order of/v1/opportunities.rules: a market’s terms changed: a new contract version replaced the previous one, a rulebook above it (series or event terms, resolution metadata) changed under an unchanged contract, or the venue’s contract terms document changed.rules_pathnames where to read the versions and diffs.
venue and markets narrow quotes, trades, books and rule changes by
their market, and relations and leads by either side; relations_truncated
is always sent to relations streams. min_usd drops smaller trades.
Resuming
Every data event has an id. After a drop, reconnect with the last id
in the Last-Event-ID header (or as cursor) and the same filters:
events after it are replayed in order, then the stream continues live,
with nothing missed or repeated. Ids are opaque, ordered strings. A
cursor from the last hour always resumes; an older or unknown cursor
gets a reset event and the stream continues from now.
Connection
The stream opens with ready. A comment line (: heartbeat) is sent
every 15 seconds; treat 45 seconds of silence as a dead connection.
Streams end themselves after 45 to 55 minutes, and when a server
restarts or a client falls a full buffer behind, with a reconnect
event carrying the cursor to resume from. Reconnect after the retry
interval (3 seconds), backing off on errors.
Limits
A key may hold one concurrent stream per 60 requests a minute of its
limit, at least 1 and at most 20 (per API instance). Opening a stream
counts as a request, and an open stream counts one more request per
minute against the daily quota; a stream whose key exhausts the quota
receives an error event and ends.
curl --request GET \
--url https://api.routeur.app/v1/stream \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.routeur.app/v1/stream"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.routeur.app/v1/stream', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.routeur.app/v1/stream"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}"retry: 3000\n\nevent: ready\ndata: {\"topics\":[\"trades\",\"leads\"],\"heartbeat_seconds\":15,\"reconnect_after_seconds\":2917,\"replay_window_seconds\":3600}\n\nid: 90412\nevent: trade\ndata: {\"venue\":\"kalshi\",\"id\":\"d9b1c2e4\",\"market_id\":\"KXNFLSPREAD-26SEP14DENKC-KC21\",\"outcome\":\"yes\",\"taker_action\":\"buy\",\"price_usd\":\"0.1800\",\"quantity\":\"250\",\"notional_usd\":\"45.00\",\"executed_at\":\"2026-09-14T18:02:11Z\",\"block\":false,\"recorded_at\":\"2026-09-14T18:02:40Z\"}\n\n: heartbeat\n\nid: 90467-0\nevent: lead\ndata: {\"graph_run\":812,\"relation\":\"contradicts\",\"cross_venue\":true,\"left\":{\"venue\":\"kalshi\",\"id\":\"KXNFLSPREAD-26SEP14DENKC-KC21\",\"title\":\"Kansas City wins by over 20.5 points?\",\"rules_hash\":\"9f2c61d0a4be\"},\"right\":{\"venue\":\"polymarket\",\"id\":\"nfl-den-kc-2026-09-15-spread-away-1pt5\",\"title\":\"Spread: Broncos (-1.5)\",\"rules_hash\":\"0c77e1b9d2aa\"},\"legs\":[{\"venue\":\"kalshi\",\"market_id\":\"KXNFLSPREAD-26SEP14DENKC-KC21\",\"side\":\"no\",\"ask_usd\":\"0.83\"},{\"venue\":\"polymarket\",\"market_id\":\"nfl-den-kc-2026-09-15-spread-away-1pt5\",\"side\":\"no\",\"ask_usd\":\"0.14\"}],\"cost_usd\":\"0.97\",\"gross_edge_usd\":\"0.03\",\"estimated_fee_usd\":\"0.01\",\"net_edge_usd\":\"0.02\",\"issues\":[\"settle differently across venues\"]}\n\nevent: reconnect\ndata: {\"reason\":\"lifetime\",\"cursor\":\"90467-0\"}\n"{
"error": {
"code": "invalid_parameter",
"message": "Invalid or unsupported query parameter: limit."
}
}{
"error": {
"code": "api_key_required",
"message": "Send an API key in the X-API-Key header or as a Bearer token."
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}Authorizations
Headers
The id of the last event received, sent by SSE clients on reconnect.
40Query Parameters
Comma-separated topics to receive.
^(quotes|trades|books|relations|leads|rules)(,(quotes|trades|books|relations|leads|rules))*$Only results on this venue.
kalshi, polymarket Up to 50 comma-separated markets as venue:id.
10500Only trades of at least this notional, in USD.
0 <= x <= 100000000Resume after this event id. Last-Event-ID does the same; this parameter wins when both are sent.
40^[0-9]+(-[0-9]+)?$Response
An event stream. Each event's data is one JSON object; the schema
for each event name is in x-events: ready (StreamReady), quote
(StreamQuote), trade (StreamTrade), book (StreamBook), relation (StreamRelation),
relations_truncated (StreamRelationsTruncated), lead
(StreamLead), rule_change (StreamRuleChange), reset
(StreamNotice), reconnect (StreamReconnect) and error
(StreamError).
The response is of type string.