ConnectRPC is the typed RPC interface we use for latency-sensitive and high-throughput API workloads.
Most teams still start with REST, and that is fine. If you are exploring endpoints, use REST first (curl/Postman). When you ship bots or tight loops, ConnectRPC usually gives better transport efficiency.
Use REST for quick exploration and broad compatibility. Use ConnectRPC when transport efficiency starts to matter.
When ConnectRPC is the right choice
ConnectRPC is usually the better fit when:
you run high-frequency bot or automation traffic
for equivalent messages, payloads are often 50%+ smaller on the wire versus JSON (exact ratio depends on message shape)
you want typed request/response contracts generated from
.protoyou want to avoid decimal/string conversion overhead in hot paths
you want one schema source used consistently by SDKs and frontend clients
ConnectRPC clients call typed methods such as:
/orders.v1.OrdersService/CreateOrder
REST remains production-supported and widely used. This is a transport choice, not a quality tier.
REST vs ConnectRPC payloads
Example below uses a trade item from read surfaces (GetUserTrades), so differences are visible in one place (symbol, ID format, and scaled values).
ConnectRPC can be sent as JSON for debugging, but the production path is binary Protobuf on the wire.
Generated ConnectRPC clients use binary Protobuf by default.
Request: GET /v1/spot/trades?symbol=BTC-USDT&limit=1Accept: application/json
{
"orderId": "3mJr7AoUXx2Wqd",
"symbol": "BTC-USDT",
"price": "50000.000000",
"qty": "0.00100000",
"fee": "0.050000"
}Request: POST /orders.v1.OrdersReadService/GetUserTradesContent-Type: application/json
Response: Content-Type: application/json
{
"order_id": "72623859790382856",
"symbol_id": 1,
"price_ticks": "50000000000",
"qty_scaled": "100000",
"fee_scaled": "50000"
}Request: POST /orders.v1.OrdersReadService/GetUserTradesContent-Type: application/proto
Response: Content-Type: application/proto
protobuf response body for:
{"order_id":"72623859790382856","symbol_id":1,"price_ticks":"50000000000","qty_scaled":"100000","fee_scaled":"50000"}
hex:
10 01 21 08 07 06 05 04 03 02 01 38 80 e8 ed a1 ba 01 40 a0 8d 06 48 d0 86 03
base64:
EAEhCAcGBQQDAgE4gOjtoboBQKCNBkjQhgM=This is protobuf wire encoding for the same logical fields shown in the JSON debug tab.
Key mapping behavior:
IDs: ConnectRPC uses fixed-width numeric IDs (for example
order_idas fixed64), while REST exposes display-friendly base58 strings (for exampleorderId).Price/quantity values: ConnectRPC uses scaled integers (for example
qty_scaled,price_ticks), while REST uses decimal strings (for exampleqty,price).Scale source: ConnectRPC payloads do not repeat scale metadata on each message. Clients should read scales from SpotConfig (
GetSpotConfig/GET /v1/spot/config) and apply them per asset/pair.Symbols & Assets: ConnectRPC uses numeric fields like
symbol_idandasset_id; REST read adapters resolve these to display values (for example"BTC-USDT"and"BTC") for readability.If you want UI parity in your own client views, convert fixed64 IDs to base58 in your display layer.
These are the primary conventions across trading payloads. On Polyester REST endpoints, this mapping pattern appears repeatedly: order_id -> orderId, symbol_id -> symbol, asset_id -> asset, price_ticks -> price, qty_scaled -> qty, fee_scaled -> fee.
ConnectRPC operating checklist
use generated clients instead of hand-built request wrappers
keep auth/request metadata centralized in one client wrapper
use binary Protobuf on wire for production (
application/proto)fetch and cache asset/pair scales from SpotConfig before decoding scaled integers
retry only transient failures with bounded backoff + jitter
for write flows, use idempotency fields supported by the endpoint (for example
request_id)do not mix decimal and scaled representations in one client path
treat pagination cursors as opaque and replay exactly as returned
handle 64-bit identifiers safely in JavaScript clients (avoid lossy
Numberconversions)
Our frontend uses ConnectRPC through the Polyester TypeScript SDK, so UI and API integrations follow the same typed contract model.
Authentication
Authenticated ConnectRPC calls follow the same account security model as the rest of the platform:
Ed25519 API key authentication for programmatic access
JWT-based auth flows where applicable
If you are setting up API keys, start here:
api-reference/authentication/ed25519-api-keys.mddeveloper-docs/interfaces-transports/api-key-replay-policy.md(write-path replay policy and latency notes)
SDK status
TypeScript SDK: available
Python SDK: planned
Go SDK: planned
Rust SDK: planned
WebSocket payload formats
WebSocket streams are available in both JSON and Proto payload formats.
JSON is convenient for inspection and quick integrations.
Proto is better when payload compactness and client-side efficiency matter.
What comes next in API Interfaces docs
Interfaces & Transports roadmap:
ConnectRPC guide (clients, metadata, retries) - this page
REST guide (signing, pagination, common patterns) - available
WebSocket guide (public vs private, subscribe model) - planned
Proto vs JSON mapping (Proto = Protocol Buffers, JSON = JavaScript Object Notation) - planned
Compression & performance tips (payload size, batching) - planned
FIX planned overview (FIX = Financial Information eXchange) - planned
SBE planned overview (SBE = Simple Binary Encoding) - planned