Cube Exchange API Reference

Build anything on Cube Exchange.

Cube Exchange is a live central-limit order-book exchange. This reference documents the complete unified REST API for programmatic trading, market making and data — one consistent set of endpoints, one symbol format, one response shape per resource. If you have written a bot for any major exchange, this will feel immediately familiar.

Market data
Tickers, order books, trades, OHLCV. Public, keyless, JSON.
Trading & bots
Orders, margin, inventory — one API key, full control.
Self-custody
On-chain settlement; you hold the keys, sign your trades.
Base URL
https://commodities.gocube.org/api/v2/commodity/v1
5 minutes

Quick start.

Every market-data endpoint is public. Fetch the markets, then a book and candles:

# 1. all markets
curl https://commodities.gocube.org/api/v2/commodity/v1/markets

# 2. order book + candles
curl "https://commodities.gocube.org/api/v2/commodity/v1/orderbook?symbol=USDT/NGN"
curl "https://commodities.gocube.org/api/v2/commodity/v1/ohlcv?symbol=USDT/NGN&timeframe=1h&limit=100"

To trade, generate an API key and send it as X-API-Key. That’s the whole model — no request signing, no nonces.

Read first

Conventions.

ConceptRule
symbolUnified BASE/QUOTE, uppercase, e.g. USDT/NGN. The same symbol is used everywhere — market data and trading. List them from /markets.
NumbersPrices, sizes and amounts are decimal strings to preserve precision; parse with a decimal library.
TimestampsUnix milliseconds throughout, each paired with an ISO-8601 datetime. OHLCV bucket times are the millisecond open time.
Base / quoteBase = the traded asset; quote = the settlement currency. Price is quote per 1 base; cost is in the quote currency.
FeesA flat 0.15% trading fee applies to every fill, maker and taker.
ErrorsNon-2xx responses return { "error": "message", "status": 4xx }. See the error reference.
Reference

Enumerations.

FieldValuesNotes
sidebuy · sellOrder direction (lowercase).
typelimit · marketLimit orders require price; market orders omit it.
statusopen · closed · canceled · rejectedopen = resting, closed = fully filled.
timeInForceGTCGood-till-cancel (resting limit orders).
takerOrMakertaker · makerYour role in a fill (on My trades).
timeframe1m 5m 15m 1h 4h 1dOHLCV bucket sizes.
Access

Authentication.

Market data is public — no key required. Trading requires an API key issued to your Cube Exchange (Cubemail) account. Send it on every trading request:

header
X-API-Key: cdx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are shown once at creation and stored only as a salted hash — Cube Exchange cannot recover a lost key. A key inherits your account’s balances and permissions. Never embed a key in client-side code; keep it server-side and rotate on any suspicion of exposure.
Credentials

API keys.

Manage keys from your account or the generator below. Programmatic key management is also available with an existing session:

POST/keys
session

Issue a new key. Body { "label": "my-bot" }. Returns the plaintext key once plus its id and prefix.

GET/keys
session

List your keys (prefixes and labels only — never the secret).

POST/keys/:id/revoke
session

Permanently revoke a key.

Sign in with your Cubemail account to generate an API key.

Sign in
Fair use

Rate limits.

Limits are generous and designed for real-time bots and minutely aggregator polling.

SurfaceGuidance
Market dataPoll as often as once per second per endpoint. Books and candles update continuously; there is no benefit to tighter polling.
Data pollingMinutely snapshot polling of market data is fully supported; no key or sign-up required.
TradingSustained order placement/cancel is fine for market making. Burst-cancel-and-replace loops of a few seconds are the intended pattern.
AbuseExcessive traffic may be throttled per key/IP. If you need higher throughput, contact the team.
Public REST

Markets & currencies.

GET/v1/markets
weight 1public

Every listed market — the canonical trading list. Returns an array of market structures.

response json
[
  { "id": "usdtngn", "symbol": "USDT/NGN", "base": "USDT", "quote": "NGN",
    "active": true, "type": "spot", "spot": true,
    "taker": 0.0015, "maker": 0.0015,
    "precision": { "amount": 8, "price": 8 },
    "limits": { "amount": { "min": "1" } } }
]
GET/v1/currencies
weight 1public

Every listed asset, keyed by code — { "USDT": {…}, "NGN": {…} }.

GET/v1/time
weight 1public

Server time — { "timestamp": 1720…, "datetime": "…" }.

GET/v1/status
weight 1public

Exchange status — { "status": "ok", "updated": … }.

Public REST

Tickers.

GET/v1/ticker?symbol=USDT/NGN
weight 1public

Live statistics for one market. Returns a ticker structure — last, bid, ask, 24h high/low and base/quote volume.

GET/v1/tickers
weight 1public

All tickers at once, as a map of { "BASE/QUOTE": ticker }.

Public REST

Order book.

GET/v1/orderbook?symbol=USDT/NGN&limit=50
weight 1public

Aggregated depth — bids high→low, asks low→high, each level [price, amount].

response json
{
  "symbol": "USDT/NGN",
  "bids": [ ["1372.10", "42.5"], ["1372.05", "18.0"] ],
  "asks": [ ["1372.40", "31.2"], ["1372.55", "12.8"] ],
  "timestamp": 1720008000000, "datetime": "2026-07-03T12:00:00.000Z"
}
Public REST

OHLCV.

GET/v1/ohlcv
weight 1public

Candlesticks aggregated from trades — the charting feed.

Query parameters

ParamTypeReqDescription
symbolstringyesUnified symbol, e.g. USDT/NGN.
timeframeenumnoBucket size (default 1h).
sinceintnoStart time, unix ms.
limitintnoMax candles.
response json
[
  [ 1720008000000, "1372.1", "1372.4", "1371.6", "1372.9", "142.5" ]
]  // [ time_ms, open, high, low, close, volume ]
Public REST

Trades.

GET/v1/trades?symbol=USDT/NGN&limit=50
weight 1public

Recent public trades — the tape. Each is a trade structure (id, timestamp, price, amount, cost, side, takerOrMaker).

Public REST

Aggregator data feed.

A public, keyless market-data feed in the industry-standard exchange format consumed by data vendors, aggregators and market terminals — pair-level tickers, full depth and the historical tape. Pair ids here are uppercase BASE_TARGET (e.g. USDT_NGN), and all values are decimal strings.

Feed base URL
https://commodities.gocube.org/api/v2/commodity/feed
GET/feed/tickers
weight 1public

Every trading pair with 24h statistics — the summary feed vendors poll on a schedule.

FieldTypeDescription
ticker_idstringPair id, BASE_TARGET.
base_currency / target_currencystringBase and quote codes.
last_pricestringLast trade price.
base_volume / target_volumestring24h volume in base / quote.
bid / askstringBest bid / ask.
high / lowstring24h high / low.
response json
[
  { "ticker_id": "USDT_NGN", "base_currency": "USDT", "target_currency": "NGN",
    "last_price": "1372.19", "base_volume": "1.04", "target_volume": "1439.83",
    "bid": "1370.0", "ask": "1374.0", "high": "1398.5", "low": "1360.4" }
]
GET/feed/orderbook?ticker_id=USDT_NGN&depth=100
weight 1public

Full order-book depth for one pair. depth caps the levels returned per side.

response json
{ "ticker_id": "USDT_NGN", "timestamp": 1720008000000,
  "bids": [ ["1370.0", "42.5"] ], "asks": [ ["1374.0", "31.2"] ] }
GET/feed/historical_trades?ticker_id=USDT_NGN&type=&limit=100
weight 1public

The completed-trade tape, split into buy and sell arrays. Filter with type=buy or type=sell.

response json
{ "buy":  [ { "trade_id": 961247, "price": "1372.19", "base_volume": "0.0001",
      "target_volume": "0.134", "trade_timestamp": 1720008000000, "type": "buy" } ],
  "sell": [ … ] }
Realtime

WebSocket feed.

Stream the market in realtime over a single connection instead of polling. One socket carries three channels per symbol — the live trade tape, ticker updates and order-book snapshots — pushed as JSON text frames. No key required; the feed is public and read-only.

WebSocket URL
wss://commodities.gocube.org/api/v2/commodity/v1/ws

Subscribe by sending a JSON frame naming the channels you want as channel:SYMBOL (unified BASE/QUOTE). The server acknowledges, then streams matching frames. Send ping to keep the link warm.

Channels

ChannelPushedPayload
tradesAs trades printArray of trade structures — new fills since the last frame.
ticker~1s snapshotA ticker structure — last, bid/ask, 24h stats.
book~1s snapshotOrder book — { bids, asks, timestamp }, each level [price, amount].

Client → server

send json
{ "method": "subscribe",   "params": ["trades:USDT/NGN", "ticker:USDT/NGN", "book:USDT/NGN"] }
{ "method": "unsubscribe", "params": ["book:USDT/NGN"] }
{ "method": "ping" }

Server → client

receive json
{ "event": "welcome", "channels": ["trades","ticker","book"] }
{ "event": "subscribed", "channels": ["trades:USDT/NGN", …] }
{ "channel": "trades", "symbol": "USDT/NGN", "data": [ { "id": "961247", "price": "1372.19", "amount": "0.0001", "side": "buy", "timestamp": 1720008000000 } ] }
{ "channel": "ticker", "symbol": "USDT/NGN", "data": { "last": "1372.19", "bid": "1370.0", "ask": "1374.0", "high": "1398.5", "low": "1360.4", "baseVolume": "1.04" } }
{ "channel": "book",   "symbol": "USDT/NGN", "data": { "bids": [["1370.0","42.5"]], "asks": [["1374.0","31.2"]], "timestamp": 1720008000000 } }
{ "event": "pong" }

Connect

# quick test from a terminal
wscat -c "wss://commodities.gocube.org/api/v2/commodity/v1/ws"
> {"method":"subscribe","params":["trades:USDT/NGN","ticker:USDT/NGN","book:USDT/NGN"]}

The socket also answers at /ws and /feed/ws under the same host. Trades stream only new prints from the moment you subscribe — seed history from /v1/trades. Reconnect and re-subscribe on disconnect; snapshots make the book self-healing.

Guide

Charting & OHLCV.

Build a charting datafeed from /v1/ohlcv: request candles by symbol and timeframe, and page through history with since (unix ms) and limit. Supported timeframes are 1m · 5m · 15m · 1h · 4h · 1d. Each row is [ time_ms, open, high, low, close, volume ], oldest first — ready to map onto any candlestick widget. Pair time-series with /v1/trades for the live tape and /v1/ticker for the header stats.

# last 500 hourly candles for USDT/NGN
curl "https://commodities.gocube.org/api/v2/commodity/v1/ohlcv?symbol=USDT/NGN&timeframe=1h&limit=500"

# a historical window (since = unix ms)
curl "https://commodities.gocube.org/api/v2/commodity/v1/ohlcv?symbol=USDT/NGN&timeframe=1d&since=1717200000000&limit=90"
X-API-Key

Balance.

GET/v1/balance
weight 1API key

Your funds as free, used and total per currency (a balance structure).

response json
{
  "USDT": { "free": "1200.00", "used": "300.00", "total": "1500.00" },
  "NGN":  { "free": "540000",  "used": "0",      "total": "540000" },
  "free": { "USDT": "1200.00", "NGN": "540000" }, "used": { … }, "total": { … }
}
X-API-Key

Orders.

POST/v1/order
weight 1API key

Place an order.

Body

FieldTypeReqDescription
symbolstringyesUnified symbol, e.g. USDT/NGN.
typeenumyeslimit or market.
sideenumyesbuy or sell.
amountstringyesOrder size in base units.
pricestringlimitLimit price (quote per base).
curl -X POST https://commodities.gocube.org/api/v2/commodity/v1/order \
  -H "X-API-Key: $KEY" -H "content-type: application/json" \
  -d '{"symbol":"USDT/NGN","type":"limit","side":"buy","amount":"100","price":"1370"}'

Response 201 — an order structure

json
{ "id": "5231", "symbol": "USDT/NGN", "type": "limit", "side": "buy",
  "price": "1370", "amount": "100", "filled": "0", "remaining": "100",
  "status": "open", "timeInForce": "GTC", "timestamp": 1720008000000 }
POST/v1/order/:id/cancel
weight 1API key

Cancel a resting order (also DELETE /v1/order/:id). Returns the canceled order.

GET/v1/order/:id
weight 1API key

Fetch one order by id.

GET/v1/orders/open
weight 1API key

Your open (resting) orders. Also /v1/orders (all) and /v1/orders/closed (filled). Optional ?symbol=.

X-API-Key

My trades.

GET/v1/mytrades?symbol=USDT/NGN
weight 1API key

Your fills with fee and takerOrMaker. Optional ?symbol= and ?limit=.

Reference

Response structures.

Every resource returns one consistent shape. Prices, sizes and amounts are decimal strings; timestamps are unix milliseconds paired with an ISO-8601 datetime; every structure carries a raw info object with the underlying exchange payload.

Market

FieldTypeDescription
idstringExchange market id.
symbolstringUnified BASE/QUOTE.
base / quotestringAsset codes.
baseId / quoteIdstringExchange-native asset ids.
activeboolTradeable now.
type · spot · marginstring · boolMarket class and capabilities.
taker / makernumberFee rates (0.0015 = 0.15%).
precisionobject{ amount, price } decimal places.
limitsobject{ amount, price, cost, leverage } min/max.
infoobjectRaw exchange payload.

Ticker

FieldTypeDescription
symbolstringUnified symbol.
timestamp / datetimeint / stringms + ISO-8601.
high / lowstring24h high / low.
bid / askstringBest bid / ask.
last / closestringLast trade price.
baseVolume / quoteVolumestring24h volume in base / quote.

Order book

{ symbol, bids: [[price, amount], …], asks: [[price, amount], …], timestamp, datetime } — bids sorted high→low, asks low→high.

OHLCV

An array of arrays, oldest first: [ timestamp_ms, open, high, low, close, volume ].

Trade

FieldTypeDescription
idstringTrade id.
timestamp / datetimeint / stringFill time.
symbolstringUnified symbol.
orderstringYour order id (on My trades).
sidestringbuy / sell.
takerOrMakerstringtaker / maker.
price / amount / coststringFill price, base size, and price×amount (quote).
feeobject{ cost, currency } when known.

Order

FieldTypeDescription
idstringOrder id.
clientOrderIdstringClient-side id (uuid).
timestamp / datetimeint / stringPlacement time.
lastTradeTimestampintTime of the last fill.
symbolstringUnified symbol.
typestringlimit / market.
timeInForcestringGTC.
sidestringbuy / sell.
pricestringLimit price.
amount / filled / remainingstringOriginal, filled and remaining base amount.
coststringFilled cost in the quote currency.
statusstringopen · closed · canceled · rejected.

Balance

A map of { CODE: { free, used, total } } plus flat free, used and total maps. free is available, used is locked in open orders, total = free + used.

Currency

{ id, code, name, active, deposit, withdraw, precision }, keyed by uppercase code.

Guide

Build a market-making bot.

A minimal two-sided quoter — read the reference price, lay a bid and an ask around it, and cancel-and-replace on a loop so your book is always fresh. Size every quote from your real free balance so you never over-commit.

const B = "https://commodities.gocube.org/api/v2/commodity/v1";
const H = { "content-type": "application/json", "X-API-Key": process.env.API_KEY };
const SYMBOL = "USDT/NGN", SPREAD = 0.002, SIZE = "50";       // 20 bps each side
const j = (u, o) => fetch(B + u, o).then(r => r.json());

async function tick() {
  const t = await j("/ticker?symbol=" + encodeURIComponent(SYMBOL));
  const ref = (parseFloat(t.bid) + parseFloat(t.ask)) / 2 || parseFloat(t.last);
  if (!ref) return;

  const open = await j("/orders/open", { headers: H });        // clear our quotes
  await Promise.all(open.map(o =>
    fetch(`${B}/order/${o.id}/cancel`, { method: "POST", headers: H })));

  const bid = (ref * (1 - SPREAD)).toFixed(2);                 // re-quote both sides
  const ask = (ref * (1 + SPREAD)).toFixed(2);
  for (const [side, price] of [["buy", bid], ["sell", ask]])
    await fetch(B + "/order", { method: "POST", headers: H,
      body: JSON.stringify({ symbol: SYMBOL, type: "limit", side, amount: SIZE, price }) });
  console.log("quoted", bid, "/", ask);
}
setInterval(tick, 5000);

Harden it with multiple ladder levels, inventory skew, and balance-capped sizing — never quote more than your free balance. Use /ohlcv for signals and /balance to track inventory.

Reference

Error reference.

Errors return a non-2xx HTTP status with a body of { "error": "message", "status": 4xx }. Each maps to a typed exception so you can catch by kind rather than parse strings.

HTTPExceptionWhen
400BadRequestMalformed request body or parameters.
401AuthenticationErrorMissing or invalid X-API-Key.
403PermissionDeniedThe key lacks permission for this action.
404BadSymbol · OrderNotFoundNo such market or order.
422InvalidOrderBad price/size, below minimum, or price out of band.
422InsufficientFundsNot enough free balance to place the order.
429RateLimitExceededSlow down; retry after a short backoff.
5xxExchangeNotAvailableMatching engine offline or a transient outage — retry.
Versioning

Changelog.

The API is versioned in the path (/v1). Additive changes ship without a version bump; breaking changes get a new version.

2026-07Unified REST API v1 — one symbol format, one response structure per resource, and a typed error hierarchy, across market data and trading.
2026-07API keys for programmatic trading; public OHLCV feed.
2026-05Public spot market-data endpoints and the central-limit order book API.
Ready to build?
Fund your account, generate a key, ship your first bot.
Open the exchange