Get Backtest Result
Retrieve the status and (when ready) the full result of a backtest job.
Endpoint
GET /v1/backtest/jobs/{id}
Weight: 2
Authentication: Required (signed)
Path parameters
| Name | Type | Mandatory | Description |
|---|---|---|---|
id | string | Yes | Job identifier returned by Create Job, e.g. bt_3c91ef. |
Response
A successful response returns the full job object. The result payload is populated only when status is done.
{
"id": "bt_3c91ef",
"status": "done",
"config": {
"template_id": "tpl_grid",
"params": {
"grid_levels": 8,
"upper_price": "72000",
"lower_price": "60000"
},
"symbols": ["BTCUSDT"],
"timeframe": "1h",
"start": "2025-01-01T00:00:00Z",
"end": "2025-12-31T23:59:59Z",
"capital": "10000.00",
"leverage": 1,
"fee_model": "fixed_bps",
"fee_bps": "5"
},
"submitted_at": "2026-04-29T10:15:00Z",
"started_at": "2026-04-29T10:15:08Z",
"finished_at": "2026-04-29T10:17:42Z",
"progress": 1.0,
"result": {
"metrics": {
"sharpe": "1.84",
"sortino": "2.31",
"calmar": "1.12",
"max_drawdown": "-0.142",
"win_rate": "0.638",
"profit_factor": "1.92",
"cagr": "0.187",
"expected_value": "12.43",
"total_trades": 247,
"avg_trade_duration_seconds": 14820
},
"equity_curve": [
["2025-01-01T00:00:00Z", "10000.00"],
["2025-01-02T00:00:00Z", "10031.50"]
],
"trades": [
{
"id": 1,
"side": "buy",
"symbol": "BTCUSDT",
"entry_time": "2025-01-15T08:00:00Z",
"entry_price": "62100.00",
"exit_time": "2025-01-15T14:00:00Z",
"exit_price": "63250.00",
"qty": "0.0805",
"pnl": "92.58",
"fee": "10.18"
}
]
},
"error": null
}
While the job is queued or running, result is null and progress is fractional in [0, 1]. While failed, result is null and error carries the failure detail.
Response fields
| Field | Type | Description |
|---|---|---|
id | string | Job identifier. |
status | enum | queued, running, done, failed, or cancelled. The latter three are terminal. |
config | object | Resolved configuration the job is running with. See Create Job for field meanings. |
submitted_at | string (ISO 8601) | When the job was accepted. |
started_at | string (ISO 8601) | null | When the worker began processing. |
finished_at | string (ISO 8601) | null | When the job entered a terminal state. |
progress | number | Fractional progress in [0, 1]. 1.0 when complete. |
result | object | null | Populated only when status = "done". |
result.metrics | object | Performance metrics. See Metrics for definitions. |
result.equity_curve | array<[ISO 8601, decimal string]> | Equity samples; one entry per simulated day. |
result.trades | array<object> | Closed trades. Each trade has id, side, symbol, entry_time, entry_price, exit_time, exit_price, qty, pnl, fee. |
error | object | null | { "code", "message" } when status = "failed". |
Polling guidance
- Poll at most once every 5 seconds per job. More aggressive polling is rate-limited.
- Stop polling as soon as
statusreaches a terminal value (done,failed,cancelled). - For long-running jobs, prefer exponential backoff after the first few polls.
Pagination of large results
For very long backtests, result.equity_curve and result.trades may eventually be paginated to keep responses manageable. In the initial release the full arrays are always returned in a single response.
Future: opt-in pagination via
?expand=equity_curve&cursor=...(andexpand=trades). The default response will then return only metrics and the first page of each array.
Errors
| HTTP | Code | Cause |
|---|---|---|
| 404 | NOT_FOUND | The job ID does not exist or is not owned by the authenticated key. |
See Errors for shared error semantics.
Example
curl -X GET https://api.pipai.example/v1/backtest/jobs/bt_3c91ef \
-H "X-PipAI-API-Key: $API_KEY" \
-H "X-PipAI-Timestamp: $TS" \
-H "X-PipAI-Signature: $SIG"