Developers
REST for everything, websockets for everything live — the same data and order flow the terminal runs on.
Overview
The Obsidiate API exposes the same data and order flow the terminal runs on: 99 instruments across crypto, stocks, forex and metals, one consistent interface. Everything is JSON over HTTPS; live data streams over websockets.
Timestamps are Unix seconds, UTC. Prices and quantities are returned as strings to avoid floating-point surprises. Market data endpoints are public; trading endpoints require an API key.
Base URL https://api.obsidiate.com/v1 Live streams wss://stream.obsidiate.com
Authentication
Create API keys from your dashboard. Each key carries scopes — read, trade, withdraw — and can be locked to IP addresses. Public market data needs no key at all.
Private requests are signed: send your key, a timestamp, and an HMAC-SHA256 signature of the timestamp, method, path and body, computed with your secret. Requests older than 30 seconds are rejected.
curl https://api.obsidiate.com/v1/balances \ -H "X-OBX-KEY: obx_live_2f8c91..." \ -H "X-OBX-TS: 1781119200" \ -H "X-OBX-SIGN: <hmac_sha256(ts + method + path + body)>"
Rate limits
Public endpoints allow 120 requests per minute per IP. Private endpoints use a weighted budget per account that scales with your tier. Exceeding a budget returns 429 with a Retry-After header.
If you are polling market data more than once a second, you want the websocket instead — it is faster, cheaper for everyone, and never rate-limits a subscribed stream.
Market data
Public, no key required. Symbols are uppercase tickers — BTC, NVDA, EUR/USD (URL-encode the slash), XAU.
/marketsEvery listed instrument with its class, name and price precision.
{
"markets": [
{ "symbol": "BTC", "class": "crypto", "name": "Bitcoin", "decimals": 2 },
{ "symbol": "EUR/USD", "class": "forex", "name": "Euro / US Dollar", "decimals": 4 }
]
}/markets/{symbol}Current quote for one instrument.
{
"symbol": "BTC",
"price": "67412.50",
"change24h": "2.41",
"high24h": "68011.00",
"low24h": "66102.20",
"volume24h": "18412.84",
"ts": 1781119324
}/markets/{symbol}/klinesHistorical candles. One bar per interval; the last bar is the live, still-forming one.
GET /v1/markets/BTC/klines?range=1D{
"symbol": "BTC",
"bars": [
{ "t": 1781119200, "o": "67318.2", "h": "67501.0", "l": "67255.4", "c": "67412.5", "v": "1284.2" }
]
}/markets/{symbol}/bookOrder book snapshot, best levels first.
{
"symbol": "BTC",
"bids": [["67410.50", "0.842"], ["67409.00", "1.205"]],
"asks": [["67412.50", "0.617"], ["67414.00", "2.330"]],
"ts": 1781119324
}/markets/{symbol}/tradesMost recent public trades, newest first.
{
"trades": [
{ "id": "t_8k2m1", "price": "67412.50", "qty": "0.0150", "side": "buy", "ts": 1781119324 }
]
}Trading
Requires a key with the trade scope. Orders are accepted, validated against your balance, then matched — the response tells you exactly how far it got.
/ordersAPI keyPlace an order. Market orders fill immediately against the book; limit orders rest; stop-loss orders trigger a market sell when the stop price trades.
POST /v1/orders
{
"symbol": "BTC",
"side": "buy",
"type": "limit",
"qty": "0.2500",
"price": "66800.00"
}{
"id": "ord_9f3k2m",
"status": "open",
"filled": "0.0000",
"ts": 1781119325
}/ordersAPI keyYour open orders, optionally filtered by symbol.
{
"orders": [
{ "id": "ord_9f3k2m", "symbol": "BTC", "side": "buy", "type": "limit", "qty": "0.2500", "price": "66800.00", "filled": "0.0000", "status": "open" }
]
}/orders/{id}API keyCancel a resting order. Fills that already happened stay yours.
{
"id": "ord_9f3k2m",
"status": "canceled",
"filled": "0.0834"
}/balancesAPI keyEvery balance on the account, including amounts locked in open orders.
{
"balances": [
{ "asset": "USD", "free": "12480.22", "locked": "16700.00" },
{ "asset": "BTC", "free": "0.4521", "locked": "0.0000" }
]
}/fillsAPI keyYour trade history, newest first.
{
"fills": [
{ "id": "f_2c91x", "order": "ord_9f3k2m", "symbol": "BTC", "side": "buy", "qty": "0.0834", "price": "66800.00", "fee": "1.39", "ts": 1781119388 }
]
}Websocket streams
Connect to wss://stream.obsidiate.com, send one subscribe message, receive ticks until you hang up. The server pings every 30 seconds; reply with a pong or the connection is dropped.
Channels are channel:SYMBOL pairs. Subscribe to as many as you like on one connection.
ticker:{symbol}Every price change for an instrument — the same feed the terminal header runs on.
{ "op": "subscribe", "channels": ["ticker:BTC", "ticker:ETH"] }{ "s": "BTC", "p": 67414.12, "t": 1781119324 }book:{symbol}Order book deltas. Apply them to a /book snapshot; a seq gap means resnapshot.
{ "op": "subscribe", "channels": ["book:BTC"] }{ "s": "BTC", "seq": 882104, "bids": [["67410.50", "0.000"]], "asks": [["67414.00", "1.882"]] }trades:{symbol}Public trades as they print.
{ "op": "subscribe", "channels": ["trades:BTC"] }{ "s": "BTC", "p": 67412.50, "q": 0.015, "side": "buy", "t": 1781119324 }Errors
Every error is the same envelope, with an HTTP status that means what it says. Error codes are stable — match on the code, not the message.
{
"error": {
"code": "insufficient_balance",
"message": "Order requires 16,700.00 USD; 12,480.22 available."
}
}Versioning
The API is versioned in the path. Within v1, changes are additive only — new fields and endpoints may appear, existing ones never change meaning or disappear. Breaking changes get a new version with a long overlap.
Live platform health, including the API and every market-data feed, is published on the status page.
This reference describes v1 as it will ship with the platform; details may change before launch. Questions or early-access requests: hello@obsidiate.com.