---
title: "Run a backtest across a pair universe (async)"
method: POST
path: "/api/v1/backtests/universe"
tags: ["Backtests"]
---

# Run a backtest across a pair universe (async)

`POST /api/v1/backtests/universe`

## Request

- Base URL: `https://tradingstrategies.work`
- URL: `https://tradingstrategies.work/api/v1/backtests/universe`
- Auth: HTTP bearer

Backtests one strategy across a pair universe. Pair cap depends on tier: Pro 50, Power 250 (Power covers crypto-top-250 in one job). Asynchronous — returns only `job_id` + `poll_url`; poll `/api/v1/jobs/{job_id}` until status='completed'. Background runtime ~1.5s × n_pairs, so a 250-pair job takes roughly 6 minutes. Use `universe_id` (e.g. 'crypto-top-10') or `pairs[]`. Benchmarks `bnh_fixed` and `dca_reference_v2` are accepted — run one over the same universe and interval, because an excess over buy-and-hold is not a statement without the buy-and-hold value itself. Results live only in the job response; they are deliberately not persisted to backtest_runs and will not appear in /v1/backtests later. Per-day quota: Pro 5/Tag, Power 50/Tag. [API Pro tier]

## Request body

- object
  - `universe_id` string: Pre-curated crypto universe id from /v1/universes (e.g. 'crypto-top-10', 'crypto-top-250'). Capped by tier (Pro 50, Power 250); a larger universe is rejected, not silently truncated.
  - `pairs` string[]: Explicit pair list (alternative to universe_id).
  - `strategy` string, required: Strategy key from /v1/strategies.
  - `interval` '1d' | '2d' | '3d' | '1w' | '1M', required
  - `date_from` string, date, required
  - `date_to` string, date
  - `capital` number
  - `params` object
  - `filters` object
    - `wma200` boolean
    - `atr_mode` 'off' | 'low' | 'high' | 'expansion'
    - `altcoin_season_mode` 'off' | 'aggressive' | 'conservative'
    - `bullmarket_stage_mode` 'off' | 'early' | 'confirmed' | 'strict'
    - `min_profit_guard_threshold` number, nullable

## Response `202`

Job accepted. Use job_id with /api/v1/jobs/{job_id} to poll.

## Other responses

- `400`: Invalid input — fehlt Pflichtfeld oder Wert außerhalb des erlaubten Bereichs.
- `401`: Unauthenticated — kein gültiger Bearer-Token im Authorization-Header.
- `403`: Tier-Insufficient — Endpoint braucht höheren API-Tier. Response enthält upgrade_url.
- `404`: Not-Found — Resource existiert nicht oder gehört nicht dem aktuellen User.
- `429`: Rate-Limit überschritten — Tier-Quota (hourly/daily) oder Per-Endpoint-Quota erreicht. Retry-After-Header gesetzt.
- `500`: Internal Error.
- `503`: Upstream-Failure — Datenquelle nicht erreichbar (Binance, EODHD, etc.).

---

[API](https://skmtc.dev/tradingstrategies/apis/backtesting-arena-public-api.md) · [All operations](https://skmtc.dev/tradingstrategies/apis/backtesting-arena-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tradingstrategies/apis/backtesting-arena-public-api/revisions/f82e8d6eecd7?raw)
