Skip to content

API Reference — Anboto Trading API v2.0#

Download OpenAPI spec · AsyncAPI (WebSocket) spec

Authentication#

Endpoints marked ApiKeyAuth need four headers on every request:

Header
X-API-KEY required your API key
X-TIMESTAMP required milliseconds since epoch
X-SIGN required signature, standard Base64
X-RECV-WINDOW request validity in ms, default 5000

Signing. Build timestamp + api_key + recv_window + (queryString | jsonBody) — query string in alphabetical key order, exactly as sent. Base64-decode the secret (standard Base64 if it contains +, / or ends with =, otherwise URL-safe). Sign with HMAC-SHA256 (system-generated keys) or RSA-SHA256 (self-generated keys). X-SIGN is the standard Base64 of the signature, not hex. Keys: pro.anboto.xyz/settings/api.

Every sample on this site calls signed_headers(body) / signed_headers_query(params) — the helper for each language, HMAC variant:

BASE=https://api.pro.anboto.xyz
# signed_headers "<query-or-body string>" -> prints curl -H flags
signed_headers() {
  local ts=$(($(date +%s) * 1000))
  local key_hex=$(printf '%s' "$API_SECRET" | base64 -d | xxd -p -c 256)
  local sign=$(printf '%s' "${ts}${API_KEY}5000$1" \
    | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$key_hex" -binary | base64)
  printf -- '-H "X-API-KEY: %s" -H "X-TIMESTAMP: %s" -H "X-RECV-WINDOW: 5000" -H "X-SIGN: %s"' \
    "$API_KEY" "$ts" "$sign"
}
# GET:  curl "$BASE/api/v2/trading/balance?exchange=BINANCE" $(signed_headers "exchange=BINANCE")
# POST: curl -X POST "$BASE/api/v2/trading/order/create" $(signed_headers "$body") \
#         -H "Content-Type: application/json" -d "$body"
import base64, hashlib, hmac, json, time
import requests

BASE = "https://api.pro.anboto.xyz"
RECV_WINDOW = "5000"

def _secret_bytes(secret: str) -> bytes:
    if any(c in secret for c in "+/") or secret.endswith("="):
        return base64.b64decode(secret)
    return base64.urlsafe_b64decode(secret + "=" * (-len(secret) % 4))

def _headers(payload: str) -> dict:
    ts = str(int(time.time() * 1000))
    digest = hmac.new(_secret_bytes(API_SECRET),
                      (ts + API_KEY + RECV_WINDOW + payload).encode(), hashlib.sha256).digest()
    return {"X-API-KEY": API_KEY, "X-TIMESTAMP": ts, "X-RECV-WINDOW": RECV_WINDOW,
            "X-SIGN": base64.b64encode(digest).decode()}

def signed_headers(body: dict) -> dict:            # POST: sign the JSON body you send
    return {**_headers(json.dumps(body)), "Content-Type": "application/json"}

def signed_headers_query(params: dict) -> dict:    # GET: sign the sorted query string
    return _headers("&".join(f"{k}={v}" for k, v in sorted(params.items())))
use base64::{engine::general_purpose::STANDARD, Engine};
use hmac::{Hmac, Mac};
use reqwest::header::HeaderMap;
use sha2::Sha256;

const BASE: &str = "https://api.pro.anboto.xyz";

fn headers(payload: &str) -> HeaderMap {
    let ts = chrono::Utc::now().timestamp_millis().to_string();
    let key = STANDARD.decode(std::env::var("API_SECRET").unwrap()).unwrap();
    let mut mac = Hmac::<Sha256>::new_from_slice(&key).unwrap();
    mac.update(format!("{ts}{}5000{payload}", std::env::var("API_KEY").unwrap()).as_bytes());
    let sign = STANDARD.encode(mac.finalize().into_bytes());
    let mut h = HeaderMap::new();
    h.insert("X-API-KEY", std::env::var("API_KEY").unwrap().parse().unwrap());
    h.insert("X-TIMESTAMP", ts.parse().unwrap());
    h.insert("X-RECV-WINDOW", "5000".parse().unwrap());
    h.insert("X-SIGN", sign.parse().unwrap());
    h
}
fn signed_headers(payload: &serde_json::Value) -> HeaderMap { headers(&payload.to_string()) }
fn signed_headers_query(params: &std::collections::BTreeMap<&str, &str>) -> HeaderMap {
    headers(&params.iter().map(|(k, v)| format!("{k}={v}")).collect::<Vec<_>>().join("&"))
}
const BASE = "https://api.pro.anboto.xyz"

func headers(payload string) map[string]string {
    ts := strconv.FormatInt(time.Now().UnixMilli(), 10)
    key, _ := base64.StdEncoding.DecodeString(os.Getenv("API_SECRET"))
    mac := hmac.New(sha256.New, key)
    mac.Write([]byte(ts + os.Getenv("API_KEY") + "5000" + payload))
    return map[string]string{
        "X-API-KEY":     os.Getenv("API_KEY"),
        "X-TIMESTAMP":   ts,
        "X-RECV-WINDOW": "5000",
        "X-SIGN":        base64.StdEncoding.EncodeToString(mac.Sum(nil)),
    }
}
func signedHeaders(body string) map[string]string { return headers(body) }
func signedHeadersQuery(q url.Values) map[string]string {
    keys := make([]string, 0, len(q))
    for k := range q { keys = append(keys, k) }
    sort.Strings(keys)
    parts := make([]string, 0, len(keys))
    for _, k := range keys { parts = append(parts, k+"="+q.Get(k)) }
    return headers(strings.Join(parts, "&"))
}
static final String BASE = "https://api.pro.anboto.xyz";

static HttpRequest.Builder signed(String path, String payload) throws Exception {
    String ts = Long.toString(System.currentTimeMillis());
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(new SecretKeySpec(Base64.getDecoder().decode(apiSecret), "HmacSHA256"));
    String sign = Base64.getEncoder().encodeToString(
        mac.doFinal((ts + apiKey + "5000" + payload).getBytes(StandardCharsets.UTF_8)));
    return HttpRequest.newBuilder(URI.create(BASE + path))
        .header("X-API-KEY", apiKey).header("X-TIMESTAMP", ts)
        .header("X-RECV-WINDOW", "5000").header("X-SIGN", sign);
}
static HttpRequest signedPost(String path, String jsonBody) throws Exception {
    return signed(path, jsonBody).header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(jsonBody)).build();
}
static HttpRequest signedGet(String pathWithQuery) throws Exception {   // query keys sorted
    String query = pathWithQuery.contains("?") ? pathWithQuery.substring(pathWithQuery.indexOf('?') + 1) : "";
    return signed(pathWithQuery, query).GET().build();
}
import { createHmac } from "node:crypto";

const BASE = "https://api.pro.anboto.xyz";

function headers(payload: string): Record<string, string> {
  const ts = Date.now().toString();
  const sign = createHmac("sha256", Buffer.from(process.env.API_SECRET!, "base64"))
    .update(ts + process.env.API_KEY + "5000" + payload).digest("base64");
  return { "X-API-KEY": process.env.API_KEY!, "X-TIMESTAMP": ts, "X-RECV-WINDOW": "5000", "X-SIGN": sign };
}
export const signedHeaders = (body: unknown) =>
  ({ ...headers(JSON.stringify(body)), "Content-Type": "application/json" });
export const signedHeadersQuery = (params: Record<string, string>) =>
  headers(Object.keys(params).sort().map((k) => `${k}=${params[k]}`).join("&"));
const val BASE = "https://api.pro.anboto.xyz"

fun signed(path: String, payload: String): HttpRequest.Builder {
    val ts = System.currentTimeMillis().toString()
    val mac = Mac.getInstance("HmacSHA256").apply {
        init(SecretKeySpec(Base64.getDecoder().decode(apiSecret), "HmacSHA256"))
    }
    val sign = Base64.getEncoder().encodeToString(mac.doFinal((ts + apiKey + "5000" + payload).toByteArray()))
    return HttpRequest.newBuilder(URI.create(BASE + path))
        .header("X-API-KEY", apiKey).header("X-TIMESTAMP", ts)
        .header("X-RECV-WINDOW", "5000").header("X-SIGN", sign)
}
fun signedPost(path: String, jsonBody: String): HttpRequest =
    signed(path, jsonBody).header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(jsonBody)).build()
fun signedGet(pathWithQuery: String): HttpRequest =              // query keys sorted
    signed(pathWithQuery, pathWithQuery.substringAfter('?', "")).GET().build()
const std::string BASE = "https://api.pro.anboto.xyz";

cpr::Header headers(const std::string& payload) {
    std::string ts = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::system_clock::now().time_since_epoch()).count());
    std::string key = base64_decode(std::getenv("API_SECRET"));
    std::string msg = ts + std::getenv("API_KEY") + "5000" + payload;
    unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int len = 0;
    HMAC(EVP_sha256(), key.data(), key.size(),
         reinterpret_cast<const unsigned char*>(msg.data()), msg.size(), digest, &len);
    return cpr::Header{{"X-API-KEY", std::getenv("API_KEY")}, {"X-TIMESTAMP", ts},
                       {"X-RECV-WINDOW", "5000"}, {"X-SIGN", base64_encode(digest, len)}};
}
cpr::Header signedHeaders(const std::string& body) { return headers(body); }
cpr::Header signedHeadersQuery(const std::map<std::string, std::string>& params) {   // std::map = sorted
    std::string qs;
    for (auto& [k, v] : params) qs += (qs.empty() ? "" : "&") + k + "=" + v;
    return headers(qs);
}
import { createHmac } from "node:crypto";

const BASE = "https://api.pro.anboto.xyz";

function headers(payload) {
  const ts = Date.now().toString();
  const sign = createHmac("sha256", Buffer.from(process.env.API_SECRET, "base64"))
    .update(ts + process.env.API_KEY + "5000" + payload).digest("base64");
  return { "X-API-KEY": process.env.API_KEY, "X-TIMESTAMP": ts, "X-RECV-WINDOW": "5000", "X-SIGN": sign };
}
export const signedHeaders = (body) =>
  ({ ...headers(JSON.stringify(body)), "Content-Type": "application/json" });
export const signedHeadersQuery = (params) =>
  headers(Object.keys(params).sort().map((k) => `${k}=${params[k]}`).join("&"));

Ready-made payloads: Request examples. Full clients: github.com/anbotolabs/examples.

Trading#

Endpoint
GET /api/v2/trading/balance Get balance
GET /api/v2/trading/listenKey Listen key
GET /api/v2/trading/order/byId Get orders
POST /api/v2/trading/order/cancel Cancel order
GET /api/v2/trading/order/cancelAll Cancel all open orders
POST /api/v2/trading/order/cancelMany Cancel many
POST /api/v2/trading/order/create Create order
POST /api/v2/trading/order/createMany Create many orders
POST /api/v2/trading/order/create_multiLegs Create multi legs order
POST /api/v2/trading/order/createMany/multilegs Create many multi legs orders
GET /api/v2/trading/order/find Find orders
GET /api/v2/trading/order/open Get open orders
GET /api/v2/trading/position Get position
GET /api/v2/trading/userTrades Get user trades

Market data#

Endpoint
GET /api/v2/data/exchanges Exchanges
GET /api/v2/data/fundingRateHistory Funding rate history
GET /api/v2/data/instruments Instruments
GET /api/v2/data/lastFundingRates Last funding rates

Status#

Endpoint
GET /status/ping Status

WebSocket streams#

WebSocket overview — endpoints, listenKey auth, keep-alive, subscribe format.

Topic
WS position position
WS balance balance
WS order order
WS trade trade
WS child_order child_order
WS position_risk position_risk
WS ticker ticker
WS ohlcv ohlcv
WS open_interest open_interest
WS Keep-alive (ping/pong) Keep-alive (ping/pong)

Schemas#

All request/response objects: Schemas