Strategy API v1
Every decision of a live Killbot strategy — by cursor or pushed to your endpoint — with the position size expressed as a share of capital, so the same capital replicates it 1:1.
Base URL https://api.killbot.cash/api/v1 · auth header X-Api-Key · every successful response is wrapped in { "data": … }.
Start polling in three calls
# 1. what your key can read
curl -s https://api.killbot.cash/api/v1/strategies \
-H "X-Api-Key: $KILLBOT_KEY"
# 2. decisions by cursor — start at 0, then pass the cursor you got back
curl -s "https://api.killbot.cash/api/v1/strategies/killbot-core/events?after=0&limit=100" \
-H "X-Api-Key: $KILLBOT_KEY"
# 3. open positions, to reconcile after downtime
curl -s https://api.killbot.cash/api/v1/strategies/killbot-core/positions \
-H "X-Api-Key: $KILLBOT_KEY"Poll with the last cursor you received. When nothing new happened, cursor equals your after — keep polling with it. Once a second is well inside the limit.
What one decision looks like
{
"data": {
"events": [ {
"id": 151,
"strategyId": "killbot-core",
"kind": "close",
"tradeId": 6549,
"symbol": "ONDOUSDT",
"side": "long",
"riskShare": 0.1483,
"price": 0.43822,
"decidedMs": 1790046006995,
"executedMs": 1790046006995,
"closeReason": "signal_exit"
} ],
"cursor": 151,
"delaySec": 0,
"serverTimeMs": 1790046600000
}
}kind“open” or “close” of a position.tradeIdPosition id — an open and its close share it. Dedupe on (tradeId, kind): never act twice on the same pair.symbolBinance USDT-M perpetual, e.g. ONDOUSDT.side“long” or “short” — the position direction, not the order side.riskSharePosition size as a share of strategy capital. Your size = your capital × riskShare. The sum across open positions can exceed 1 — positions use leverage.priceOur execution price. Use it as the reference for your own slippage control.decidedMs / executedMsWhen the strategy decided, and when our order was filled.closeReason“signal_exit”, “stop_loss”, “risk_limit” or “other”. null on open.Three things integrations get wrong
Sizing
your capital × riskShare — nothing else. If that number falls below the symbol’s minimum order on your account, skip the trade and its close; otherwise you end up short a position you never opened.
Idempotency
Store the cursor where it survives a restart, and dedupe on (tradeId, kind). Webhook delivery is at least once — a timeout after you processed an event brings it back.
Reconciliation
After any downtime, read /positions and make your book match: close what is not there, treat what you missed as missed. Do not replay old events into the market.
Webhooks
On paid plans every decision is POSTed to your HTTPS endpoint as { "type": "strategy.event", "deliveryId": …, "data": { …event… } }, in order and at least once. Headers: X-Killbot-Event-Id, X-Killbot-Timestamp, X-Killbot-Signature = v1= + hex HMAC-SHA256 over "<timestamp>.<raw body>".
import crypto from 'node:crypto';
// req.body must be the RAW bytes, not the parsed object:
// re-serializing JSON changes the bytes and the signature will never match.
export function verify(secret, headers, rawBody) {
const ts = headers['x-killbot-timestamp'];
const sig = headers['x-killbot-signature'];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // replay window
const mac = crypto.createHmac('sha256', secret).update(ts + '.').update(rawBody).digest('hex');
const a = Buffer.from('v1=' + mac);
const b = Buffer.from(String(sig));
return a.length === b.length && crypto.timingSafeEqual(a, b);
}import hmac, hashlib, time
def verify(secret: str, ts: str, body: bytes, sig: str) -> bool:
if abs(time.time() - int(ts)) > 300: # replay window
return False
mac = hmac.new(secret.encode(), ts.encode() + b"." + body, hashlib.sha256).hexdigest()
return hmac.compare_digest("v1=" + mac, sig) # constant time- Answer
2xxwithin 5 s. Anything else is retried 1 s, 2 s, 4 s … up to 5 min. - Later events wait for the retry — you never receive a
closebefore itsopen. - Redirects are not followed. A new subscription starts at the current event; history stays in
/events. - Delivery state for your key:
GET /strategies/killbot-core/webhook.
Plans, delay and limits
Sandbox keys receive events delayed by 15 minutes, and /positions as of now − delaySec; paid keys are real time with delaySec = 0. The limit is 300 requests per minute per key.
400Invalid query parameter (a malformed cursor, limit out of range).401Missing or unknown key.403The key has no access to this strategy.404No such strategy.429Rate limit — 300 requests per minute.Beyond REST
OpenAPI
https://api.killbot.cash/api/v1/openapi.json — generate a typed client in your language instead of hand-writing one.
MCP server
Read-only access to the same data from Claude, Cursor or any MCP client, with your key. Ask us and we send the package.
Reference executor
A Docker image that mirrors the stream on your Binance account — dry-run by default. Your exchange keys stay with you; they never reach us.
Every position on our account carries an exchange stop-loss (6% long, 8% short). We do not manage your account — place your own. The stream is information for your own execution decisions, not investment advice. Futures trading with leverage can lose part or all of the capital committed; past performance does not guarantee future results.