ZAAR

API

Binance Spot-shaped, with the changes in decisions.md D-6. The generated OpenAPI document (/v1/openapi.json, committed at docs/openapi.json) is the exact contract; this page is the map. Signing is in auth.md.

Hosts

env REST WebSocket
prod https://api.zaar.network/v1 wss://api.zaar.network/v1/ws
staging https://api.staging.zaar.network/v1 wss://api.staging.zaar.network/v1/ws
local http://127.0.0.1:8080/v1 ws://127.0.0.1:8080/v1/ws

Conventions

Endpoints

General and market data (NONE)

GET /v1/ping liveness
GET /v1/time server time
GET /v1/exchangeInfo assets, markets, filters, fee schedule
GET /v1/depth?symbol&limit order book
GET /v1/trades?symbol&limit recent trades
GET /v1/historicalTrades?symbol&fromId&limit older trades
GET /v1/klines?symbol&interval&startTime&endTime&limit candles (1m … 1M)
GET /v1/ticker/24hr, /ticker/price, /ticker/bookTicker tickers

Trading (TRADE, READ)

POST /v1/order place (LIMIT, MARKET, LIMIT_MAKER); response = Binance FULL + account
POST /v1/order/test validate parameters, filters and scope without placing
DELETE /v1/order?symbol&orderId|origClientOrderId cancel
DELETE /v1/openOrders?symbol cancel all on a market
GET /v1/order, /v1/openOrders, /v1/allOrders query orders
GET /v1/myTrades?symbol fills with fees

Accounts and transfers (READ, TRANSFER) — new vs Binance

GET /v1/accounts accounts reachable by the key
GET /v1/account balances (free, locked) of one account
POST /v1/transfer {toAccount, asset, amount, clientTransferId}
GET /v1/transfers?asset&startTime&endTime transfer history incl. trades and fees

Org (USERS_MANAGE, KEYS_MANAGE, ORG_ADMIN) — new

POST /v1/org/users, GET /v1/org/users users by externalRef
PATCH /v1/org/users enable or disable a user
POST /v1/org/accounts open an account for a user or the org
PATCH /v1/org/accounts freeze, unfreeze or close an account (also NETWORK_ADMIN)
POST /v1/org/apps, GET /v1/org/apps apps
POST /v1/apiKeys, GET /v1/apiKeys, DELETE /v1/apiKeys keys (public keys only)
GET /v1/org/fees fee share earned

Admin (NETWORK_ADMIN) — new

POST /v1/admin/orgs create org (with its first ORG_ADMIN key)
PATCH /v1/admin/orgs org status, org fee share
POST /v1/admin/assets, PATCH /v1/admin/assets create asset, change its status
POST /v1/admin/markets, PATCH /v1/admin/markets create market, change status/fees
PUT /v1/admin/fees network default fee schedule
POST /v1/admin/mint, POST /v1/admin/burn paper money in and out
GET /v1/admin/stats seq, state hash, counts

WebSocket /v1/ws

JSON text frames, Binance-style. Requests:

{"id": 1, "method": "SUBSCRIBE", "params": ["btc-usd@trade", "btc-usd@depth", "btc-usd@kline_1m"]}
{"id": 2, "method": "UNSUBSCRIBE", "params": ["btc-usd@trade"]}
{"id": 3, "method": "LIST_SUBSCRIPTIONS"}
{"id": 4, "method": "session.logon", "params": {"apiKey": "...", "timestamp": 0, "signature": "..."}}
{"id": 5, "method": "userDataStream.subscribe", "params": {"account": 7}}

Also session.status, session.logout and userDataStream.unsubscribe {subscriptionId?}. Replies: {"id", "result"} for the stream methods, {"id", "status": 200, "result"} for session.* and userDataStream.*; any error is {"id", "status", "error": {"code", "msg"}}. session.logon signs the request payload of auth.md with METHOD = WS, path = /v1/ws and empty query, account and body; userDataStream.subscribe needs READ over the account (decided by the core).

Market streams arrive as {"stream": "btc-usd@trade", "data": {...}}. Symbols are lowercase in stream names.

stream payload when
<symbol>@trade {e: "trade", E, s, t, p, q, T, m, M} every fill
<symbol>@depth {e: "depthUpdate", E, s, U, u, pu, b, a} every batch that changed the book
<symbol>@depth20 {lastUpdateId, bids, asks} every second
<symbol>@bookTicker {u, s, b, B, a, A} when the best bid or ask changes
<symbol>@kline_<interval> {e: "kline", E, s, k: {t, T, s, i, o, c, h, l, v, n, x, q, V, Q}} every second while the market trades
<symbol>@ticker {e: "24hrTicker", E, s, p, P, w, c, o, h, l, v, q, O, C, F, L, n} every second while the market trades

Depth sync. Update ids are journal sequence numbers, so they are not contiguous per market: U/u are the first/last seq that changed this book in the event and pu is the u of the previous event for the same market (as on Binance futures). To keep a local book: open the stream, fetch GET /v1/depth (its lastUpdateId = L), drop events with u <= L; the first applied event must have pu <= L and each later one pu = the previous u; otherwise refetch.

User stream events arrive as {"subscriptionId": 0, "event": {...}}, in Binance shapes plus A (the account id): executionReport (every order change; x = NEW, TRADE, CANCELED, EXPIRED, REJECTED), outboundAccountPosition (balances touched by a command), balanceUpdate (mint, burn, transfer, import; signed d) and transfer (ZAAR: the transfer record for those kinds).

Each connection has a bounded outgoing queue; a client that cannot keep up is disconnected and must reconnect and resync. The server pings every 20 s and closes connections silent for 60 s.

Reserved for v1.1: order placement over WebSocket (order.place etc.), amend keep-priority, order lists, SBE binary encoding.