快速开始
本页带你完整跑通第一个 Sparky FAPI 调用:钱包登录 → 创建 API Key → 签名请求 → 下单。示例使用 Avalanche 部署,换链只需替换 Base URL。
1. 钱包登录,获取 JWT
API Key 通过原生 API 创建,需要 EIP-712 登录 得到的 JWT。
import time, requests
from eth_account import Account
from eth_account.messages import encode_typed_data
BASE = "https://api-avax.sparkydex.app"
acct = Account.from_key("0xYourPrivateKey")
addr = acct.address.lower()
nonce_data = requests.get(f"{BASE}/api/v1/auth/nonce/{addr}").json()
typed = nonce_data["typed_data"] # domain + Login 类型 + message
signed = acct.sign_message(encode_typed_data(full_message=typed))
sig = signed.signature.hex()
sig = sig if sig.startswith("0x") else "0x" + sig
jwt = requests.post(f"{BASE}/api/v1/auth/login", json={
"address": addr,
"signature": sig,
"timestamp": typed["message"]["timestamp"],
}).json()["token"]
2. 创建 API Key
r = requests.post(f"{BASE}/api/v1/api-keys",
headers={"Authorization": f"Bearer {jwt}"},
json={"label": "my-bot", "ip_whitelist": ""})
key = r.json()
API_KEY = key["api_key"] # 64 位十六进制 → X-MBX-APIKEY 请求头
API_SECRET = key["secret_key"] # 64 位十六进制 → 只返回一次,立即保存
每个账户每条链最多 30 个 Key。列表 / 更新 / 删除见 API Keys。
3. 给请求签名
所有签名接口都需要 X-MBX-APIKEY、timestamp(毫秒)查询参数和 signature 查询参数。规则与 Binance 相同,但有一处必须注意:
- GET / DELETE — 对 URL-encoded 的查询串签名。
- POST / PUT — 参数放在 JSON body;签名内容为
查询串 + 原始 body(body 字节原样追加,不做 URL-encode),随后原样发送 body。
import hashlib, hmac, json, urllib.parse
def _sign(payload: str) -> str:
return hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha256).hexdigest()
def signed(method: str, path: str, params: dict | None = None, body: dict | None = None):
params = dict(params or {})
params["timestamp"] = int(time.time() * 1000)
qs = urllib.parse.urlencode(params, safe="")
body_str = "" if body is None else json.dumps(body, separators=(",", ":"))
sig = _sign(qs + body_str) # POST/PUT:body 追加到签名负载
url = f"{BASE}{path}?{qs}&signature={sig}"
headers = {"X-MBX-APIKEY": API_KEY, "Content-Type": "application/json"}
r = requests.request(method, url, data=body_str or None, headers=headers)
return r.status_code, r.json()
print(signed("GET", "/fapi/v2/balance"))
时钟正确(Sparky 双向校验 |now − timestamp| ≤ 60 000 ms)、secret 正确、Key 处于 active,就会得到 200 与余额数组。
4. 设置杠杆并下第一单
signed("POST", "/fapi/v1/leverage", body={"symbol": "BTCUSDT", "leverage": 10})
status, order = signed("POST", "/fapi/v1/order", body={
"symbol": "BTCUSDT",
"side": "BUY",
"type": "LIMIT",
"timeInForce": "GTC",
"quantity": "0.010",
"price": "60000",
"newClientOrderId": "my-order-1",
})
print(status, order) # {"orderId": "...", "status": "NEW", ...}
# 按客户端 ID 查询与撤单(GET/DELETE:参数在查询串)
signed("GET", "/fapi/v1/order", params={"symbol": "BTCUSDT", "origClientOrderId": "my-order-1"})
signed("DELETE", "/fapi/v1/order", params={"symbol": "BTCUSDT", "origClientOrderId": "my-order-1"})
5. curl 版本
API_KEY="a1b2c3d4..."; SECRET="f6e5d4c3..."; BASE="https://api-avax.sparkydex.app"
# 先校时
curl -s "$BASE/fapi/v1/time"
# 限价买入:body 追加到签名负载
TS=$(($(date +%s%3N)))
BODY='{"symbol":"BTCUSDT","side":"BUY","type":"LIMIT","timeInForce":"GTC","quantity":"0.010","price":"60000","newClientOrderId":"my-order-1"}'
QS="timestamp=$TS"
SIG=$(echo -n "${QS}${BODY}" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.*= //')
curl -s -X POST "$BASE/fapi/v1/order?$QS&signature=$SIG" \
-H "X-MBX-APIKEY: $API_KEY" -H "Content-Type: application/json" -d "$BODY"
6. 常见错误
-1021 Timestamp outside recv window— 时钟漂移。用GET /fapi/v1/time校时;Sparky 的窗口固定为 60 秒,recvWindow无法加宽。SIGNATURE_INVALID(HTTP 401,{"success":false,"error":{...}}信封)— secret 错误,或 POST/PUT 时对 body 做了 URL-encode / 忘记追加 body。INVALID_API_KEY/API_KEY_DISABLED(HTTP 401)— 该 Key 不存在于当前链的 部署,或已被禁用。IP_NOT_ALLOWED(HTTP 403)— 客户端 IP 不在 Key 的ip_whitelist内。-2019 Margin is insufficient— 通过 Vault 充值流程 充值。-1013— 数量小于lot_size,或名义额超出[min_order_size_usd, max_order_size_usd]。
完整错误码表见 错误码。