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.
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.
| Method | Path | Access | Description |
|---|---|---|---|
| GET | /api/v1/time | Public | Server time in ms (sync your clock for signing). |
| GET | /api/v1/markets | Public | Spot markets with tick size, lot size, min notional and fees. |
| GET | /api/v1/ticker?symbol=BTC_USDT | Public | 24 h stats for one market (omit symbol for all). |
| GET | /api/v1/depth?symbol=BTC_USDT&limit=20 | Public | Order book levels [price, quantity], up to 100. |
| GET | /api/v1/trades?symbol=BTC_USDT&limit=50 | Public | Latest public trades, up to 200. |
| GET | /api/v1/account | Signed | Balances (available, locked) and key permissions. |
| GET | /api/v1/orders?symbol=&status=open|closed&limit= | Signed | Your orders, newest first. |
| GET | /api/v1/order?id=123 | Signed | One of your orders. |
| GET | /api/v1/myTrades?symbol=&limit= | Signed | Your fills, newest first. |
| POST | /api/v1/order | Trading key | Place a limit or market order (JSON body). |
| DELETE | /api/v1/order?id=123 | Trading key | Cancel one open order. |
| DELETE | /api/v1/openOrders?symbol=BTC_USDT | Trading key | Cancel 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
}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 return an HTTP status and a JSON body { code, message }.
| 401 | AUTH_REQUIRED | Signature headers missing. |
| 401 | INVALID_KEY | Unknown or revoked key, or the account is disabled. |
| 401 | KEY_NOT_SIGNABLE | Key created before request signing: create a new one. |
| 401 | TIMESTAMP_OUT_OF_WINDOW | Clock drift: use GET /api/v1/time. |
| 401 | INVALID_SIGNATURE | Signature doesn't match method, path, timestamp or body. |
| 401 | REPLAYED_REQUEST | The same signature was sent twice. |
| 403 | IP_NOT_ALLOWED | Request IP is not on the key's allowlist. |
| 403 | TRADING_NOT_ALLOWED | Read-only key used for an order endpoint. |
| 400 | BAD_PARAM / MISSING_PARAM / BAD_JSON | Invalid input. |
| 400 | INSUFFICIENT_BALANCE / REJECTED | The order was refused (balance, limits, market halted…). |
| 404 | UNKNOWN_SYMBOL / UNKNOWN_ORDER | No such market or order. |
| 429 | RATE_LIMITED | Too many requests. |
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.