REST Api Doc
REST Api Doc
REST Api Endpoints
Base Url: https://api.xoibit.com
Public Api Endpoints (No Authentication Required)
Private Api Endpoints (Authentication Required)
API Authentication Guide (HMAC-SHA256)
Our API uses HMAC-SHA256 signatures for authentication.
Each request must include specific headers for the server to verify its authenticity and integrity.
Required Headers
x-public-key: Your assigned public key (used to identify you).
x-signature: HMAC-SHA256 signature computed using your secret key.
x-timestamp: Current Unix timestamp in milliseconds.
x-nonce: UUID v4 (required for non-GET requests only).
Signature Generation Process
The signature is an HMAC-SHA256 hash of a message built using the following format:
{HTTP_METHOD}{PATH_WITHOUT_QUERY_PARAMS}{REQUEST_BODY}{TIMESTAMP} (for GET requests)
{HTTP_METHOD}{PATH_WITHOUT_QUERY_PARAMS}{REQUEST_BODY}{TIMESTAMP}{NONCE} (for non GET requests)
Example message:
For a POST request to /api/v1/spot/orders with a JSON body:
POST/api/v1/spot/orders{"amount":0.001,"currency_pair_code":"BTCUSDT","order_type":1}17399480000005030ca8f-a2a8-4e8b-8326-4be4ccbbed54
For a POST request to /api/v1/spot/orders/:order_type/:uid/cancel with a JSON body:
POST/api/v1/spot/orders/1/cnclnlkacsncadad7yslsp/cancel{}17399480000005030ca8f-a2a8-4e8b-8326-4be4ccbbed54
For a GET /api/v1/spot/orders?currency_pair=BTC_USDT without a JSON body:
GET/api/v1/spot/orders{}1761114679701
⚠️ Important: - Always exclude query parameters when constructing the message.
- For GET requests, use {} (empty object) as the body.
- Nonce should be strict UUID v4, otherwise you will face nonce format error
Example (Node.js + Axios)
const { createHmac, randomUUID } = require('crypto');
const axios = require('axios');
async function sendSignedRequest() {
const method = 'GET'; // or POST, PUT, DELETE
const path = '/api/v1/spot/orders?currency_pair=BTC_USDT'; // full path (can include query params)
const pathWithoutQueryParams = '/api/v1/spot/orders'; // only used for signature
const body = JSON.stringify({}); // empty for GET
const timestamp = new Date().getTime();
const nonce = randomUUID();
const publicKey = 'Your-public-key';
const secretKey = 'Your-private-key';
// Construct message
const message = `${method}${pathWithoutQueryParams}${body}${timestamp}${method != "GET" ? nonce : ""}`;
// Generate HMAC-SHA256 signature
const signature = createHmac('sha256', secretKey)
.update(message)
.digest('hex');
// Build headers
const headers = {
'x-public-key': publicKey,
'x-signature': signature,
'x-timestamp': timestamp.toString(),
};
if (method !== 'GET') {
headers['x-nonce'] = nonce;
}
// Send request
const response = await axios({
method,
url: `https://api.xoibit.com${path}`,
headers,
data: method === 'GET' ? undefined : JSON.parse(body),
});
console.log('Response:', response.data);
}
sendSignedRequest().catch(console.error);
Step-by-Step Summary
1️⃣ Create a timestamp (Date.now())
2️⃣ Generate a nonce (randomUUID()) — only for non-GET requests
3️⃣ Remove query parameters from the API path
4️⃣ Construct the message: {METHOD}{PATH_WITHOUT_QUERY_PARAMS}{BODY}{TIMESTAMP}
5️⃣ Generate HMAC-SHA256 signature using your secret key
6️⃣ Add headers: x-public-key, x-signature, x-timestamp, and optionally x-nonce
7️⃣ Send the request using Axios or Fetch
Example Header Overview
x-public-key: 90cf64d72ef3119aa7e380fb1836583a71713a49
x-signature: 4a2cd2fbe02f5ff917eab5e6b79f8edcb3cd71a97e98773a74ab87e...
x-timestamp: 1739948000000
x-nonce: 49e084b3-b821-4abf-9a3a-f5ce10e38cd4
Notes
- The timestamp must be within an acceptable time window (e.g., ±60 seconds).
- The nonce must be unique per request (helps prevent replay attacks).
- The message must match exactly between client and server — even a single missing character will cause a signature mismatch.
- Always use pathWithoutQueryParams when computing the signature.
Example Base URL:
https://api.xoibit.com
Example Endpoint:
POST /api/v1/spot/orders