> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tilt.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Build and backtest a Tilt

> Use the REST API to discover construction fields, create a Tilt, evaluate it, read its constituents, and run a backtest.

This guide builds a quarterly quality-growth Tilt from catalog discovery through
backtesting. It uses one Tilt throughout so that each response supplies the IDs
and revision needed by the next request.

Set the base URL and API key used by the examples:

```bash theme={null}
export TILT_API_URL="https://x.invalid"
export TILT_API_KEY="YOUR_API_KEY"
```

## Step 1: Discover fields and a universe

Construction expressions use exact catalog field names. Search the catalog
before writing a rule:

```bash theme={null}
curl --request POST \
  --url "$TILT_API_URL/api/v1/catalog/search" \
  --header "X-Api-Key: $TILT_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "query": "operating margin",
    "limit": 10
  }'
```

Use the returned `name` in an expression. Inspect an exact field to check its
units, coverage, null rate, and distribution before choosing a threshold:

```bash theme={null}
curl --request POST \
  --url "$TILT_API_URL/api/v1/catalog/inspect" \
  --header "X-Api-Key: $TILT_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"column_name":"market_cap"}'
```

Universe preset IDs are discovered rather than fixed in the API schema:

```bash theme={null}
curl --request GET \
  --url "$TILT_API_URL/api/v1/catalog/universe_presets" \
  --header "X-Api-Key: $TILT_API_KEY"
```

Choose the `id` that describes the intended candidate universe. A named index
is not a universe preset; use an expression such as `index("S&P 500") > 0` in
the filter when index membership is part of the methodology.

[Search catalog reference →](/api-reference/index-construction-preview/search-catalog)

## Step 2: Create the Tilt project

Create an unevaluated draft. This establishes the Tilt project and its first
version but does not produce constituents yet.

```bash theme={null}
curl --request POST \
  --url "$TILT_API_URL/api/v1/tilts" \
  --header "X-Api-Key: $TILT_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Quality Growth",
    "universe_preset": "us_investable"
  }'
```

The response contains two identities:

```json theme={null}
{
  "uuid": "6bcfd210-80f5-4f0b-ab27-6b675194a4a1",
  "version_group_sqid": "quality-growth",
  "revision": "2026-09-29T14:32:10Z",
  "name": "Quality Growth",
  "universe_preset": "us_investable"
}
```

* `version_group_sqid` identifies the Tilt project across its versions.
* `uuid` identifies this particular draft or published version.
* `revision` is the optimistic-concurrency token for the next edit.

Save the returned UUID for the remaining requests:

```bash theme={null}
export TILT_UUID="6bcfd210-80f5-4f0b-ab27-6b675194a4a1"
```

[Create a Tilt reference →](/api-reference/index-construction-preview/create-tilt)

## Step 3: Resolve any ticker overrides

Skip this step when the methodology has no forced inclusions or exclusions.
Overrides require exact `tilt_asset_id` values, not ticker symbols:

```bash theme={null}
curl --request GET \
  --get \
  --url "$TILT_API_URL/api/v1/tickers/search" \
  --data-urlencode "symbols=AAPL" \
  --data-urlencode "exchange=XNAS" \
  --header "X-Api-Key: $TILT_API_KEY"
```

A symbol can identify more than one listing. Compare the returned name,
exchange, and security type before selecting the intended `tilt_asset_id`.

[Resolve ticker listings reference →](/api-reference/index-construction-preview/search-tickers)

## Step 4: Save and evaluate the methodology

Apply construction rules to the draft. This operation saves the effective
methodology and its complete weighted constituent snapshot together. If
validation or evaluation fails, it saves neither.

```bash theme={null}
curl --request PATCH \
  --url "$TILT_API_URL/api/v1/tilts/$TILT_UUID" \
  --header "X-Api-Key: $TILT_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "base_revision": "2026-09-29T14:32:10Z",
    "assignment_expression": "quality=revenue_growth_3y+roe",
    "filter_expression": "market_cap>5000 and fcf_margin>0.08",
    "score_expression": "quality",
    "weight_expression": "free_float_market_cap",
    "included_tilt_asset_ids": [],
    "excluded_tilt_asset_ids": [],
    "rules": {
      "max_constituents": 20,
      "rebalancing_period": "QUARTERLY",
      "capping_methodology": "THRESHOLD_BASED",
      "max_position_weight": "0.10",
      "top_n_position_threshold": "0.045",
      "top_n_position_weight": "0.45"
    }
  }'
```

The response includes the effective rules and an evaluation summary. Keep its
`tilt_uuid` and `revision`: applying changes to a published Tilt can create a
new draft UUID, so the response is authoritative for subsequent requests.

<Note>
  `rebalancing_period` is part of the saved methodology. It accepts `MONTHLY`,
  `QUARTERLY`, `SEMI_ANNUALLY`, or `ANNUALLY`. The backtest endpoint follows
  this value; it does not accept a separate cadence override.
</Note>

[Apply construction reference →](/api-reference/index-construction-preview/apply-construction)

## Step 5: Read the evaluated constituents

Read the complete stored result after a successful apply:

```bash theme={null}
curl --request GET \
  --url "$TILT_API_URL/api/v1/tilts/$TILT_UUID/constituents" \
  --header "X-Api-Key: $TILT_API_KEY"
```

```json theme={null}
{
  "tilt_uuid": "6bcfd210-80f5-4f0b-ab27-6b675194a4a1",
  "revision": "2026-09-29T14:33:02Z",
  "as_of_date": "2026-09-26",
  "total_constituents": 2,
  "total_weight": 1,
  "constituents": [
    {
      "tilt_asset_id": "US0378331005-XNAS",
      "symbol": "AAPL",
      "name": "Apple Inc.",
      "exchange": "XNAS",
      "score": 1.42,
      "weight": 0.54
    },
    {
      "tilt_asset_id": "US5949181045-XNAS",
      "symbol": "MSFT",
      "name": "Microsoft Corp.",
      "exchange": "XNAS",
      "score": 1.18,
      "weight": 0.46
    }
  ]
}
```

`weight` is a portfolio fraction, so `0.54` means 54%. This endpoint returns
the saved evaluation; reading it does not rerun the rules with newer data.

[Constituents reference →](/api-reference/index-construction-preview/get-constituents)

## Step 6: Backtest the saved methodology

Choose the analysis window with dates. Add a benchmark when you need relative
performance and risk statistics:

```bash theme={null}
curl --request GET \
  --get \
  --url "$TILT_API_URL/api/v1/tilts/$TILT_UUID/backtest" \
  --data-urlencode "start_date=2021-01-01" \
  --data-urlencode "end_date=2026-01-01" \
  --data-urlencode "benchmark=SPY" \
  --header "X-Api-Key: $TILT_API_KEY"
```

This quarterly Tilt is reconstituted quarterly throughout the requested date
range because its saved `rules.rebalancing_period` is `QUARTERLY`. To test a
monthly methodology, save a version with `MONTHLY` and backtest the UUID
returned by that apply operation. A run-time cadence override would test rules
that are not the saved methodology, so the endpoint does not allow one.

The response contains the Tilt return series and scheduled membership changes.
When `benchmark` is supplied, it also contains the benchmark series, period
returns, relative return when the coverage windows match, and risk statistics.
Rebalance events describe scheduled additions and removals; they are not a
transaction ledger or complete corporate-action history.

[Backtest reference →](/api-reference/index-construction-preview/backtest-tilt)

## Update and rerun

Read the latest Tilt before editing, then send its `revision` as
`base_revision`. Omitted construction fields keep their saved values. For
example, this changes only the cadence and reevaluates the Tilt:

```bash theme={null}
curl --request PATCH \
  --url "$TILT_API_URL/api/v1/tilts/$TILT_UUID" \
  --header "X-Api-Key: $TILT_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "base_revision": "2026-09-29T14:33:02Z",
    "rules": {
      "rebalancing_period": "MONTHLY"
    }
  }'
```

Use the new `tilt_uuid` and `revision` from the response for the next
constituent read or backtest.
