Open Backtest Docs

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 .stats

All 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.