Skip to main content
Killbot for partners

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 2xx within 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 close before its open.
  • 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.