Якщо ваш бот вже працює з Binance USD-M Futures, замініть один базовий URL — і ви одразу на BuyCrypt. Наші користувачі знаходять вашого бота в таблиці лідерів, тестують його на безкоштовному демо-рахунку $1,000 і переходять на реальні ключі, коли переконуються у результаті.
Жодного переписування коду. Жодних специфічних особливостей біржі. Те саме підписання HMAC-SHA256, той самий WebSocket-потік даних користувача, ті самі типи ордерів — все це обгорнуто над нашим движком демо-торгівлі, щоб користувачі могли порівнювати ботів без ризику для капіталу.
Кожен користувач, який підписується, отримує власний демо-рахунок із віртуальним балансом $1,000. Ваш бот торгує на ньому. Вони стежать за PnL у реальному часі, просадкою, відсотком виграшів. Жодного ризику для реального капіталу — і жодних витрат на залучення для вас.
Власний демо-рахунок вашого бота відображається в публічній таблиці лідерів із значком 🤖 БОТ. Користувачі бачать рейтинг PnL поряд із реальними трейдерами. Натискають на рядок, тиснуть «Підключити» — миттєва підписка.
Якщо ваш бот використовує будь-який SDK для Binance Futures (binance-connector-python, python-binance, CCXT тощо), вкажіть його base_url на https://api.buycrypt.com/fapi. HMAC, recvWindow, типи ордерів — ідентичні.
Коли користувач підписується, ми відправляємо POST із щойно виданим API-ключем + секретом на URL вашого вебхука — підписаний 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) і починайте торгувати від його імені.
Більшість SDK для Binance Futures приймають кастомний базовий 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-ключ + секрет для нього на стороні сервера і відправляємо їх POST-запитом на вашу зареєстровану URL-адресу вебхука. Секрет ніколи не повертається користувачу — він передається лише вам через 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 з секретом, яким ми поділилися під час реєстрації. Перевіряйте в константному часі, перш ніж довіряти вмісту. Приклади — у нашому партнерському посібнику.
Базовий URL: https://api.buycrypt.com/fapi. Автентифікація: заголовок X-MBX-APIKEY + підпис HMAC-SHA256 для підписаних ендпоінтів. Вікно прийому: 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. Той самий формат payload, що й у 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 — це увесь онбординг.