Skip to main content

Quickstart β€” Your First Trade in 5 Minutes

This guide walks you through a complete integration: fetch public market data, authenticate, place an order on testnet, and subscribe to real-time updates via WebSocket.


Prerequisites​

Use testnet first

All examples below target testnet so you can experiment without risking real funds. Switch to production URLs when you're ready.

ProductProductionTestnet
Spot RESThttps://api.btse.com/spothttps://testapi.btse.io/spot
Spot WebSocketwss://ws.btse.com/ws/spotwss://testws.btse.io/ws/spot

Step 1 β€” Fetch Public Market Data (No Auth Required)​

Get a list of all tradeable spot markets to find the symbol you want to trade.

Endpoint: GET /public-api/market/v1/markets

No headers required. Returns price, volume, and trading pair configuration for every market.

See Markets Information for the full field reference.

example
GET/public-api/market/v1/markets

Python

import requests

resp = requests.get("https://testapi.btse.io/public-api/market/v1/markets")
symbols = resp.json()["data"]["symbols"]

# Find BTC-USDT
btc = next(s for s in symbols if s["symbol"] == "BTC-USDT")
print(f"BTC-USDT minOrderSize: {btc['minOrderSize']}, active: {btc['active']}")

Node.js

const resp = await fetch(
"https://testapi.btse.io/public-api/market/v1/markets"
);
const { data } = await resp.json();

const btc = data.symbols.find((s) => s.symbol === "BTC-USDT");
console.log(`BTC-USDT minOrderSize: ${btc.minOrderSize}, active: ${btc.active}`);

curl

curl https://testapi.btse.io/public-api/market/v1/markets?symbol=BTC-USDT

Step 2 β€” Sign an Authenticated Request​

Private endpoints require three headers. The signature is HMAC-SHA384(secret, path + nonce + body).

See Authentication for the full specification.

Headers for every private request:

HeaderValue
request-apiYour API key
request-nonceCurrent UTC timestamp in milliseconds
request-signHMAC-SHA384 signature

Signature input = urlPath + nonce + bodyString

  • For GET requests, bodyString is empty string ""
  • For POST/PUT/DELETE, bodyString is the raw JSON body
example

Python β€” signing helper

import hmac, hashlib, time, json, requests

API_KEY = "your-api-key"
API_SECRET = "your-api-secret"
BASE_URL = "https://testapi.btse.io/spot"

def signed_request(method, path, body=None):
nonce = str(int(time.time() * 1000))
body_str = json.dumps(body) if body else ""
message = path + nonce + body_str
signature = hmac.new(
API_SECRET.encode(), message.encode(), hashlib.sha384
).hexdigest()

headers = {
"request-api": API_KEY,
"request-nonce": nonce,
"request-sign": signature,
"Content-Type": "application/json",
}
url = BASE_URL + path
if method == "GET":
return requests.get(url, headers=headers)
elif method == "POST":
return requests.post(url, headers=headers, json=body)
elif method == "DELETE":
return requests.delete(url, headers=headers)

Node.js β€” signing helper

import crypto from "crypto";

const API_KEY = "your-api-key";
const API_SECRET = "your-api-secret";
const BASE_URL = "https://testapi.btse.io/spot";

async function signedRequest(method, path, body) {
const nonce = Date.now().toString();
const bodyStr = body ? JSON.stringify(body) : "";
const message = path + nonce + bodyStr;
const signature = crypto
.createHmac("sha384", API_SECRET)
.update(message)
.digest("hex");

const headers = {
"request-api": API_KEY,
"request-nonce": nonce,
"request-sign": signature,
"Content-Type": "application/json",
};

const resp = await fetch(BASE_URL + path, {
method,
headers,
body: body ? JSON.stringify(body) : undefined,
});
return resp.json();
}

Step 3 β€” Place a Test Order​

Place a limit buy order for BTC-USD on testnet.

Endpoint: POST /api/v3.3/order

Required permission: Trading

The response includes status: 2 (ORDER_INSERTED) on success. See Error Codes β†’ API Status Enum for all status codes.

See Create New Order for the full field reference.

example
POST/api/v3.3/order

Python

order = {
"symbol": "BTC-USD",
"side": "BUY",
"type": "LIMIT",
"price": 20000,
"size": 0.001,
"time_in_force": "GTC",
}

resp = signed_request("POST", "/api/v3.3/order", order)
result = resp.json()
print(f"Order ID: {result[0]['orderID']}, status: {result[0]['status']}")

Node.js

const order = {
symbol: "BTC-USD",
side: "BUY",
type: "LIMIT",
price: 20000,
size: 0.001,
time_in_force: "GTC",
};

const result = await signedRequest("POST", "/api/v3.3/order", order);
console.log(`Order ID: ${result[0].orderID}, status: ${result[0].status}`);

Response

[
{
"status": 2,
"symbol": "BTC-USD",
"orderType": 76,
"price": 20000.0,
"side": "BUY",
"size": 0.001,
"orderID": "990db9b6-2ed4-4c68-b46e-827c88cc3884",
"timestamp": 1660208800123,
"triggerPrice": 0.0,
"trigger": false,
"averageFillPrice": 0.0,
"fillSize": 0.0,
"postOnly": false,
"remainingSize": 0.001,
"time_in_force": "GTC"
}
]

Step 4 β€” Subscribe to Real-Time Updates via WebSocket​

Open a WebSocket connection to receive live order updates and trade fills.

Connection flow:

  1. Connect to wss://testws.btse.io/ws/spot
  2. Send ping every 15 seconds to keep alive (server responds pong)
  3. Authenticate with authKeyExpires to access private topics
  4. Subscribe to topics: notificationApiV3 (order updates), fills (trade fills)

WS authentication signature:

HMAC-SHA384(secret, "/ws/spot" + nonce)

See WebSocket Authentication for details.

example

Python (using websockets library)

import asyncio, websockets, json, hmac, hashlib, time

WS_URL = "wss://testws.btse.io/ws/spot"
API_KEY = "your-api-key"
API_SECRET = "your-api-secret"

async def main():
async with websockets.connect(WS_URL) as ws:
# 1. Authenticate
nonce = str(int(time.time() * 1000))
sig = hmac.new(
API_SECRET.encode(),
f"/ws/spot{nonce}".encode(),
hashlib.sha384,
).hexdigest()

await ws.send(json.dumps({
"op": "authKeyExpires",
"args": [API_KEY, nonce, sig],
}))

# 2. Subscribe to order notifications
await ws.send(json.dumps({
"op": "subscribe",
"args": ["notificationApiV3"],
}))

# 3. Listen for messages
async for msg in ws:
if msg == "pong":
continue
data = json.loads(msg)
print(json.dumps(data, indent=2))

asyncio.run(main())

Node.js (using ws library)

import WebSocket from "ws";
import crypto from "crypto";

const WS_URL = "wss://testws.btse.io/ws/spot";
const API_KEY = "your-api-key";
const API_SECRET = "your-api-secret";

const ws = new WebSocket(WS_URL);

ws.on("open", () => {
// 1. Authenticate
const nonce = Date.now().toString();
const sig = crypto
.createHmac("sha384", API_SECRET)
.update("/ws/spot" + nonce)
.digest("hex");

ws.send(JSON.stringify({
op: "authKeyExpires",
args: [API_KEY, nonce, sig],
}));

// 2. Subscribe to order notifications
ws.send(JSON.stringify({
op: "subscribe",
args: ["notificationApiV3"],
}));

// 3. Keep alive
setInterval(() => ws.send("ping"), 15000);
});

ws.on("message", (msg) => {
const str = msg.toString();
if (str === "pong") return;
console.log(JSON.parse(str));
});

Step 5 β€” Cancel the Test Order​

Clean up by cancelling the order you placed.

Endpoint: DELETE /api/v3.3/order

Pass the orderID from Step 3. See Cancel Order for the full reference.

example
DELETE/api/v3.3/order

Python

resp = signed_request(
"DELETE",
"/api/v3.3/order?symbol=BTC-USD&orderID=990db9b6-2ed4-4c68-b46e-827c88cc3884",
)
print(resp.json())

Node.js

const result = await signedRequest(
"DELETE",
"/api/v3.3/order?symbol=BTC-USD&orderID=990db9b6-2ed4-4c68-b46e-827c88cc3884"
);
console.log(result);

What's Next?​

GoalResource
Explore all spot endpointsSpot API Overview
Try endpoints interactivelyAPI Explorer
Trade futuresFutures API Overview
Manage wallets & withdrawalsWallet API Overview
Build a real-time orderbookOrderbook Incremental Updates
Understand error responsesError Codes