Demo exchange — all balances are test funds. Do not send real crypto to any address shown here.

Voracex API

Connect trading bots and portfolio tools with a REST API. Market data is public; account and trading endpoints need an API key and a signed request. No API endpoint can withdraw funds.

Base URLhttps://voracex.com/api/v1Create an API key

Authentication

  1. Create a key on the API keys page. Copy the secret right away: it is shown only once.
  2. Send three headers with every signed request: X-DX-APIKEY (your key), X-DX-TIMESTAMP (current time in milliseconds) and X-DX-SIGNATURE.
  3. The signature is HMAC-SHA256 of timestamp + HTTP method + path with query string + raw body, hex encoded, using the secret as the key.
  4. The timestamp must be within 5 seconds of the server clock (set X-DX-RECV-WINDOW up to 60000 ms if needed). Each signature can be used once.
signature = hex( HMAC_SHA256( secret, timestamp + METHOD + path?query + body ) )

X-DX-APIKEY:    dx_xxxxxxxxxxxxxxxxxxxxxxxx
X-DX-TIMESTAMP: 1760534400000
X-DX-SIGNATURE: 5f0c…(64 hex characters)

Prices and amounts are decimal strings (for example "0.0015") to avoid rounding errors. Times are Unix milliseconds.

Permissions

  • Read-only keys can read balances, orders and trades.
  • Keys with “Allow trading” can also place and cancel spot orders.
  • Withdrawals are never possible with an API key.
  • Add an IP allowlist to a key so it only works from your server.

Endpoints

MethodPathAccessDescription
GET/api/v1/timePublicServer time in ms (sync your clock for signing).
GET/api/v1/marketsPublicSpot markets with tick size, lot size, min notional and fees.
GET/api/v1/ticker?symbol=BTC_USDTPublic24 h stats for one market (omit symbol for all).
GET/api/v1/depth?symbol=BTC_USDT&limit=20PublicOrder book levels [price, quantity], up to 100.
GET/api/v1/trades?symbol=BTC_USDT&limit=50PublicLatest public trades, up to 200.
GET/api/v1/accountSignedBalances (available, locked) and key permissions.
GET/api/v1/orders?symbol=&status=open|closed&limit=SignedYour orders, newest first.
GET/api/v1/order?id=123SignedOne of your orders.
GET/api/v1/myTrades?symbol=&limit=SignedYour fills, newest first.
POST/api/v1/orderTrading keyPlace a limit or market order (JSON body).
DELETE/api/v1/order?id=123Trading keyCancel one open order.
DELETE/api/v1/openOrders?symbol=BTC_USDTTrading keyCancel all your open orders (in one market).

POST /api/v1/order

{
  "symbol": "BTC_USDT",
  "side": "buy",            // "buy" | "sell"
  "type": "limit",          // "limit" | "market"
  "price": "60000",         // limit orders
  "quantity": "0.001",      // limit orders and market sells
  "quoteQuantity": "50"     // market buys: amount of USDT to spend
}

Examples

curl (bash + openssl)

KEY="dx_..."; SECRET="..."
TS=$(date +%s000)
PATH_Q="/api/v1/account"
SIG=$(printf "%s" "${TS}GET${PATH_Q}" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')
curl -s "https://voracex.com${PATH_Q}" \
  -H "X-DX-APIKEY: $KEY" -H "X-DX-TIMESTAMP: $TS" -H "X-DX-SIGNATURE: $SIG"

Node.js 18+

import crypto from "node:crypto";

const KEY = process.env.DX_KEY, SECRET = process.env.DX_SECRET;

async function dx(method, path, body) {
  const ts = Date.now().toString();
  const raw = body ? JSON.stringify(body) : "";
  const sig = crypto.createHmac("sha256", SECRET).update(ts + method + path + raw).digest("hex");
  const res = await fetch("https://voracex.com" + path, {
    method,
    headers: { "content-type": "application/json", "X-DX-APIKEY": KEY, "X-DX-TIMESTAMP": ts, "X-DX-SIGNATURE": sig },
    body: raw || undefined,
  });
  return res.json();
}

console.log(await dx("GET", "/api/v1/account"));
console.log(await dx("POST", "/api/v1/order", { symbol: "BTC_USDT", side: "buy", type: "limit", price: "60000", quantity: "0.001" }));

Python 3

import hashlib, hmac, json, os, time, requests

KEY, SECRET = os.environ["DX_KEY"], os.environ["DX_SECRET"].encode()

def dx(method, path, body=None):
    ts = str(int(time.time() * 1000))
    raw = json.dumps(body, separators=(",", ":")) if body else ""
    sig = hmac.new(SECRET, (ts + method + path + raw).encode(), hashlib.sha256).hexdigest()
    headers = {"content-type": "application/json", "X-DX-APIKEY": KEY, "X-DX-TIMESTAMP": ts, "X-DX-SIGNATURE": sig}
    return requests.request(method, "https://voracex.com" + path, headers=headers, data=raw or None).json()

print(dx("GET", "/api/v1/orders?status=open"))
print(dx("DELETE", "/api/v1/openOrders?symbol=BTC_USDT"))

Errors

Errors return an HTTP status and a JSON body { code, message }.

401AUTH_REQUIREDSignature headers missing.
401INVALID_KEYUnknown or revoked key, or the account is disabled.
401KEY_NOT_SIGNABLEKey created before request signing: create a new one.
401TIMESTAMP_OUT_OF_WINDOWClock drift: use GET /api/v1/time.
401INVALID_SIGNATURESignature doesn't match method, path, timestamp or body.
401REPLAYED_REQUESTThe same signature was sent twice.
403IP_NOT_ALLOWEDRequest IP is not on the key's allowlist.
403TRADING_NOT_ALLOWEDRead-only key used for an order endpoint.
400BAD_PARAM / MISSING_PARAM / BAD_JSONInvalid input.
400INSUFFICIENT_BALANCE / REJECTEDThe order was refused (balance, limits, market halted…).
404UNKNOWN_SYMBOL / UNKNOWN_ORDERNo such market or order.
429RATE_LIMITEDToo many requests.

Rate limits

Public endpoints: 1,200 requests per minute per IP. Signed endpoints: 600 requests per minute per key. Orders: 100 per 10 seconds per key. Over the limit you get HTTP 429.