Если ваш бот уже работает с Binance USD-M Futures, просто смените один base URL — и вы в эфире на BuyCrypt. Наши пользователи находят бота в лидерборде, тестируют его на бесплатном демо-счёте $1,000 и переходят на реальные ключи, когда убеждаются в результате.
Никакого переписывания кода. Никаких биржевых специфических костылей. Та же подпись HMAC-SHA256, тот же WebSocket user-data stream, те же типы ордеров — обёрнуты поверх нашего демо-движка, чтобы пользователи могли сравнивать ботов, не рискуя реальным капиталом.
Каждый подписчик получает собственный демо-счёт с виртуальным балансом $1,000. Ваш бот торгует на нём. Пользователи видят PnL в реальном времени, просадку, процент прибыльных сделок. Никакого риска для реального капитала — и никаких затрат на привлечение с вашей стороны.
Демо-счёт вашего бота отображается в публичном лидерборде со значком 🤖 БОТ. Пользователи видят рейтинг PnL среди реальных трейдеров. Нажимают на строку, жмут «Подключить» — мгновенная подписка.
Если ваш бот использует любой Binance Futures SDK (binance-connector-python, python-binance, CCXT и др.), укажите его base_url на https://api.buycrypt.com/fapi. HMAC, recvWindow, типы ордеров — идентичны.
Когда пользователь подписывается, мы POST-им свежесозданный API key + secret на ваш вебхук — с HMAC-подписью, с повторными попытками при сбое (экспоненциальный бэкофф), с dead-letter для восстановления. Вам не нужно запрашивать учётные данные у пользователя.
Пользователь открывает лидерборд. Аккаунт вашего бота отображается с чипом 🤖 БОТ рядом с именем и счётчиком подписчиков. Нажимает на строку.
На странице профиля бота видит «Подключить к демо-счёту». Один тап создаёт новое демо $1,000 и ваш бот начинает торговать на нём.
Пользователь наблюдает, как бот торгует на его демо дни или недели. PnL, позиции, процент прибыльных сделок — всё в реальном времени в приложении. Если нравится — добавляет реальный Binance API-ключ прямо в BuyCrypt, чтобы перейти с демо на продакшн.
Пользователь добавляет свой реальный Binance API-ключ в BuyCrypt. Мы передаём его на ваш вебхук тем же способом, что и демо-ключ — тот же ивент subscription.created, только уже с боевыми кредами. Одна интеграция покрывает и демо, и live-флоу.
Зарегистрируйте обычный аккаунт на BuyCrypt — как любой пользователь. Сразу после регистрации вам выдаётся бесплатный демо-счёт со стартовым балансом. Никаких заявок, никакой очереди на ревью.
Сгенерируйте API-ключи прямо в мобильном приложении BuyCrypt: My Profile → API keys → нажмите на демо-счёт → Generate. Вы получите свежие apiKey + apiSecret — показываются один раз, скопируйте их в бот. Дальше направьте свой существующий Binance USD-M Futures-бот на https://api.buycrypt.com/fapi — он заработает без правок: тот же HMAC, те же эндпоинты, те же типы ордеров.
Как только мы видим, что на вашем демо идёт API-трейдинг, аккаунт автоматически помечается как бот. Ваш демо появляется в лидерборде с бейджем 🤖 БОТ и публичным профилем — другие пользователи могут найти его и подписаться.
Когда готовы принимать подписчиков — добавьте webhook URL в настройках бот-профиля. Каждый раз, когда пользователь подписывается — на демо или с реальными Binance-ключами — мы шлём POST-ивент subscription.created с API-ключом и секретом для счёта этого пользователя. Сохраняйте (userId, apiKey, apiSecret) и начинайте торговать от его имени.
Большинство Binance Futures SDK принимают кастомный base 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's go-binance, JS node-binance-api — все работают одинаково. Боты на чистом requests.get(...).headers["X-MBX-APIKEY"] = key тоже работают: правило подписи HMAC побайтно идентично.
Когда пользователь BuyCrypt подписывается на вашего бота, мы генерируем пару API key + secret на стороне сервера и отправляем их POST-запросом на ваш зарегистрированный вебхук-URL. Secret никогда не передаётся пользователю — он идёт только вам, по HTTPS, с подписью.
TL;DR: sign up → tap «Generate API key» on your demo → generate a webhook secret → run one Python script → admin approves. ~5 minutes.
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.
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.
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
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
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.
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 — админ ротировал ваш вебхук-секрет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" } }
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 не удались, ивент попадает в нашу dead-letter таблицу — админ может воспроизвести его вручную.
Если ваш эндпоинт падает 10 раз подряд, мы помечаем его как отключённый и прекращаем отправку ивентов. Свяжитесь с нами для повторного включения. Предотвращает блокировку новых подписчиков мёртвым ботом.
Каждое тело запроса подписывается HMAC-SHA256 с секретом, переданным при регистрации. Проверяйте в константном времени перед доверием пейлоаду. Примеры — в нашем партнёрском гайде.
Base URL: https://api.buycrypt.com/fapi. Авторизация: заголовок X-MBX-APIKEY + HMAC-SHA256 подпись на подписанных эндпоинтах. Recv window: 5,000 мс по умолчанию, максимум 60,000 мс.
{}.MARKET, LIMIT, STOP_MARKET, TAKE_PROFIT_MARKET, STOP, TAKE_PROFIT (лимитный), TRAILING_STOP_MARKET. Флаги: reduceOnly, closePosition, timeInForce (GTC/IOC/FOK), newClientOrderId для идемпотентности, workingType, callbackRate.orderId или origClientOrderId.{dualSidePosition: false}.ORDER_TRADE_UPDATE, ACCOUNT_UPDATE, MARGIN_CALL. Структура пейлоада идентична Binance.subscribe/unsubscribe/list_subscriptions — проксируется напрямую в Binance.X-MBX-USED-WEIGHT-1M, X-MBX-ORDER-COUNT-10S, Retry-After при 429.Retry-AfterНикаких заявок, никакой очереди на ревью, никаких интеграционных сборов. Регистрируешься как обычный юзер, генеришь API-ключи в мобильном приложении, направляешь бота на https://api.buycrypt.com/fapi — это весь онбординг.