BuyCrypt
面向机器人开发者

接入你的交易机器人。同款 Binance API。

如果你的机器人已经支持 Binance U 本位合约,只需更换一个基础 URL,即可在 BuyCrypt 上线。我们的用户会在排行榜中发现你的机器人,先用免费的 $1,000 模拟账户试用,满意后再升级为真实密钥。

无需重写代码,没有交易所特有的怪癖。相同的 HMAC-SHA256 签名、相同的 WebSocket 用户数据流、相同的订单类型——全部封装在我们的模拟交易引擎之上,用户无需承担资金风险即可对比不同机器人。

为什么选择 BuyCrypt

面向交易机器人的模拟优先分发

每位用户 $1,000 免费模拟金

每位订阅用户都会获得一个拥有 $1,000 虚拟余额的专属模拟账户,由你的机器人进行交易。他们可以实时查看 PnL、回撤、胜率,无需承担真实资金风险——你也无需承担获客成本。

排行榜曝光

你的机器人专属模拟账户会以 🤖 БОТ 徽章出现在公开排行榜中。用户可以看到它在真实交易者中的 PnL 排名。点击该行,点按“Connect”即可立即订阅。

零代码改动

如果你的机器人使用任意 Binance 合约 SDK(binance-connector-pythonpython-binance、CCXT 等),只需将其 base_url 指向 https://api.buycrypt.com/fapi。HMAC、recvWindow、订单类型——完全一致。

Webhook 交付密钥

当用户订阅时,我们会将新生成的 API key + secret 通过 POST 发送到你的 webhook URL——经 HMAC 签名,失败后按指数退避重试,并可从死信队列中恢复。你永远无需向用户索要凭证。

用户旅程

用户如何发现并订阅你的机器人

1

发现

用户打开排行榜,你的机器人账户会在用户名旁显示 🤖 БОТ 标签及订阅者数量。他们点击该行。

2

模拟试用

在机器人的资料页面,他们会看到“连接模拟账户”。轻点一下即可为其创建一个全新的 $1,000 模拟账户,你的机器人随即开始交易。

3

观察并决定

用户会观察机器人在模拟账户上交易数天甚至数周。PnL、持仓、胜率——应用内实时可见。如果满意,他们会在 BuyCrypt 内输入真实的 Binance API 密钥,从模拟升级到实盘。

4

升级

用户在 BuyCrypt 内添加真实的 Binance API 密钥。我们会以交付模拟密钥同样的方式将其发送到你的 webhook——同样的 subscription.created 事件,只是换成了他们的生产环境凭证。一次接入即可覆盖模拟与实盘两种流程。

开发者接入

如何将你的机器人接入 BuyCrypt

1

注册

注册一个普通的 BuyCrypt 账户——流程与普通用户完全相同。注册的那一刻,你就会获得一个带起始余额的免费模拟账户。无需申请表,无需审核排队。

2

通过 API 交易你的模拟账户

直接在 BuyCrypt 移动应用内生成 API 密钥:我的资料 → API 密钥 → 点击你的模拟账户 → 生成。系统会显示一次全新的 apiKey + apiSecret——请复制到你的机器人中。然后将你现有的 Binance U 本位合约机器人指向 https://api.buycrypt.com/fapi,即可直接运行——相同的 HMAC、相同的接口、相同的订单类型。

3

自动标记为机器人

一旦我们检测到你的模拟账户上出现 API 驱动的交易,你的账户就会被自动标记为机器人。你的模拟账户会以 🤖 БОТ 标签和公开资料的形式出现在排行榜中,方便其他用户发现并订阅。

4

(可选)通过 webhook 接收订阅者

当你准备好接收订阅者时,请在设置中为你的机器人资料添加一个 webhook URL。每当有用户订阅——无论是模拟账户还是真实 Binance 密钥——我们都会 POST 一个 subscription.created 事件,附带该用户账户的 API key + secret。保存 (userId, apiKey, apiSecret) 并开始代其交易。

即插即用

复用你现有的 Binance 合约机器人

大多数 Binance 合约 SDK 都支持自定义基础 URL。以下是一个典型 Python 机器人所需的全部改动:

# before — trading on real Binance
from binance.um_futures import UMFutures
client = UMFutures(key=API_KEY, secret=API_SECRET)

# after — trading on a BuyCrypt user's demo
from binance.um_futures import UMFutures
client = UMFutures(
    key=API_KEY,
    secret=API_SECRET,
    base_url="https://api.buycrypt.com/fapi",   # <- the only line that changes
)

# everything below is identical to your existing code
client.new_order(symbol="BTCUSDT", side="BUY", type="MARKET", quantity=0.01)
client.account()
client.cancel_open_orders(symbol="BTCUSDT")

CCXT、python-binance、Go 的 go-binance、JS 的 node-binance-api——都以相同方式工作。纯粹使用 requests.get(...).headers["X-MBX-APIKEY"] = key 的机器人同样可用;HMAC 签名规则完全一致(字节级相同)。

Webhook

我们如何将 API 密钥送达你的系统

当 BuyCrypt 用户订阅你的机器人时,我们会在服务端为该用户生成专属的 API key + secret,并通过 HTTPS 以签名方式 POST 到你注册的 webhook URL。密钥永远不会返回给用户——只会发送给你。

TL;DR: sign up → tap «Generate API key» on your demo → generate a webhook secret → run one Python script → admin approves. ~5 minutes.

Step 1 — Sign up

Open buycrypt.com/terminal (or the mobile app). Sign in via Google or phone. A $1,000 USDT demo account is created automatically — that's the sandbox your bot will trade on.

Step 2 — Generate your trading API key (in the app)

In the app: Profile → API Keys → tap your demo account → «Bot API keys» → Generate. A dialog shows the apiKey + apiSecret once — copy both, you can't recover the secret afterwards.

# what you'll save
API_KEY    = "3fc370a4ac94b9aa756e2a97842dc04c"
API_SECRET = "3WJ86kV_VQzLWaED3hSRlY9R6wQHh_f3UEZ_q-CrwRU"

Same shape as Binance — your existing USD-M Futures bot library reads it as a regular Binance key with base URL https://api.buycrypt.com/fapi.

Step 3 — Generate your webhook signing secret

A second secret, separate from API_SECRET. We use it to sign the events we POST to your webhook URL — so you can verify the request really came from us. You generate it on your side; we encrypt-store it but never reveal back:

# any of these works — pick one. Save the output.
$ openssl rand -hex 32                          # macOS / Linux
$ python3 -c "import secrets; print(secrets.token_hex(32))"   # cross-platform

# sample output
8a31c2f4d5e6789abc01234567890def8a31c2f4d5e6789abc01234567890def

Step 4 — Register the bot (one signed POST)

Drop your three secrets into one signed POST. Save this as register_bot.py and run it once. Works on any OS with Python 3.10+ and pip install requests:

import hmac, hashlib, time, urllib.parse, requests

# ─── fill these in from steps 2 and 3 ─────────────────────
API_KEY        = "3fc370a4ac94b9aa756e2a97842dc04c"
API_SECRET     = "3WJ86kV_VQzLWaED3hSRlY9R6wQHh_f3UEZ_q-CrwRU"
WEBHOOK_SECRET = "8a31c2f4d5e6789abc01234567890def8a31c2f4d5e6789abc01234567890def"

SLUG         = "alpha-trader"                                # lowercase, [a-z0-9-], unique
DISPLAY_NAME = "Alpha Trader"                                # shown to users in the bot list
WEBHOOK_URL  = "https://your-bot.example.com/buycrypt/hook"   # MUST be HTTPS, public
# ──────────────────────────────────────────────────────────

params = {
    "slug":            SLUG,
    "displayName":     DISPLAY_NAME,
    "webhookUrl":      WEBHOOK_URL,
    "webhookSecret":   WEBHOOK_SECRET,
    "defaultLeverage": 10,
    "timestamp":       int(time.time() * 1000),
}
qs  = urllib.parse.urlencode(params)
sig = hmac.new(API_SECRET.encode(), qs.encode(), hashlib.sha256).hexdigest()

r = requests.post(
    "https://api.buycrypt.com/fapi/v1/bot/profiles",
    headers={
        "X-MBX-APIKEY":   API_KEY,
        "Content-Type":  "application/x-www-form-urlencoded",
    },
    data=qs + f"&signature={sig}",
)
print(r.status_code, r.json())

Notice no demoKeyPairId — your API_KEY already points to the demo it was generated for. Need to register against a different demo? Generate a separate API key for it (step 2 again).

Expected output:

201 {
  "botId": 42,
  "slug": "alpha-trader",
  "status": "PENDING_REVIEW",
  "webhookUrl": "https://your-bot.example.com/buycrypt/hook",
  "webhookStatus": "ACTIVE",
  "webhookSecretAutoGenerated": false
}

Common errors:

{"code":-2010, "msg":"Slug already in use."}                # pick another slug
{"code":-1102, "msg":"webhookSecret must be at least 32..."}  # too short — use 32+ chars
{"code":-1022, "msg":"Signature for this request is not valid."}  # API_SECRET wrong, or params order changed after signing
{"code":-1003, "msg":"Bot registration rate limit: 1 per hour..."}  # wait it out

Step 5 — Wait for approve, then receive events

Bot lands in PENDING_REVIEW. Our admin sees your request immediately and approves it. To check status anytime:

import hmac, hashlib, time, urllib.parse, requests

API_KEY    = "3fc370a4..."
API_SECRET = "3WJ86kV..."

qs  = urllib.parse.urlencode({"timestamp": int(time.time() * 1000)})
sig = hmac.new(API_SECRET.encode(), qs.encode(), hashlib.sha256).hexdigest()
r = requests.get(
    f"https://api.buycrypt.com/fapi/v1/bot/profiles?{qs}&signature={sig}",
    headers={"X-MBX-APIKEY": API_KEY},
)
print(r.json())   # [{"botId":42, "status":"ACTIVE", ...}] when approved

Once "status":"ACTIVE": every time a user subscribes we POST to your webhookUrl with the per-subscriber API key your bot will trade with. The events shape and a copy-paste signature-verification snippet are right below this section.

Lost your webhook secret? Pick a new one and rotate (same signing pattern as registration):

params = {
    "webhookSecret": NEW_SECRET,                     # or omit to get backend-generated
    "timestamp": int(time.time() * 1000),
}
qs  = urllib.parse.urlencode(params)
sig = hmac.new(API_SECRET.encode(), qs.encode(), hashlib.sha256).hexdigest()
requests.post(
    "https://api.buycrypt.com/fapi/v1/bot/profiles/42/webhook/rotate-secret",
    headers={"X-MBX-APIKEY": API_KEY,
             "Content-Type": "application/x-www-form-urlencoded"},
    data=qs + f"&signature={sig}",
)

Old secret invalid the second the new one saves. Rate limit: 10 rotations/hour per bot.

Webhook event shapes (what we POST to you)

subscription.created —— 用户刚刚订阅

POST https://your-bot.example.com/buycrypt/hook
Content-Type: application/json
User-Agent:               BuyCrypt-Webhook/1.0
X-BuyCrypt-Event:         subscription.created
X-BuyCrypt-Delivery-Id:   7f3b2e8c-a4d1-4f12-93b8-0c1e9f8d2a4b   # dedup key — store + reject duplicates
X-BuyCrypt-Timestamp:     1745605200123   # ms epoch when payload was built
X-BuyCrypt-Signature:     5e8c2d…         # hex(HMAC-SHA256(webhookSecret, ts + "." + body))

{
  "event":        "subscription.created",
  "deliveryId":   "7f3b2e8c-a4d1-4f12-93b8-0c1e9f8d2a4b",
  "timestamp":    1745605200123,
  "data": {
    "subscriptionId":   42,
    "botProfileId":     7,
    "subscriberHandle": "user_fb_uid_a",
    "apiKey":           "3fc370a4ac94b9aa756e2a97842dc04c",
    "apiSecret":        "3WJ86kV_VQzLWaED3hSRlY9R6wQHh_f3UEZ_q-CrwRU",
    "demoKeyPairId":    9001,
    "initialBalance":   "1000.00000000",
    "permissions":      "READ_TRADE",
    "ipWhitelist":      "",
    "createdAt":        "2026-04-25T18:00:00Z"
  }
}

subscription.deleted —— 用户已断开,密钥已禁用

X-BuyCrypt-Event: subscription.disconnected

{
  "event":      "subscription.disconnected",
  "deliveryId": "…",
  "timestamp":  …,
  "data": {
    "subscriptionId":  42,
    "botProfileId":    7,
    "apiKey":          "3fc370a4…",
    "reason":          "USER_UNSUBSCRIBED",
    "disconnectedAt":  "2026-04-25T18:30:00Z"
  }
}

secret.regenerated —— 管理员已轮换你的 webhook secret

X-BuyCrypt-Event: secret.regenerated

{
  "event":      "secret.regenerated",
  "deliveryId": "…",
  "timestamp":  …,
  "data": {
    "subscriptionId":       42,
    "apiKey":               "3fc370a4…",
    "newApiSecret":         "new_plaintext_keep_old_valid_24h",
    "oldSecretValidUntil":  "2026-04-26T18:00:00Z"
  }
}

Verify the signature (constant-time)

Use the raw request body bytes — DO NOT parse JSON first and re-serialize, you'll lose key order and signatures will diverge. Always compare in constant time.

# Python (FastAPI / Flask)
import hmac, hashlib, time

WEBHOOK_SECRET = "whsec_aGVsbG8gd29ybGQ_..."   # whsec_…43 chars

def verify(headers, body_bytes):
    sig = headers["X-BuyCrypt-Signature"]
    ts  = int(headers["X-BuyCrypt-Timestamp"])

    # anti-replay: reject if too old
    if abs(time.time() * 1000 - ts) > 5 * 60 * 1000:
        return False

    payload = f"{ts}.".encode() + body_bytes
    expected = hmac.new(WEBHOOK_SECRET.encode(), payload, hashlib.sha256).hexdigest()

    return hmac.compare_digest(expected, sig)
// Node.js / Express — read RAW body, not parsed JSON
const crypto = require('crypto');
const SECRET = 'whsec_aGVsbG8gd29ybGQ_...';

app.post('/buycrypt/hook',
  express.raw({ type: 'application/json' }),   // raw, not json()!
  (req, res) => {
    const sig = req.headers['x-buycrypt-signature'];
    const ts  = parseInt(req.headers['x-buycrypt-timestamp'], 10);

    if (Math.abs(Date.now() - ts) > 5 * 60 * 1000) return res.status(401).end();

    const expected = crypto.createHmac('sha256', SECRET)
      .update(`${ts}.`).update(req.body).digest('hex');

    if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig))) {
      return res.status(401).end();
    }
    // req.body is a Buffer here — JSON.parse(req.body.toString('utf8'))
    res.sendStatus(200);
});

重试策略

共 6 次尝试,按指数退避:1 分钟、5 分钟、30 分钟、2 小时、6 小时、12 小时。全部 6 次失败后,事件会进入我们的死信表,管理员可以重放。

自动禁用

如果你的接口连续失败 10 次,我们会将其标记为禁用并停止发送事件。请联系我们重新启用。这可以防止失效的机器人无限期地阻挡新订阅者。

签名验证

每个请求体都会使用注册时共享的密钥进行 HMAC-SHA256 签名。请在信任负载之前以恒定时间校验签名。示例请参见我们的合作伙伴指南。

API 概览

我们支持的全部 Binance U 本位合约方法

基础 URL:https://api.buycrypt.com/fapi。鉴权:X-MBX-APIKEY 请求头 + 签名接口上的 HMAC-SHA256 签名。Recv window:默认 5,000 ms,最大 60,000 ms。

公开市场数据(无需鉴权)

GET
/v1/ping
健康检查。返回 {}
GET
/v1/time
服务器时间(毫秒)——同步你的时钟以避免 recvWindow 不匹配。
GET
/v1/exchangeInfo
交易对、过滤器、精度、杠杆档位。
GET
/v1/ticker/price · /ticker/24hr · /ticker/bookTicker
最新成交价 · 24 小时统计 · 最优买卖价。
GET
/v1/depth?symbol=&limit=
订单簿快照(limit ∈ {5,10,20,50,100,500,1000})。
GET
/v1/klines
任意周期的 OHLCV K 线(1m、5m、1h、4h、1d)。
GET
/v1/markPrice · /v1/fundingRate · /v1/premiumIndex
用于强平计算的标记价格 · 资金费率历史 · 溢价指数。
GET
/v1/trades · /v1/aggTrades
最近成交与归集成交。

账户与持仓(需签名)

GET
/v1/account · /v2/account · /v3/account
完整账户快照——余额、总保证金、各币种明细、当前持仓。三个路径版本返回相同的负载(兼容 Binance)。
GET
/v2/balance · /v3/balance
各币种钱包余额。我们仅提供 USDT。
GET
/v2/positionRisk · /v3/positionRisk
当前持仓,包含标记价格、开仓价格、未实现盈亏、强平价格。
GET
/v1/userTrades · /v1/income · /v1/commissionRate · /v1/leverageBracket
交易历史 · 已实现收益 · 各交易对费率 · 杠杆档位。

交易(需签名)

POST
/v1/order
下单。支持 MARKETLIMITSTOP_MARKETTAKE_PROFIT_MARKETSTOPTAKE_PROFIT(限价版)、TRAILING_STOP_MARKET。参数:reduceOnlyclosePositiontimeInForce(GTC/IOC/FOK)、用于幂等的 newClientOrderIdworkingTypecallbackRate
GET
/v1/order
通过 orderIdorigClientOrderId 查询单个订单。
DELETE
/v1/order
取消单个订单。
DELETE
/v1/allOpenOrders?symbol=X
一次性取消某交易对下的所有挂单。
GET
/v1/openOrders
当前所有活跃(未成交、未取消)的订单。
GET
/v1/allOrders
订单历史。默认返回最近 500 条。
POST
/v1/leverage · /v1/marginType · /v1/positionMargin
设置杠杆(1×–125×)· 逐仓/全仓 · 追加逐仓保证金。
GET
/v1/positionSide/dual
对冲模式标志。我们目前仅支持单向持仓——返回 {dualSidePosition: false}

用户数据 WebSocket(私有)

POST
/v1/listenKey
创建一个 60 分钟有效期的 listenKey,用于 WS 握手鉴权。
PUT
/v1/listenKey
将 listenKey 的有效期再延长 60 分钟。请每隔 < 60 分钟调用一次以保持连接活跃。
DELETE
/v1/listenKey
关闭时销毁 listenKey。
WS
wss://api.buycrypt.com/fapi/ws/<listenKey>
推送订单、余额、持仓相关事件:ORDER_TRADE_UPDATEACCOUNT_UPDATEMARGIN_CALL。负载结构与 Binance 相同。

市场数据 WebSocket(公开)

WS
wss://api.buycrypt.com/fapi/stream?streams=btcusdt@trade/btcusdt@kline_1m
多流订阅。支持 subscribe/unsubscribe/list_subscriptions 控制消息——直通上游 Binance。
限流与错误

限流与错误代码

按 API 密钥分桶限流

  • 权重:2,400 / 分钟
  • 下单:300 / 10 秒
  • 签名读取:1,200 / 分钟
  • 每次响应的请求头:X-MBX-USED-WEIGHT-1MX-MBX-ORDER-COUNT-10S,429 时附带 Retry-After

常见错误代码

  • -1003 请求过多——请根据 Retry-After 退避
  • -1021 时间戳超出 recvWindow
  • -1022 签名无效
  • -1102 缺少必填参数
  • -1116 订单类型无效
  • -2010 订单被拒绝(余额不足等)
  • -2011 未知订单
  • -2014 API 密钥格式无效
  • -2015 API 密钥、IP 或权限无效
  • -2019 保证金不足

准备好接入你的机器人了吗?

无需申请表,无需审核排队,无需接入费用。像普通用户一样注册,在移动应用中生成 API 密钥,将你的机器人指向 https://api.buycrypt.com/fapi——接入流程就是这么简单。