> ## 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.

# Portfolio Feed Guide

> One call that turns a portfolio and a few interests into the news that matters, grouped into titled stories and topics, ranked, with the impact on each holding.

## Overview

The Portfolio Feed answers "what happened in the last day or two that matters to this portfolio?" in a single request. You send a portfolio, optionally a few interests and a time window; you get back the window's Dow Jones articles grouped into titled stories, ranked so the day's biggest news leads and a story about one of your holdings is lifted in proportion to the position, with each article carrying its portfolio exposure.

Everything expensive happens when an article is ingested: its importance rating, its story assignment and title, its scenario tree. A feed call only selects and ranks, so it returns in tens of milliseconds and can be made on every page load.

## The request

```bash theme={null}
curl -X POST "https://tilt.io/api/v1/backchannel/scenarios/feed" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "portfolio_weights": {"MH33D6-R": 0.4, "037833100": 0.3, "P8R3C2-R": 0.3},
    "queries": [{"query": "artificial intelligence", "weight": 1.0}],
    "window_hours": 48,
    "topic_grouping": true
  }'
```

* `portfolio_weights` is keyed by Tilt asset id or CUSIP; the two can be mixed. Weights are read as portfolio shares, so they should sum to one. See the [Scenario Analysis Guide](/backchannel/scenario-analysis-guide) for resolving tickers.
* `queries` is optional. Without it the feed is every article in the window ranked by importance, with your holdings blended in. With it, articles are selected by similarity to the interests and importance still drives the order.
* `window_hours` defaults to 48 and goes up to 168 (a week).
* `topic_grouping` adds a second, broader layer on top of the stories (see below).

Every other field has a default that matches how the feed is tuned; the reference page lists them.

## The response

```json theme={null}
{
  "success": true,
  "window_since": "2026-09-06T17:00:00+00:00",
  "articles_considered": 150,
  "stories_considered": 145,
  "groups_total": 131,
  "groups": [
    {
      "group_id": "story-8f3c…",
      "title": "U.S. Strikes Three Iranian Ships After Missiles Fired at American Aircraft Carrier",
      "title_source": "story",
      "score": 0.9,
      "rank": 0.9,
      "max_importance": 9,
      "story_count": 1,
      "holdings": [],
      "holdings_weight": 0.0,
      "portfolio_exposure": {"mad_pct": 1.8, "expected_return_pct": -0.6, "article_point_id": "…"},
      "articles": [{"headline": "…", "tilt_source": "WSJ", "importance_rating": 9, "portfolio_exposure": {"…": "…"}}]
    },
    {
      "group_id": "story-2a91…",
      "title": "GE Aerospace to Buy Consolidated Precision Products for $11.4 Billion",
      "title_source": "story",
      "score": 0.7,
      "rank": 0.722,
      "max_importance": 7,
      "holdings": ["G6Y2KQ-R"],
      "holdings_weight": 0.0055,
      "articles": [{"…": "…"}]
    }
  ],
  "topics": [
    {
      "topic_id": "story-8f3c…",
      "title": "Middle East Geopolitical Risk",
      "title_source": "subject_code",
      "story_count": 5,
      "article_count": 6,
      "max_importance": 9,
      "holdings": [],
      "groups": [{"…": "…"}]
    }
  ],
  "warnings": []
}
```

`groups` is the feed, in order. Each group is one story: its `title`, the `articles` that tell it (one per vendor version, the best first), `max_importance` on the 1 to 10 scale the pipeline assigns at ingest, the `holdings` it touches and their combined share of the portfolio, and `portfolio_exposure`, the exposure of the group's most exposed article. Each article also carries its own `portfolio_exposure`, and `include_scenarios: true` returns the scenario tree behind it.

## How articles are grouped

Two layers, both computed before you call.

**Stories** are the groups. When an article is ingested it is matched against the last seven days of articles on its headline and opening paragraph; articles that describe the same event share one story and one title, written once for the story. A re-issued article ("-- 2nd Update") folds into the same story. `title_source` tells you where a title came from: `story` for the pipeline's title, `subject_code` when a story is titled by a subject code its articles share, `headline` when it falls back to the lead headline.

**Topics**, returned when `topic_grouping` is true, gather several stories into a broader thread: the Iran strikes, the Houthi attack on Saudi energy and the oil price reaction become one *Middle East Geopolitical Risk* topic. A topic is titled by the subject code most of its stories share, or by its leading story. The groups inside a topic are the same objects as in `groups`, in the same order, so a client can render either view from one response.

## How the feed is ranked

The order is by `rank`, which is the story's best article score plus a holdings lift:

* The score is importance, so a 9 leads an 8 whatever the portfolio. Iran sending missiles outranks a routine note about a large holding.
* A story tagged to one of your holdings, rated at least 4, is lifted by up to two importance points, in proportion to the position: a 5% position or larger earns the full lift, a 1% position a fifth of it. A major story about a company that is all of a portfolio rises near the top; broad company news does not displace the day's biggest events.
* Within a story, a WSJ article leads when its score is within a small margin of the story's best, so the higher-quality version is the one shown first. `source_preference` changes the vendors, `[]` disables it.

`holdings_boost`, `full_boost_share` and `holdings_min_importance` tune the lift; the defaults are what the examples above use.

## Practical notes

* Latency is tens of milliseconds for a portfolio-only call. Interest queries add an embedding step for headlines the pipeline has not seen; expect under a second for a seven-day window.
* Send the portfolio on each call; nothing is stored between calls.
* Identical calls return identical order.
* `min_importance` drops minor items; `limit_groups` and `max_per_group` size the page.
