WebSockets · Futures
Futures absorption stream
/v1/ws/futures/absorptionwsFuturesAbsorptionOn this page
Held-extreme absorption from the same model as REST /v1/futures/absorption and the terminal's Futures Absorption widget: sellers absorbed when net aggressive selling keeps hitting a low that holds (buyers at a holding high), confirmed back at the extreme, with a threshold scaled to the contract's own volume. kind called is sent the moment an absorption is announced; kind updated follows at most once a second per absorption while its net aggression keeps growing (the same id as the call and as REST). Each dated contract's model is warmed from the captured recent tape of the current session, so calls can arrive right after subscribing; it starts afresh at each session open and restarts from the captured tape after a gap. Subscribe and unsubscribe products (ES, a product selects its front contract) or dated contracts (NQZ6) on one socket. The model parameters are the defaults; tune them per request on the REST route.
Connect and subscribe
Open wss://api.ordermap.si/v1/ws/futures/absorption?symbols=ES with your key in the Authorization header and your saved installation ID in X-OrderMap-Device-ID, then send a subscribe message. Up to 25 symbols per connection. Streams need API Pro. All keys and projects share one active device per account and one connection per event type. Reuse the same installation ID for every stream and reconnect. Browser subprotocols, limits and close codes are in WebSockets.
Node.js
import WebSocket from "ws";
// Create a UUID once per installation, save it, and reuse it for every stream.
const deviceId = process.env.ORDERMAP_DEVICE_ID;
if (!deviceId) throw new Error("Set ORDERMAP_DEVICE_ID to this installation's saved UUID.");
const ws = new WebSocket("wss://api.ordermap.si/v1/ws/futures/absorption?symbols=ES", {
headers: {
Authorization: `Bearer ${process.env.ORDERMAP_API_KEY}`,
"X-OrderMap-Device-ID": deviceId,
},
});
ws.on("open", () => ws.send(JSON.stringify({ action: "subscribe", symbols: ["ES"] })));
ws.on("message", (raw) => {
const message = JSON.parse(raw.toString());
if (message.type === "event") console.log(message.seq, message.data);
if (message.type === "gap") console.warn("continuity lost: refetch the range over REST", message);
});
ws.on("close", (code, reason) => console.log("closed", code, reason.toString()));Subscribe message
{"action":"subscribe","symbols":["ES"]}Upgrade headers
A persistent installation ID is required. Supply the header below, or offer it as an ordermap.device.<id> browser subprotocol with ordermap.v1. Reuse the same saved ID for every event type, key, project and reconnect. Headers are not subscription filters.
| Parameter | Type and limits | Description |
|---|---|---|
X-headeroptional | stringat least 16 charactersat most 128 characterspattern ^[A-Za-z0-9_-]{16,128}$ | Required unless supplied as an ordermap.device.<id> subprotocol together with ordermap.v1. Generate one random identifier per client installation and persist it across event types, keys, projects and reconnects. Never send it in the URL. |
Subscription parameters
3 parameters, none required. Send them in the query string of the upgrade request, or as the filters of a subscribe message.
| Parameter | Type and limits | Description |
|---|---|---|
symbolsqueryoptional | array<string>comma-separated in one parameter1 to 25 itemseach at most 128 characterspattern ^[A-Za-z][A-Za-z0-9.]{0,9}$ | Symbols to subscribe to (up to 25). |
sidequeryoptional | array<string>comma-separated in one parameterbuysell1 to 2 items | Only these absorbed aggressors: sell (sellers absorbed at a low) or buy (buyers absorbed at a high). |
min_queryoptional | integermin 1max 1000000 | Only absorptions whose net aggression reaches this many contracts. |
Event
Each event is one message: {"type":"event","event_type":"futures.absorption","seq":N,"data":{...}}.
data of futures.absorption
aggressor_sharenumberrequiredaggressor_volume divided by classified_volume.aggressor_volumeintegerrequiredAggressor contracts since the test began.classified_volumeintegerrequiredBuy plus sell contracts since the test began.contractstringrequiredDated contract.end_timeintegerunix-msrequiredLatest print that grew the absorption. Unix epoch milliseconds (UTC).idstringrequiredIdentifier of the absorption, the same on its call, its updates and REST /v1/futures/absorption.kindstringrequiredcalled when the absorption is announced, updated while its net aggression keeps growing.calledupdatednet_aggressionintegerrequiredAggressor contracts minus the other side's since the test began (unknown-side prints excluded).pricenumberrequiredThe holding low or high.price_ticksstringrequiredprice as an integer count of ticks, as a string.sidestringrequiredAbsorbed aggressor: sell when sellers were absorbed at a holding low, buy when buyers were absorbed at a holding high.buysellstart_timeintegerunix-msrequiredFirst print of the test of that low or high. Unix epoch milliseconds (UTC).symbolstringrequiredThe symbol subscribed to.thresholdnumberrequiredNet aggression the call required.timestampintegerunix-msrequiredTime of the print that produced this event. Unix epoch milliseconds (UTC).trigger_timeintegerunix-msrequiredWhen the absorption was called. Unix epoch milliseconds (UTC).
Example event
{
"type": "event",
"event_type": "futures.absorption",
"seq": 1,
"data": {
"aggressor_share": 0.5865,
"aggressor_volume": 61,
"classified_volume": 104,
"contract": "NQZ6",
"end_time": 1792979848900,
"id": "4c1f0a9e2d7b6c5a8e3f1d0b9a7c6e5f4d3b2a1c0e9f8d7c6b5a4e3d2c1b0a9f",
"kind": "called",
"net_aggression": 18,
"price": 29163.75,
"price_ticks": "116655",
"side": "sell",
"start_time": 1792979827763,
"symbol": "NQ",
"threshold": 13.84,
"timestamp": 1792979848900,
"trigger_time": 1792979848900
}
}Before the upgrade
Errors before the upgrade are ordinary JSON errors; after it, problems arrive as messages and close codes (see WebSockets).
| Status | Meaning | Body |
|---|---|---|
101 | Switching protocols: WebSocket protocol ordermap.v1. | Switching protocols |
400 | Invalid handshake parameters or missing, malformed or conflicting persistent device identifier. | Error object |
401 | Missing or invalid API key (Authorization, X-API-Key or, from a browser, the ordermap.key. subprotocol). | Error object |
403 | The plan has no streaming (streaming_not_in_plan), the dataset is not released, or the account is suspended. | Error object |
409 | stream_connection_limit: the account is already connected on another device, or already has this event type open on the active device. The existing connection is preserved.Retry-After | Error object |
426 | The request is not a WebSocket upgrade. | Error object |
429 | Rate limit or WebSocket cooldown.Retry-After | Error object |
503 | stream_unavailable: the stream is not enabled or its source is down; retry after Retry-After seconds.Retry-After | Error object |
Authenticated responses carry the X-RateLimit-* headers (see rate limits); 429 and 503 add Retry-After.
