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β
- A BTSE account β sign up at www.btse.com
- An API key with Trading permission β see Authentication β Step 1
- Python 3.8+ or Node.js 18+ installed
All examples below target testnet so you can experiment without risking real funds. Switch to production URLs when you're ready.
| Product | Production | Testnet |
|---|---|---|
| Spot REST | https://api.btse.com/spot | https://testapi.btse.io/spot |
| Spot WebSocket | wss://ws.btse.com/ws/spot | wss://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.
/public-api/market/v1/marketsPython
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:
| Header | Value |
|---|---|
request-api | Your API key |
request-nonce | Current UTC timestamp in milliseconds |
request-sign | HMAC-SHA384 signature |
Signature input = urlPath + nonce + bodyString
- For GET requests,
bodyStringis empty string"" - For POST/PUT/DELETE,
bodyStringis the raw JSON body
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.
/api/v3.3/orderPython
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:
- Connect to
wss://testws.btse.io/ws/spot - Send
pingevery 15 seconds to keep alive (server respondspong) - Authenticate with
authKeyExpiresto access private topics - Subscribe to topics:
notificationApiV3(order updates),fills(trade fills)
WS authentication signature:
HMAC-SHA384(secret, "/ws/spot" + nonce)
See WebSocket Authentication for details.
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.
/api/v3.3/orderPython
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?β
| Goal | Resource |
|---|---|
| Explore all spot endpoints | Spot API Overview |
| Try endpoints interactively | API Explorer |
| Trade futures | Futures API Overview |
| Manage wallets & withdrawals | Wallet API Overview |
| Build a real-time orderbook | Orderbook Incremental Updates |
| Understand error responses | Error Codes |