Getting started
Run backtests programmatically with the Open Backtest API.
The Open Backtest API lets you fetch market candles, create backtest
sessions, push trades and read computed statistics — everything you see in
the app, scriptable. Sessions created through the API show up in your
workspace like any other, tagged api/sdk.
Authentication
The API is part of the Pro plan. Create a key in
Settings → API in the app — the full key (obk_…) is shown exactly
once. Pass it on every request in the x-api-key header:
curl http://localhost:3000/api/v1/me \
-H "x-api-key: obk_your_key_here"Base URL: http://localhost:3000/api/v1 in development,
https://api.openbacktest.com/api/v1 in production.
Errors and rate limits
Every non-2xx response uses one envelope:
{ "error": { "code": "NOT_FOUND", "message": "Session not found" } }Codes: UNAUTHORIZED, PRO_REQUIRED, RATE_LIMITED, NOT_FOUND,
UNKNOWN_SYMBOL, SESSION_NOT_ACTIVE, VALIDATION_ERROR,
MARKET_DATA_UNAVAILABLE, INTERNAL.
Keys are limited to 1000 requests/hour (HTTP 429 with a Retry-After
header beyond that). Candle requests draw from an additional per-user
budget shared with the app — one upstream quota per account.
A complete run in curl
BASE=http://localhost:3000/api/v1
KEY=obk_your_key_here
# 1. Who am I?
curl -s $BASE/me -H "x-api-key: $KEY"
# 2. Create a project
PROJECT=$(curl -s -X POST $BASE/projects -H "x-api-key: $KEY" \
-H "Content-Type: application/json" \
-d '{"name":"My strategy","symbol":"BTCUSDT","timeframe":"1h"}')
# 3. Open a session (fees in percent per side)
SESSION=$(curl -s -X POST $BASE/sessions -H "x-api-key: $KEY" \
-H "Content-Type: application/json" \
-d "{\"projectId\":\"$(echo $PROJECT | jq -r .project.id)\",
\"name\":\"Run 1\",\"initialBalance\":10000,
\"feesConfig\":{\"entryFee\":0.1,\"exitFee\":0.1,\"type\":\"percent\"}}")
SID=$(echo $SESSION | jq -r .session.id)
# 4. Push closed trades (batches of up to 500)
curl -s -X POST $BASE/sessions/$SID/trades -H "x-api-key: $KEY" \
-H "Content-Type: application/json" \
-d '{"trades":[{"side":"long","qty":0.1,"entryPrice":60000,
"entryTime":1751000000000,"exitPrice":61000,"exitTime":1751003600000}]}'
# 5. Finish and read the stats
curl -s -X POST $BASE/sessions/$SID/finish -H "x-api-key: $KEY" | jq .statsAll dates are millisecond epochs. Trades are ingested closed (entry + exit in one record) — metrics (fees, P&L, R-multiple) are computed server-side and frozen at ingest.
Prefer Python? The SDK wraps this whole lifecycle in a few lines, with candles as pandas DataFrames.