---
title: "Get Model History"
method: GET
path: "/v1/models/{model}/history"
tags: ["Models"]
---

# Get Model History

`GET /v1/models/{model}/history`

## Request

- Base URL: `https://api.ensemble.markets` (the document declares no server; this is the origin it was published from)
- URL: `https://api.ensemble.markets/v1/models/{model}/history`
- Auth: HTTP bearer

The model's history over a window, in the blocks you ask for (public or owner).

`dates` is shared by every per-day block. Member models are multiplied through in `allocation` and expanded in `tree`; node weights are fractions of this model at every depth, and `labels` names every key. `latest` is the current allocation plus the latest rebalance decision resolved through each member. `metrics` and `fees` describe the same window. The window defaults to the model's default view (`window` on the fact sheet); `full_history=true` reveals everything computed. `run_id` reads a snapshot run instead of the live history.

## Path parameters

- `model` string, required: Model ID (model_... or legacy m-...), slug, symbol or exact name

## Query parameters

- `include` string[]: Blocks to return: returns (daily gross returns), allocation (daily weights resolved to tickers plus CASH, with the rebalance ledger; positions and holdings are aliases), tree (daily weights with member models expanded), latest (the current allocation and target allocation), custom (the model's own diagnostics), metrics (performance figures), fees (net-of-fee overlay, Business)
- `run_id` string, nullable: Read this run's result instead of the live history
- `start_date` string, date, nullable: Earliest bar to return (YYYY-MM-DD, inclusive). Omit for the beginning of the series (for a model, its default view start).
- `end_date` string, date, nullable: Latest bar to return (YYYY-MM-DD, inclusive). Omit for the end of the series.
- `full_history` boolean: Models only: return everything computed instead of starting at the model's default view start (see the fact sheet's `window`). Ignored when start_date is given.
- `management_fee` number: Annual management fee as a fraction, e.g. 0.01 for 1% (`include=fees`)
- `financing_rate` number: Annual rate on gross exposure above 100%, as a fraction (`include=fees`)
- `commission_bps` number: Commissions in basis points of traded notional (`include=fees`)
- `slippage_bps` number: Slippage in basis points of traded notional (`include=fees`)

## Response `200`

Successful Response

- ModelHistory: A model's history over one window, in the blocks asked for. `dates` is shared by every per-day block (`returns`, `allocation`, `tree`, `custom.series`, `fees`) and is sent only when one of them is requested; a `metrics` or `latest` read carries no per-day data. Blocks not requested are null.
  - `start_date` string, date, nullable: Window start applied (inclusive); the model's default when none was requested
  - `end_date` string, date, nullable: Window end applied (inclusive); null means through the last bar
  - `full_history` boolean: True when the model's default view start was bypassed
  - `run_id` string, nullable: The run whose result this is (the live run by default)
  - `dates` string[], nullable: Bar dates shared by the per-day blocks; null when none of them was requested
  - `availability` ModelAvailability: Data availability recorded by the run: raw facts, not settings.
    - `partial` string, nullable: First computed bar (some members may still be missing)
    - `complete` string, nullable: First bar on which every universe member has data
    - `members` object, nullable: First bar with data for each universe member, {symbol: date}
    - `members_last` object, nullable: Last bar with data for each universe member, {symbol: date}, as the run saw it. A member behind the others lagged the final bar or has ended; the latest target was decided without it.
    - `backfills` object, nullable: History extensions the run applied, {symbol: source}. Present when a holding's series was extended before its own inception.
  - `returns` number[], nullable: Daily gross returns
  - `allocation_change_indices` integer[], nullable: Indices into `dates` where the allocation differs from the prior day
  - `rebalance_indices` integer[], nullable: Indices into `dates` on which a target filled, from the rebalance ledger. Null when the ledger does not cover the whole history, so a reader must not infer rebalance days from a drifting allocation.
  - `rebalance_count` integer, nullable: Exact number of filled rebalance dates in this window, from complete ledger coverage or a full-history total. Null when unknown.
  - `allocation` object[], nullable: One weight dict per day, resolved to tickers plus CASH with member models multiplied through. The current (drifted) allocation series.
  - `rebalances` RebalanceEntry[], nullable: The model's rebalance decisions inside the window, oldest first
    - `decision_date` string, nullable
    - `fill_date` string, nullable: Null while pending
    - `status` 'pending' | 'filled', required
    - `weights` object, required
  - `rebalances_truncated` boolean, nullable: True when the stored ledger was capped and older decisions are missing
  - `tree` array[], nullable: One node list per day; member models expanded with their own holdings
    - PositionNode[]
      - `id` string, required: Member model ID, ticker, or CASH
      - `weight` number, required
      - `as_of` string, nullable: Book date the member's allocation was read from (latest view only)
      - `children` PositionNode[], nullable: The member's own allocation; absent for assets and cash
  - `labels` object: Symbol, name, type and depth for every key in `allocation`, `tree` and `rebalances`
  - `latest` ModelLatest: The most recent book and the latest decision, resolved through members.
    - `as_of` string, nullable: Date of the latest book
    - `allocation` object, required: Current allocation, resolved to tickers plus CASH
    - `tree` PositionNode[], required
      - `id` string, required: Member model ID, ticker, or CASH
      - `weight` number, required
      - `as_of` string, nullable: Book date the member's allocation was read from (latest view only)
      - `children` PositionNode[], nullable: The member's own allocation; absent for assets and cash
    - `target` TargetAllocation: The model's latest rebalance decision, what a follower should hold. Distinct from the daily book, which is what the backtest held after price drift. `pending` means the decision was made on the last bar and fills at the next session's close. Members contribute their own latest decisions.
      - `decision_date` string, nullable
      - `fill_date` string, nullable: Null while pending
      - `status` 'pending' | 'filled', required
      - `allocation` object, required: Resolved to tickers plus CASH
      - `tree` PositionNode[], required
        - `id` string, required: Member model ID, ticker, or CASH
        - `weight` number, required
        - `as_of` string, nullable: Book date the member's allocation was read from (latest view only)
        - `children` PositionNode[], nullable: The member's own allocation; absent for assets and cash
    - `previous_target` TargetAllocation: The model's latest rebalance decision, what a follower should hold. Distinct from the daily book, which is what the backtest held after price drift. `pending` means the decision was made on the last bar and fills at the next session's close. Members contribute their own latest decisions.
      - `decision_date` string, nullable
      - `fill_date` string, nullable: Null while pending
      - `status` 'pending' | 'filled', required
      - `allocation` object, required: Resolved to tickers plus CASH
      - `tree` PositionNode[], required
        - `id` string, required: Member model ID, ticker, or CASH
        - `weight` number, required
        - `as_of` string, nullable: Book date the member's allocation was read from (latest view only)
        - `children` PositionNode[], nullable: The member's own allocation; absent for assets and cash
    - `unresolved_members` string[]: Members whose historical allocation was not recorded; underlying-asset exports are unavailable
    - `labels` object
  - `custom` ModelCustomBlock: Model-recorded diagnostics beyond returns and positions. Key names are chosen by the model; the two-part shape is fixed. A series is aligned 1:1 with the model's `dates`. The whole block is capped at 512KB.
    - `series` object: Per-date diagnostics aligned with `dates`
    - `values` object: Scalars, summaries, and other non-daily output
    - `truncation` object, nullable: Per-key notes when the size budget forced truncation
  - `metrics` ModelMetrics: Performance over the window, with the conventions that produced it.
    - `cagr` number, required
    - `volatility` number, required
    - `sharpe` number, required: (cagr - risk_free) / volatility
    - `max_drawdown` number, required
    - `trades` integer: Fills in the window: one per symbol per execution, from the engine's trade ledger. A model without a ledger reports its book-change days instead.
    - `rebalances` integer: Days in the window on which a target filled (distinct execution dates)
    - `trading_days` integer, required
    - `bars_per_year` integer: Bars a year the series was annualised at: 252 on an exchange calendar, 365 for a 24/7 market
    - `risk_free` number: Annual risk-free rate deducted before sharpe
  - `fees` ModelFees: Net-of-fee returns and the fee charged each day, aligned with `dates`.
    - `assumptions` FeeAssumptions, required: Flat industry-standard rates overlaid on gross returns (`include=fees`). Time-varying or exotic costs belong in the model's own script and its custom diagnostics. Fund expense ratios are already in the prices.
      - `management_fee` number: Annual management fee as a fraction, e.g. 0.01 for 1%
      - `financing_rate` number: Annual rate charged on gross exposure above 100%, as a fraction
      - `commission_bps` number: Commissions, in basis points of two-sided traded notional
      - `slippage_bps` number: Slippage, in basis points of two-sided traded notional
    - `returns` number[], required: Daily net returns; gross is the `returns` block
    - `management` number[], required: Fraction of NAV charged that day
    - `financing` number[], required
    - `trading` number[], required
  - `contribution` ModelContribution: Frozen, bounded attribution; absent evidence never uses current prices.
    - `available` boolean, required
    - `method` string, nullable
    - `price_basis` string, nullable
    - `series` object: Daily arithmetic contributions on the shared dates, at direct asset/member level; null means missing evidence
    - `omitted_keys` string[]: Holdings outside the eight largest average absolute weights
    - `unavailable_keys` string[]: Holdings with missing recorded price evidence

## Other responses

- `403`: `include=fees` requires the Business plan
- `404`: Model not found or has no history
- `4XX`: The request was refused; `error.type` says why
- `5XX`: The server failed; quote `X-Request-Id` when reporting it

---

[API](https://skmtc.dev/ensemble/apis/ensemble-api.md) · [All operations](https://skmtc.dev/ensemble/apis/ensemble-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ensemble/apis/ensemble-api/revisions/4c0fbd80c197?raw)
