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

# Portfolio Theme Exposure

> Decompose a portfolio across the telemetry theme baskets (ASYNC — returns job_id). Poll GET /v1/jobs/{job_id} for the result.

Decomposes a portfolio across the telemetry-radar theme baskets. **Async —
returns a `job_id` immediately.**

1. **Submit**: POST your holdings to `/v1/portfolio/theme-exposure`.
2. **Receive**: a `job_id` and polling URL.
3. **Poll**: `GET /v1/jobs/{job_id}` until `status` is `completed`.

> [!NOTE]
>
> Symbols are taken as RICs, as sent, with no ticker resolution: a bare ticker
> like `AGG` can mean a different stock on a different exchange than the one
> you intend. Resolve tickers to RICs first: for stocks, use
> [Stock Search](https://docs.chicago.global/api-reference/stock/search.md) or
> [Validate Symbol](https://docs.chicago.global/api-reference/validation/validate-symbol.md); for ETFs, use
> [ETF Search](https://docs.chicago.global/api-reference/etf/search.md) or
> [Validate ETF Symbol](https://docs.chicago.global/api-reference/etf/validate.md). Do not use
> `POST /v1/portfolio/resolve` for this. It is a Portfolio Tracker function
> that requires a date per holding and renormalizes weights to 1.0, a
> different contract from this endpoint's. A request where **none** of the
> symbols is a known RIC is rejected with `400` before a job is created, and
> nothing is charged.

## Request Body

| Field | Type | Required | Description |
| - | - | - | - |
| `holdings` | array of `Holding` | Yes | 1–100 positions. |
| `themes` | array of string | No | Up to 10 theme questions ("how exposed am I to X?"). Each entry is a basket ID or a theme-name substring. |

**`Holding` object:**

| Field | Type | Required | Description |
| - | - | - | - |
| `symbol` | string | Yes | RIC of the position, e.g. `AAPL.O`, `JPM.N`, `0700.HK`. 1–24 characters. |
| `weight` | number | Yes | Portfolio fraction in the base currency. Need not sum to 1; may be negative for shorts. Must be finite. |

## Response (job created)

```json theme={null}
{
  "job_id": "theme-9c1e4f2a-...",
  "status": "pending",
  "check_url": "/v1/jobs/theme-9c1e4f2a-...",
  "estimated_duration_seconds": 10,
  "message": "Theme-exposure decomposition started. Poll the check_url for results."
}
```

## Completed Job Result

Documented directly from the endpoint's own contract. `result` carries:

| Field | Description |
| - | - |
| `themes[]` | One entry per theme basket the book reaches: basket id, name, market, quadrant; `gross_weight` (sum of absolute per-name net exposure); `net_weight` (signed); `member_rics` (your held names counting toward the theme, not the basket's full roster); `active_weight` with `active_weight_status` (`null` or `"no_benchmark"` — no market-neutral reference is served yet, never fabricated). |
| `coverage` | `themed` / `unthemed` / `fi_pending` / `unresolved` / `cash` / `lookthrough_residual`, reconciling to `total_book`. |
| `equity_sleeve` | `themed + unthemed`, the denominator for theme percentages. Check `diagnostics.equity_sleeve_nonpositive` before dividing. |
| `fi_by_type` | Fixed-income weight by sub-asset (bond, credit, macro funds receive no theme exposure). |
| `diagnostics`, `disclosures`, `methodology_note` | Conservation totals, resolution counters, data-gap magnitudes, and caveats applicable to this book. |
| `basket_universe` | The report date of the theme baskets used (a staleness signal) and their data-quality counters. |
| `theme_queries[]` | Present only when `themes` was sent. Per query: `status` (`matched` / `ambiguous` / `not_found`), the member-inclusive exposure headline and assigned view when matched, or capped `candidates` with `n_candidates_total` when ambiguous. Numeric fields are `null` unless matched. |

ETFs are unpacked to their constituents at reported weights, nested funds
included. Weight the holdings data does not cover is reported as
`lookthrough_residual` and never spread over known constituents. A symbol
that is not a known RIC is reported as unresolved weight, not guessed.

Exact field types and nullability depend on the book's composition — see a
live job result for the authoritative shape.

```json theme={null}
{
  "job_id": "theme-9c1e4f2a-...",
  "status": "completed",
  "result": {
    "themes": [
      {
        "basket_id": "us-ai-infra-02",
        "name": "US AI Infrastructure",
        "market": "US",
        "quadrant": "Fading",
        "gross_weight": 0.08,
        "net_weight": 0.08,
        "member_rics": ["NVDA.O", "AVGO.O"],
        "active_weight": null,
        "active_weight_status": "no_benchmark"
      }
    ],
    "coverage": { "themed": 0.62, "unthemed": 0.21, "fi_pending": 0.0, "unresolved": 0.02, "cash": 0.05, "lookthrough_residual": 0.10, "total_book": 1.0 },
    "equity_sleeve": 0.83,
    "fi_by_type": {},
    "diagnostics": {},
    "disclosures": [],
    "methodology_note": "...",
    "basket_universe": { "report_date": "2026-11-04" }
  }
}
```

## Errors

| Status | When |
| - | - |
| `400` | None of the supplied symbols resolve to a known RIC. No job is created and nothing is charged. |
| `429` | The theme-exposure worker is at capacity; `Retry-After: 2` is set. |
| `500` | Job creation failed unexpectedly. |


## OpenAPI

````yaml POST /v1/portfolio/theme-exposure
openapi: 3.1.0
info:
  title: Parallax API
  description: >-
    Parallax by Chicago Global — AI-powered investment research and portfolio
    analytics. Multi-factor scoring, portfolio analysis and tracking, financial
    statements, analyst estimates, ETF analytics, valuation (DCF & multiples),
    macro and market telemetry, and AI-generated research reports. Credits can
    be fractional. Per-symbol reads cost 0.05 credits per submitted symbol; see
    each operation for its price. A 503 indicates an availability failure, not
    data age.
  version: 2.0.0
servers:
  - url: https://api.chicago.global
security:
  - HTTPBearer: []
paths:
  /v1/portfolio/theme-exposure:
    post:
      tags:
        - v1
        - Portfolio
      summary: Portfolio Theme Exposure
      description: >-
        Decompose a portfolio across the telemetry theme baskets (ASYNC —
        returns job_id). Poll GET /v1/jobs/{job_id} for the result.
      operationId: portfolio_theme_exposure_v1_portfolio_theme_exposure_post
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - holdings
              properties:
                holdings:
                  type: array
                  minItems: 1
                  maxItems: 100
                  description: Up to 100 positions.
                  title: Holdings
                  items:
                    type: object
                    required:
                      - symbol
                      - weight
                    properties:
                      symbol:
                        type: string
                        minLength: 1
                        maxLength: 24
                        description: >-
                          RIC of the position, e.g. AAPL.O, JPM.N, SPY.P,
                          0700.HK, PTT.BK. Symbols are taken as sent, with no
                          ticker resolution: a symbol that is not a known RIC is
                          reported in the result as unresolved weight, never
                          guessed. Resolve tickers to RICs first: for stocks,
                          GET /v1/stock/search or GET /v1/validate-symbol; for
                          ETFs, GET /v1/etf/search or GET /v1/etf/validate.
                      weight:
                        type: number
                        description: >-
                          Portfolio fraction in the base currency. Weights need
                          not sum to 1 and may be negative for short positions;
                          non-finite values are rejected.
                themes:
                  type: array
                  maxItems: 10
                  default: []
                  description: >-
                    Optional theme questions ('how exposed am I to X?'). Each
                    entry is a basket_id or a theme-name substring; the result
                    gains a theme_queries[] block with the member-inclusive
                    exposure (every held member of the theme, overlap disclosed)
                    next to the assigned view. An ambiguous name returns
                    candidates, never a guess.
                  title: Themes
                  items:
                    type: string
              title: ThemeExposureRequest
        required: true
      responses:
        '200':
          description: Job created
          content:
            application/json:
              schema: {}
        '400':
          description: None of the supplied symbols resolve to a known RIC
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
        '429':
          description: 'Theme-exposure worker at capacity (Retry-After: 2)'
        '500':
          description: Failed to create job
      security:
        - HTTPBearer: []
components:
  schemas:
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.