Docs

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:

sh
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.pb

These operations serve protobuf (each reference page says so under Response):

OperationMessage
GET /v2/gex/{symbol}/gridGexGridResponse
GET /v2/chain/{symbol}ChainResponse
GET /v2/stocks/{symbol}/barsBarsResponse
GET /v2/offexchange/{symbol}/activity and the other three off-exchange viewsOffExchange…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

SchemaPackageUsed for
/v2/rest-protocol.protoitmatrixhq.rest.v1Negotiated REST bodies
/v2/ws-protocol.protoitmatrixhq.ws.v1WebSocket 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

sh
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.proto
import 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)

Generate bindings: TypeScript

With ts-proto and any protoc (the grpcio-tools one above works):

sh
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.proto
import { 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);

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.