API
Protobuf
Ask for application/x-protobuf on the high-volume reads and get compact binary bodies, defined by two public .proto schemas you can generate bindings from.
JSON is the default everywhere. On the high-volume reads you can ask for a protobuf body instead — smaller and faster to decode, with the same data. Errors are always JSON.
Content negotiation
Send Accept: application/x-protobuf:
curl -sS -G "https://api.itmatrixhq.com/v2/gex/SPY/grid" \
-H "Authorization: Bearer $ITM_API_KEY" \
-H "Accept: application/x-protobuf" \
-d "top=20" \
-o grid.pbThese operations serve protobuf (each reference page says so under Response):
| Operation | Message |
|---|---|
GET /v2/gex/{symbol}/grid | GexGridResponse |
GET /v2/chain/{symbol} | ChainResponse |
GET /v2/stocks/{symbol}/bars | BarsResponse |
GET /v2/offexchange/{symbol}/activity and the other three off-exchange views | OffExchange…Response |
Any other Accept value gets JSON. A non-2xx answer is always the JSON error envelope — check the status and Content-Type before decoding.
The schemas
| Schema | Package | Used for |
|---|---|---|
/v2/rest-protocol.proto | itmatrixhq.rest.v1 | Negotiated REST bodies |
/v2/ws-protocol.proto | itmatrixhq.ws.v1 | WebSocket data frames (Streaming) |
Conventions in both: prices are sint32 scaled by 10,000; timestamps are epoch milliseconds; strikes are integer thousandths of a dollar; option right is 0 = call, 1 = put; expiries are days since 1970-01-01; absent optional fields are unset, not zero. Some counters are uint64 — use a 64-bit integer type in your language.
Generate bindings: Python
pip install grpcio-tools protobuf
curl -sS -o rest.proto https://api.itmatrixhq.com/v2/rest-protocol.proto
curl -sS -o ws.proto https://api.itmatrixhq.com/v2/ws-protocol.proto
python -m grpc_tools.protoc -I. --python_out=. rest.proto ws.protoimport os
import httpx
import rest_pb2
response = httpx.get(
"https://api.itmatrixhq.com/v2/gex/SPY/grid",
params={"top": 20},
headers={
"Authorization": f"Bearer {os.environ['ITM_API_KEY']}",
"Accept": "application/x-protobuf",
},
)
response.raise_for_status()
grid = rest_pb2.GexGridResponse.FromString(response.content)
for row in grid.rows:
print(row.strike_thousandths / 1000, row.gex)import os
import itmatrix as itm
# The SDK negotiates protobuf and returns the same models as JSON.
with itm.ITMClient(api_key=os.environ["ITM_API_KEY"], transport="protobuf") as client:
grid = client.get_gex("SPY", top=20)
print(grid.data.net_gex, len(grid.data.strikes))Generate bindings: TypeScript
With ts-proto and any protoc (the grpcio-tools one above works):
npm install --save-dev ts-proto
npm install @bufbuild/protobuf
python -m grpc_tools.protoc -I. \
--plugin=protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto \
--ts_proto_out=./gen \
--ts_proto_opt=forceLong=bigint,esModuleInterop=true \
rest.proto ws.protoimport { GexGridResponse } from "./gen/rest";
const url = new URL("https://api.itmatrixhq.com/v2/gex/SPY/grid");
url.search = new URLSearchParams({ top: "20" }).toString();
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${process.env.ITM_API_KEY}`,
Accept: "application/x-protobuf",
},
});
if (!response.ok) throw new Error(JSON.stringify(await response.json()));
const grid = GexGridResponse.decode(new Uint8Array(await response.arrayBuffer()));
console.log(grid.netGex, grid.rows.length);import { ITMClient } from "@itmatrixhq/core";
// The SDK negotiates protobuf and returns the same models as JSON.
const client = new ITMClient({ apiKey: process.env.ITM_API_KEY, transport: "protobuf" });
const { data } = await client.getGex("SPY", { top: 20 });
console.log(data.net_gex, data.strikes.length);forceLong=bigint keeps 64-bit fields exact. The SDK tab on each example shows the same read through the SDK, which negotiates protobuf for you.
Keep your copy of the schemas current: re-encoding a decoded message with an older schema drops fields it does not know. See Versioning.