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
event: ready
data: {"topics":["trades","leads"],"heartbeat_seconds":15,"reconnect_after_seconds":2917,"replay_window_seconds":3600}
id: 90412
event: trade
data: {"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"}
: heartbeat
id: 90467-0
event: lead
data: {"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"]}
event: reconnect
data: {"reason":"lifetime","cursor":"90467-0"}
{
"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
event: ready
data: {"topics":["trades","leads"],"heartbeat_seconds":15,"reconnect_after_seconds":2917,"replay_window_seconds":3600}
id: 90412
event: trade
data: {"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"}
: heartbeat
id: 90467-0
event: lead
data: {"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"]}
event: reconnect
data: {"reason":"lifetime","cursor":"90467-0"}
{
"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>"
}
}Headers
Query Parameters
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.