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

> One call: a portfolio, optional interests and a time window in; the window's Dow Jones articles out, grouped into titled stories (and optionally broader topics), ranked by importance lifted by how much each story is about this portfolio (an article tagged to a position, or one whose scenario tree moves the portfolio more than it usually moves against the market), spread so one topic does not take the whole page, each article carrying its portfolio exposure. Stories and titles are precomputed at ingest, so a call takes tens of milliseconds.



## OpenAPI

````yaml POST /api/v1/backchannel/scenarios/feed
openapi: 3.0.3
info:
  title: Pulse API
  version: 1.0.0
  description: >-
    API for integrating Tilt market intelligence capabilities, including
    scenarios, topics, company news, company search, and risk analysis.
servers:
  - url: https://tilt.io
    description: Production
security:
  - apiKeyAuth: []
paths:
  /api/v1/backchannel/scenarios/feed:
    post:
      tags:
        - Scenarios
      summary: Grouped news feed for a portfolio
      description: >-
        One call: a portfolio, optional interests and a time window in; the
        window's Dow Jones articles out, grouped into titled stories (and
        optionally broader topics), ranked by importance lifted by how much each
        story is about this portfolio (an article tagged to a position, or one
        whose scenario tree moves the portfolio more than it usually moves
        against the market), spread so one topic does not take the whole page,
        each article carrying its portfolio exposure. Stories and titles are
        precomputed at ingest, so a call takes tens of milliseconds.
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ArticleFeedRequest'
      responses:
        '200':
          description: Grouped, ranked feed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArticleFeedResponse'
      security:
        - apiKeyAuth: []
components:
  schemas:
    ArticleFeedRequest:
      type: object
      properties:
        portfolio_weights:
          type: object
          nullable: true
          additionalProperties:
            type: number
          description: >-
            Portfolio weights keyed by tilt_id or CUSIP. Mixed identifiers are
            allowed; CUSIPs are resolved to tilt_ids server-side. Stories tagged
            to a holding are blended into the feed and lifted in proportion to
            the position.
        queries:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/WeightedQuery'
          minItems: 1
          maxItems: 20
          description: >-
            Interest queries, weighted. When omitted the feed is every article
            in the window ranked by importance.
        window_hours:
          type: integer
          minimum: 1
          maximum: 168
          default: 48
          description: How far back to look, in hours (max 7 days).
        min_importance:
          type: integer
          nullable: true
          minimum: 1
          maximum: 10
          description: Drop articles rated below this.
        min_score:
          type: number
          minimum: 0
          maximum: 1
          default: 0.4
          description: Minimum query similarity (query mode only).
        importance_weight:
          type: number
          minimum: 0
          maximum: 2
          default: 0.5
          description: 'Query mode: score * (1 + weight * importance / 10).'
        pool_size:
          type: integer
          minimum: 10
          maximum: 400
          default: 150
          description: Max articles considered before grouping.
        max_portfolio_articles:
          type: integer
          minimum: 0
          maximum: 100
          default: 30
          description: Cap on holdings-tagged articles blended into the pool.
        holdings_min_importance:
          type: integer
          minimum: 1
          maximum: 10
          description: >-
            A story rated below this earns no portfolio lift, whatever its
            holdings or exposure. Omit to take SIG's default (3); the ranking
            defaults are SIG's, so a value set here overrides them for every
            call.
        holdings_boost:
          type: number
          minimum: 0
          maximum: 1
          description: >-
            The lift a fully relevant story earns, in score units where
            importance 10 is 1.0. Relevance is the larger of the holdings signal
            (an article tagged to a position, pro rata to its share until
            full_boost_share) and the exposure signal (the article's scenario
            tree moves the portfolio more than it usually moves against the
            market). Omit to take SIG's default (0.6, six importance points). 0
            ranks the feed on importance alone.
        full_boost_share:
          type: number
          minimum: 0
          exclusiveMinimum: true
          maximum: 1
          description: >-
            Portfolio share at which a tagged position earns the full lift;
            smaller positions earn it pro rata. Omit to take SIG's default
            (0.03).
        exposure_specificity:
          type: number
          nullable: true
          minimum: 1.1
          maximum: 20
          description: >-
            Multiple of the portfolio's typical move against the market at which
            an article's exposure counts as fully specific. Omit to take SIG's
            default (3); null ranks on tagged holdings alone.
        exposure_full_mad:
          type: number
          minimum: 0
          exclusiveMinimum: true
          maximum: 50
          description: >-
            Portfolio MAD, in percentage points, at which the exposure signal is
            at full strength; smaller moves scale it down. Omit to take SIG's
            default (0.5).
        max_per_topic:
          type: integer
          minimum: 0
          maximum: 50
          description: >-
            At most this many of the returned groups may belong to one topic
            until every other topic in reach is placed, so the day's dominant
            story keeps its lead but not the whole page. Omit to take SIG's
            default (2); 0 returns groups in rank order.
        source_preference:
          type: array
          items:
            type: string
          maxItems: 10
          default:
            - WSJ
          description: >-
            Vendors in order of preference. Within a group, a preferred vendor's
            article leads when its score is within source_margin of the group's
            best. Never moves a group down the feed; [] disables.
        source_margin:
          type: number
          minimum: 0
          maximum: 1
          default: 0.1
          description: >-
            How far below the group's best score a preferred vendor may still
            lead.
        limit_groups:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
          description: Max groups returned.
        max_per_group:
          type: integer
          minimum: 1
          maximum: 50
          default: 5
          description: Max articles returned per group.
        group_threshold:
          type: number
          minimum: 0.5
          maximum: 0.95
          default: 0.75
          description: Complete-link cosine threshold for two articles to share a group.
        topic_grouping:
          type: boolean
          default: false
          description: >-
            Also gather the returned story groups into broader topics (an
            ongoing conflict, a data release and its market reaction). Story
            groups are unchanged; the topics come back in `topics`.
        topic_threshold:
          type: number
          minimum: 0.4
          maximum: 0.95
          default: 0.7
          description: >-
            Cosine at which two stories share a topic on embedding alone;
            stories that share a subject code join at a lower bar.
        collapse_versions:
          type: boolean
          default: true
          description: >-
            Keep only the latest version of a re-issued article ('-- Update',
            '-- 4th Update').
        include_content:
          type: boolean
          default: false
          description: Include full article text.
        include_scenarios:
          type: boolean
          default: false
          description: Include each article's scenario tree.
        include_exposure_details:
          type: boolean
          default: false
          description: >-
            Include per-leaf portfolio exposure details (the summary is always
            included).
    ArticleFeedResponse:
      type: object
      properties:
        success:
          type: boolean
        window_since:
          type: string
        articles_considered:
          type: integer
        stories_considered:
          type: integer
        groups_total:
          type: integer
        groups:
          type: array
          items:
            $ref: '#/components/schemas/FeedGroup'
        topics:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/FeedTopic'
          description: >-
            Only with topic_grouping: the returned groups gathered into broader
            topics, in feed order.
        typical_exposure_ratio:
          type: number
          nullable: true
          description: >-
            Median over the pool of the portfolio's MAD to SPY's under one
            article's tree: how much more than the market this portfolio moves
            on a typical story. The exposure signal is measured against it.
        warnings:
          type: array
          items:
            type: string
      required:
        - success
        - window_since
        - articles_considered
        - stories_considered
        - groups_total
        - groups
        - warnings
    WeightedQuery:
      type: object
      properties:
        weight:
          type: number
          minimum: 0
          maximum: 1
        query:
          type: string
          minLength: 1
      required:
        - weight
        - query
    FeedGroup:
      type: object
      properties:
        group_id:
          type: string
          description: >-
            The pipeline's story id, else the point id of the group's
            best-scoring article. Stable across calls that differ only in
            source_preference.
        title:
          type: string
        title_source:
          type: string
          enum:
            - story
            - subject_code
            - headline
        topic_point_id:
          type: string
          nullable: true
          description: backchannel_subject_codes point id when the title is a subject code.
        score:
          type: number
        rank:
          type: number
          description: >-
            What the feed is ordered by: the best member score plus its
            portfolio lift. Groups are then spread so no topic takes more than
            max_per_topic of the returned groups; a deferred group keeps its
            rank.
        portfolio_relevance:
          type: number
          description: >-
            0 to 1: the relevance that earned the group its lift, the larger of
            the holdings signal (tagged to a position) and the exposure signal
            (moves the portfolio more than the market).
        relevance_source:
          type: string
          nullable: true
          enum:
            - holding
            - exposure
            - null
          description: >-
            Which signal set portfolio_relevance; null when the group earned no
            lift.
        max_importance:
          type: integer
        story_count:
          type: integer
          description: Distinct stories in the group before max_per_group.
        versions_collapsed:
          type: integer
          description: Re-issued versions folded into the returned stories.
        latest_published_at:
          type: string
          nullable: true
        tilt_asset_ids:
          type: array
          items:
            type: string
        holdings:
          type: array
          items:
            type: string
          description: Portfolio tilt_ids mentioned in the group.
        holdings_weight:
          type: number
          description: Share of the portfolio (0 to 1) held in the group's holdings.
        portfolio_exposure:
          $ref: '#/components/schemas/FeedGroupExposure'
        articles:
          type: array
          items:
            $ref: '#/components/schemas/ArticleScenarioResponse'
      required:
        - group_id
        - title
        - title_source
        - score
        - rank
        - max_importance
        - story_count
        - versions_collapsed
        - tilt_asset_ids
        - holdings
        - holdings_weight
        - articles
    FeedTopic:
      type: object
      properties:
        topic_id:
          type: string
          description: The group_id of the topic's leading story group.
        title:
          type: string
        title_source:
          type: string
          enum:
            - subject_code
            - story
        story_count:
          type: integer
          description: Story groups in the topic.
        article_count:
          type: integer
        max_importance:
          type: integer
        holdings:
          type: array
          items:
            type: string
        holdings_weight:
          type: number
        groups:
          type: array
          items:
            $ref: '#/components/schemas/FeedGroup'
          description: The topic's story groups, in feed order.
      required:
        - topic_id
        - title
        - title_source
        - story_count
        - article_count
        - max_importance
        - holdings
        - holdings_weight
        - groups
    FeedGroupExposure:
      type: object
      nullable: true
      properties:
        mad_pct:
          type: number
        expected_return_pct:
          type: number
        article_point_id:
          type: string
        market_mad_pct:
          type: number
          nullable: true
          description: >-
            What the same article's scenario tree does to the market (SPY), in
            percentage points.
      required:
        - mad_pct
        - expected_return_pct
        - article_point_id
    ArticleScenarioResponse:
      type: object
      properties:
        point_id:
          type: string
        headline:
          type: string
        content:
          type: string
          nullable: true
        date:
          type: string
        publication_time:
          type: string
          nullable: true
        tilt_source:
          type: string
          default: ''
        importance_rating:
          type: integer
          default: 0
        importance_rationale:
          type: string
          default: ''
        generated_at:
          type: string
          default: ''
        article_image_url:
          type: string
          nullable: true
        fallback_image_id:
          type: string
          nullable: true
        timeline:
          type: array
          items:
            $ref: '#/components/schemas/TimelineEvent'
          default: []
        scenarios:
          type: array
          items:
            $ref: '#/components/schemas/Scenario'
          default: []
        subject_codes:
          type: array
          items:
            type: object
            additionalProperties:
              nullable: true
          default: []
        subject_codes_original:
          type: array
          items:
            type: string
          default: []
        prediction_markets:
          type: array
          items:
            $ref: '#/components/schemas/PredictionMarket'
          default: []
        score:
          type: number
          nullable: true
        tilt_asset_ids:
          type: array
          items:
            type: string
          default: []
        securities:
          type: array
          items:
            $ref: '#/components/schemas/SecurityRef'
          default: []
          description: >-
            Securities mentioned in the article, mapping each tilt_asset_id to
            its CUSIP when known.
        portfolio_exposure:
          $ref: '#/components/schemas/PortfolioExposure'
        warnings:
          type: array
          nullable: true
          items:
            type: string
      required:
        - point_id
        - headline
        - date
    TimelineEvent:
      type: object
      properties:
        date:
          type: string
        summary:
          type: string
      required:
        - date
        - summary
    Scenario:
      type: object
      properties:
        probability:
          type: integer
          minimum: 0
          maximum: 100
        title:
          type: string
        description:
          type: string
        sub_scenarios:
          type: array
          nullable: true
          items:
            type: object
            additionalProperties:
              nullable: true
          description: Nested sub-scenarios (same shape as Scenario)
        macro_shocks:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/MacroShock'
      required:
        - probability
        - title
        - description
    PredictionMarket:
      type: object
      properties:
        market_id:
          type: string
        question:
          type: string
        relevance:
          type: string
        reasoning:
          type: string
        top_outcomes:
          type: array
          items:
            type: object
            additionalProperties:
              nullable: true
      required:
        - market_id
        - question
        - relevance
        - reasoning
        - top_outcomes
    SecurityRef:
      type: object
      properties:
        tilt_asset_id:
          type: string
        cusip:
          type: string
          nullable: true
          description: CUSIP for this security when SIG can resolve one.
      required:
        - tilt_asset_id
    PortfolioExposure:
      type: object
      nullable: true
      properties:
        mad_pct:
          type: number
        expected_return_pct:
          type: number
        num_leaf_scenarios:
          type: integer
        leaf_details:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/LeafScenarioDetail'
        scenario_level_details:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/ScenarioLevelDetail'
      required:
        - mad_pct
        - expected_return_pct
        - num_leaf_scenarios
    MacroShock:
      type: object
      properties:
        indicator:
          type: string
        impact:
          type: number
      required:
        - indicator
        - impact
    LeafScenarioDetail:
      type: object
      properties:
        path:
          type: array
          items:
            type: string
        title:
          type: string
        joint_probability_pct:
          type: number
        portfolio_return_pct:
          type: number
        abs_portfolio_return_pct:
          type: number
      required:
        - path
        - title
        - joint_probability_pct
        - portfolio_return_pct
        - abs_portfolio_return_pct
    ScenarioLevelDetail:
      type: object
      properties:
        title:
          type: string
        description:
          type: string
        probability_pct:
          type: number
        portfolio_return_mean_pct:
          type: number
        portfolio_return_std_pct:
          type: number
        macro_shocks:
          type: array
          items:
            $ref: '#/components/schemas/MacroShockDistributionDetail'
        sub_scenario_count:
          type: integer
      required:
        - title
        - description
        - probability_pct
        - portfolio_return_mean_pct
        - portfolio_return_std_pct
        - macro_shocks
        - sub_scenario_count
    MacroShockDistributionDetail:
      type: object
      properties:
        indicator:
          type: string
        mean:
          type: number
        std:
          type: number
      required:
        - indicator
        - mean
        - std
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key

````