跳到主要内容

快速开始

本页带你完整跑通第一个 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.<sparky-domain>"
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-APIKEYtimestamp(毫秒)查询参数和 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.<sparky-domain>"

# 先校时
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]

完整错误码表见 错误码