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

# Customization Guide

> An introduction to setting up and optimizing a client portfolio.

## Overview

The Tilt Portfolio Optimization Platform enables you to create personalized portfolio optimizations for your clients. This guide walks through the complete workflow from initial organization setup to generating optimized trade proposals.

## Step 1: Organization Setup

### Configure Asset Classes

We'll start by defining the asset classes available in your organization. An asset class consists of a name, description, and a benchmark that represents it. We'll first search for available benchmark indexes, and then use that to create the asset class.

#### Search Available Benchmarks

```bash theme={null}
curl --request GET \
  --url https://api.tilt.io/api/v1/custom/benchmark_indexes/ \
  --header 'X-Api-Key: <api-key>'
```

[View API Reference →](/api-reference/endpoint/get-benchmark-indexes)

#### Create Asset Classes

Now we can create an asset class using one of our benchmarks. The example below uses `M75BNK-R`, which is the identifier for the `SPY` ETF.

```bash theme={null}
curl --request POST \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/asset_classes/ \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
  "name": "US Equities",
  "description": "Example US Equities Asset Class",
  "benchmark_index_identifier": "M75BNK-R"
}'
```

[View API Reference →](/api-reference/endpoint/post-asset-class)

## Step 2. Portfolio Setup

Now that we have an asset class, let's create a portfolio which uses that asset class. We can make an example portfolio with a single allocation to US equities, although it is possible to blend multiple asset classes together.

We reference the asset class using it's UUID that was returned when creating it. We can always [list available asset classes](/api-reference/endpoint/get-asset-classes) to retrieve all asset classes.

At this point, we can enable direct indexing per asset class, for this portfolio. Later, we can override this setting per client too.

<Tip>
  Direct indexing only takes affect if the underlying benchmark index also supports direct indexing.
</Tip>

```bash theme={null}
curl --request POST \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/portfolio_configs/ \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
  "name": "Example Portfolio",
  "asset_allocations": [
    {
      "asset_class_uuid": "asset-class-uuid",
      "target_allocation": "1",
      "direct_indexing_enabled": true
    }
  ]
}'
```

[View API Reference →](/api-reference/endpoint/post-portfolio-config)

## Step 3: Client and Account Setup

### Understanding Clients and Accounts

In Tilt, a **client** represents a person or entity in your system, and each client can have one or more **accounts**. Holdings, portfolio assignments, and optimizations all operate at the account level.

When you create a client, a default account is automatically created. The response includes both the client UUID and the account UUID within the `accounts` array.

### Create a Client

Let's create a new client, which will also create a default account. The `external_id` should be a string that represents this client in your system.

```bash theme={null}
curl --request POST \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/clients/ \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
  "external_id": "<string>"
}'
```

The response will include:

* `uuid`: The client UUID
* `accounts`: An array containing the default account with its own `uuid`

<Tip>
  When creating a client, we can also provide configuration and holdings information for the default account, but we'll update those separately in this guide.
</Tip>

[View API Reference →](/api-reference/endpoint/post-org-client)

### Update Account Holdings

Now, let's assign the account to a portfolio and update its holdings.

We use the portfolio UUID which was returned when creating the portfolio, or we can find it by [listing the available portfolios](/api-reference/endpoint/get-portfolio-configs).

```bash theme={null}
curl --request PATCH \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/clients/{client_uuid}/accounts/{account_uuid} \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
    "portfolio_config_uuid": "portfolio-config-uuid",
    "holdings": {
      "tax_lots": [
        {
          "tilt_asset_id": "MH33D6-R",
          "quantity": "100",
          "cost_basis": "250",
          "trade_date": "2025-01-01",
          "wash_sale_date": "2025-01-01",
          "last_sold_for_loss_date": "2025-01-01"
        },
        {
          "tilt_asset_id": "P8R3C2-R",
          "quantity": "50",
          "cost_basis": "120",
          "trade_date": "2025-01-01",
          "wash_sale_date": "2025-01-01",
          "last_sold_for_loss_date": "2025-01-01"
        }
      ],
      "cash_balance": "50000",
      "non_tradable_assets_value": "5000"
    }
  }'
```

<Tip>
  `MH33D6-R` and `P8R3C2-R` are the identifiers for Apple and Microsoft respectively. More information on asset identifiers is in the [Tilt Asset IDs](#tilt-asset-ids) section.
</Tip>

[View API Reference →](/api-reference/endpoint/patch-client-account)

### Update Direct Indexing Preference

We may override the direct indexing preferences for an account by updating `asset_class_settings`. For example, we can disable direct indexing for a particular asset class:

```bash theme={null}
curl --request PATCH \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/clients/{client_uuid}/accounts/{account_uuid} \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
    "asset_class_settings": [
      {
        "asset_class_uuid": "asset-class-uuid",
        "direct_indexing_enabled": false
      }
    ]
  }'
```

[View API Reference →](/api-reference/endpoint/patch-client-account)

## Step 4: Portfolio Optimization

We can run optimization either for a single account, or in bulk across many accounts and clients. To start with, let's run the optimization for a single account.

### Single Account Optimization

Run an optimization for an individual account to get customized portfolio weights:

```bash theme={null}
curl --request POST \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/clients/{client_uuid}/accounts/{account_uuid}/optimize/ \
  --header 'X-Api-Key: <api-key>'
```

[View API Reference →](/api-reference/endpoint/post-account-optimize)

### Generate Trade Proposals

Convert the optimized weights into actionable trade proposals.

```bash theme={null}
curl --request POST \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/clients/{client_uuid}/accounts/{account_uuid}/proposal/ \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
    "optimized_weights": {
      "MH33D6-R": "0.5",
      "P8R3C2-R": "0.5"
    }
  }'
```

[View API Reference →](/api-reference/endpoint/post-account-proposal)

## Step 5: Bulk Operations

### Bulk Optimization and Proposals

We can optimize clients in bulk by calling the bulk optimize endpoint, passing in a list of client UUIDs. This responds with a list of proposal UUID's, that we can then check the result of.

```bash theme={null}
curl --request POST \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/optimized_proposals/ \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
    "client_uuids": [
      "client-uuid-1",
      "client-uuid-2",
      "client-uuid-3"
    ]
  }'
```

[View API Reference →](/api-reference/endpoint/post-bulk-client-optimize-proposal)

### Check Task Results

We can get the status for each proposal by calling the check status endpoint:

```bash theme={null}
curl --request POST \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/optimized_proposals/ \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
    "proposal_uuids": [
      "proposal-uuid-1",
      "proposal-uuid-2",
      "proposal-uuid-3"
    ]
  }'
```

[View API Reference →](/api-reference/endpoint/get-bulk-optimization-status)

To get the result for a generated proposal, we can call the get task result endpoint. This will return both the optimized weights and generated trades for that proposal.

```bash theme={null}
curl --request GET \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/optimized_proposals/{proposal_uuid}/ \
  --header 'X-Api-Key: <api-key>'
```

[View API Reference →](/api-reference/endpoint/get-optimization-task-result)

We can also search all generated proposals, and filter them based on criteria such as age, drift or turnover.

```bash theme={null}
curl --request POST \
  --url https://api.tilt.io/api/v1/custom/org/{organization_uuid}/optimized_proposals/list/ \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <api-key>' \
  --data '{
  "status": "pending",
  "created_after": "2025-10-01",
  "min_average_drift": "0.1"
}'
```

## Configuration Hierarchy

Optimization configuration can be set on the account-level, portfolio-level, and organization level, and are merged together based on this order of precedence:

1. **Account config** (highest priority)
2. **Portfolio config**
3. **Organization config** (fallback defaults)

The configs are represented by the same schema, so all config values can be overriden at each level. The account and organization config is set in the `customization_config` field in their respective schemas.

Note that account and organization values outside of `customization_config` are unique to the account or organization, and are not merged. For example, `factor_values` is a top-level field in the organization schema. It is set globally for the organization, and cannot be overridden. Most properties are set via config however, and can be flexibly overridden as needed.

<Info>
  For list values (e.g., `no_trade` assets), the system uses the most specific non-empty list available. For example, if an account has any `no_trade` assets defined, these completely replace any organization-level `no_trade` assets rather than merging.
</Info>

<Tip>
  You can also set **dynamic rules** on configs at any level to make parameter values change automatically based on time schedules and conditions. See the [Dynamic Rules Guide](/dynamic-rules/guide) for details.
</Tip>

## Tilt Asset IDs

We use asset IDs throughout the API to identify assets, rather than symbols. We can use the [search tickers endpoint](/api-reference/endpoints/search-tickers) to find the tilt asset ID corresponding to a certain ticker symbol.

```bash theme={null}
curl --request GET \
  --url https://api.tilt.io/api/v1/tickers/search?symbols=MSFT&ticker_types=common_stock \
  --header 'X-Api-Key: <api-key>'
```
