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

# tRPC TradFi Market Data API

> Glider-tradeable asset news, U.S. equity and index snapshots, and ticker overviews backed by Massive market data.

The `tradFiMarketData.*` namespace is available on the public tRPC base
endpoint:

* Base endpoint: `POST /v1/trpc`
* Namespace: `tradFiMarketData.*`
* Auth: public
* Upstream: [Massive REST API](https://massive.com/docs/rest/quickstart)
* Server cache: 300 seconds by default. Platform API uses process memory plus
  Redis or the asset-data-sync KV-backed remote cache when configured.

## REST Assets

Successful branding images use a canonical uppercase ticker-and-kind edge cache
key. The Worker and browser cache policy is 7 days, with browsers allowed to
serve stale images while revalidating for another 30 days
(`public, max-age=604800, stale-while-revalidate=2592000, s-maxage=604800`).
Error responses are never stored in the edge cache.

* `GET /v1/tradfi-market-data/tickers/{ticker}/branding`
  * Purpose: proxy the default Massive ticker branding image without exposing
    the Massive API key to browser clients
  * Default: `icon`, because square/circular UI slots should prefer compact
    brand marks over rectangular wordmarks
  * Params:
    * `ticker`: normalized stock ticker
  * Response: image bytes with the upstream content type when branding exists;
    `404` when Massive has no icon branding for that ticker

* `GET /v1/tradfi-market-data/tickers/{ticker}/branding/{kind}`
  * Purpose: proxy Massive ticker branding images without exposing the Massive
    API key to browser clients
  * Params:
    * `ticker`: normalized stock ticker
    * `kind`: `logo` or `icon`
  * Response: image bytes with the upstream content type when branding exists;
    `404` when Massive has no branding for that ticker

## Procedures

* `tradFiMarketData.getStockNews`
  * Purpose: fetch recent stock-market news, optionally scoped to caller-provided
    tickers
  * Input:
    * optional `tickers`, up to 25 symbols
    * optional `limit`, 1-50, default `6`
  * Upstream endpoint:
    [`GET /v2/reference/news`](https://massive.com/docs/rest/stocks/news)
  * Response includes normalized articles, publishers, tickers, insights, and
    cache metadata

* `tradFiMarketData.getTradeableAssetNews`
  * Purpose: fetch recent stock-market news for Glider-tradeable RWA underlyings
    without requiring clients to know the tradeable ticker universe
  * Input:
    * optional `limit`, 1-50, default `6`
  * Upstream endpoint:
    [`GET /v2/reference/news`](https://massive.com/docs/rest/stocks/news)
  * Response includes normalized articles, publishers, tradeable tickers,
    tradeable insights, and cache metadata. Results are limited to canonical RWA
    assets with `asset_class` `equity` or `fund` and an issuer product with at
    least one linked onchain asset.

* `tradFiMarketData.getMarketStatus`
  * Purpose: fetch the current Massive market-hours state for canonical TradFi
    RWA underlyings
  * Input: none
  * Upstream endpoint: `GET /v1/marketstatus/now`
  * Response includes normalized exchange status, broad market status,
    extended-hours flags, currency market status, provider server time, and
    cache metadata

* `tradFiMarketData.getStockSnapshots`
  * Purpose: fetch latest stock snapshots for a ticker set, using Massive's
    full-market snapshot endpoint with a ticker filter
  * Input:
    * required `tickers`, 1-100 symbols
    * optional `includeOtc`, default `false`
  * Upstream endpoint:
    [`GET /v2/snapshot/locale/us/markets/stocks/tickers`](https://massive.com/docs/rest/stocks/snapshots/full-market-snapshot)
  * Response includes normalized snapshots, count, request id, and cache
    metadata

* `tradFiMarketData.getStockAggregateBars`
  * Purpose: fetch OHLC bars for stock detail charts
  * Input:
    * required `ticker`
    * required `multiplier`, 1-1440
    * required `timespan`: `minute`, `hour`, `day`, `week`, `month`,
      `quarter`, or `year`
    * required `from` and `to` as `YYYY-MM-DD` or millisecond timestamps
    * optional `adjusted`, default `true`
    * optional `sort`, `asc` or `desc`, default `asc`
    * optional `limit`, 1-50000, default `5000`
  * Upstream endpoint:
    [`GET /v2/aggs/ticker/{stocksTicker}/range/{multiplier}/{timespan}/{from}/{to}`](https://massive.com/docs/stocks/get_v2_aggs_ticker__stocksTicker__range__multiplier___timespan___from___to)
  * Response includes normalized timestamped OHLC bars, volume, VWAP,
    transaction count, request id, and cache metadata

* `tradFiMarketData.getStockAggregateBarsBatch`
  * Purpose: fetch sparklines for a visible stock set in one browser request
    while retaining the existing per-ticker server cache
  * Input: the same range, timespan, sorting, adjustment, and optional ticker
    history fields as `getStockAggregateBars`, plus `tickers` (1-50) instead of
    a single `ticker`
  * Runtime normalizes and deduplicates tickers, resolves up to six concurrently,
    and returns one item per ticker
  * Each item contains either `response` or a bounded `error`; one upstream
    failure does not discard successful charts for the rest of the batch

* `tradFiMarketData.getRelatedTickers`
  * Purpose: fetch Massive related tickers for a TradFi symbol so symbol-detail
    clients can show peer or thematically similar market links
  * Input:
    * required `ticker`
  * Upstream endpoint:
    [`GET /v1/related-companies/{ticker}`](https://massive.com/docs/rest/stocks/tickers/related-tickers)
  * Response includes normalized related ticker symbols, count, request id, and
    cache metadata

* `tradFiMarketData.getIndexSnapshots`
  * Purpose: fetch latest market index snapshots for dashboard surfaces such as
    the S\&P 500, Nasdaq 100, Dow Jones, Russell 2000, or VIX
  * Input:
    * required `tickers`, 1-20 index symbols such as `I:SPX` or `I:VIX`
  * Upstream endpoint:
    [`GET /v3/snapshot/indices`](https://massive.com/docs/rest/indices/snapshots/indices-snapshot)
  * Response includes normalized index values, session open/high/low/close,
    change, change percent, count, request id, and cache metadata

* `tradFiMarketData.getIndexAggregateBars`
  * Purpose: fetch timestamped OHLC bars for index sparklines and charts
  * Input:
    * required `ticker`, index symbol such as `I:SPX` or `I:VIX`
    * required `multiplier`, 1-1440
    * required `timespan`: `minute`, `hour`, `day`, `week`, `month`,
      `quarter`, or `year`
    * required `from` and `to` as `YYYY-MM-DD` or millisecond timestamps
    * optional `adjusted`, default `true`
    * optional `sort`, `asc` or `desc`, default `asc`
    * optional `limit`, 1-50000, default `5000`
  * Upstream endpoint:
    `GET /v2/aggs/ticker/{indexTicker}/range/{multiplier}/{timespan}/{from}/{to}`
  * Response includes normalized timestamped OHLC bars, volume, VWAP,
    transaction count, request id, and cache metadata

* `tradFiMarketData.getSp500Heatmap`
  * Purpose: fetch an S\&P 500 constituent heatmap payload that uses
    State Street SPY holdings weight for tile size, repo-owned S\&P 500 sector
    metadata for grouping, and Massive snapshots for live return/color
  * Input:
    * optional `availability`, `all` or `glider_supported`, default `all`
    * optional `limit`, 1-600, default `120`
  * Upstream endpoints:
    * State Street SPY daily holdings workbook from `SP500_HOLDINGS_URL`
    * Massive [`GET /v2/snapshot/locale/us/markets/stocks/tickers`](https://massive.com/docs/rest/stocks/snapshots/full-market-snapshot)
  * Response includes constituent metadata, normalized snapshot fields, sector
    labels, tradeability, holdings `weightPct`, `holdingsSource`,
    `holdingsAsOfDate`, request ids, and cache metadata. The compatibility
    `weight` field equals `weightPct`; `weightSource` is `index_weight`.

* `tradFiMarketData.getEquitySectorPerformance`
  * Purpose: aggregate daily cached State Street SPY holdings weights and
    Massive constituent snapshots into sector-level market performance rows for
    the Stocks page
  * Input:
    * optional `availability`, `all` or `glider_supported`, default `all`
  * Upstream endpoints:
    * State Street SPY daily holdings workbook from `SP500_HOLDINGS_URL`
    * Massive [`GET /v2/snapshot/locale/us/markets/stocks/tickers`](https://massive.com/docs/rest/stocks/snapshots/full-market-snapshot)
  * Response includes sector key/name, constituent count, weighted change
    percent, up/down counts, top movers, source/as-of metadata, request ids, and
    cache metadata

* `tradFiMarketData.getStockDetails`
  * Purpose: hydrate a stock detail surface with Massive ticker overview,
    snapshot, and recent news
  * Input:
    * required `ticker`
    * optional `newsLimit`, 1-20, default `5`
  * Upstream endpoints:
    [`GET /v3/reference/tickers/{ticker}`](https://massive.com/docs/rest/stocks/tickers/ticker-overview),
    [`GET /v2/snapshot/locale/us/markets/stocks/tickers/{stocksTicker}`](https://massive.com/docs/rest/stocks/snapshots/single-ticker-snapshot),
    and [`GET /v2/reference/news`](https://massive.com/docs/rest/stocks/news)
  * Response includes ticker overview fields such as company description,
    branding logo/icon URLs, homepage, market cap, SIC code/industry, FIGIs,
    employees, normalized snapshot, latest news articles, and separate cache
    metadata for each upstream request

* `tradFiMarketData.getDividends`
  * Purpose: hydrate the shared stock/fund symbol-page Dividends panel
  * Input: required `ticker`, normalized to uppercase
  * Sources:
    * Massive dividends history (`/stocks/v1/dividends`)
    * latest stock snapshot for trailing-12-month yield
    * adjusted monthly aggregate bars for the five-year average yield
  * Response: `null` when the ticker has no payable cash dividends. Otherwise:
    * `annual`: ascending calendar-year totals for the current year plus the
      nine before it; historical totals prefer the provider's split-adjusted
      cash amount and mark the current year with `partial: true`
    * `ttmYieldPct`: trailing-12-month dividends divided by the latest share
      price, in percent points
    * `avgYield5yPct`: average annual yield over the last five complete
      calendar years, in percent points
    * `frequencyPerYear`: provider-reported annual payment count, or `null`
    * `recent`: the latest ten payments, newest first, with ex-date, optional
      pay date, and the cash amount paid per share
  * The endpoint is instrument-neutral: both equity and fund tickers use the
    same normalized response and six-hour dividend-history cache.

* `tradFiMarketData.getFundDistributionYields`
  * Purpose: yield column on market boards that list fund wrappers (the bonds
    desk), without a per-row request fan-out
  * Input: required `tickers`, 1-20 entries, normalized to uppercase and deduped
  * Sources: the same dividend history and snapshot reads as
    `getDividends`, so the six-hour corporate-actions cache is shared
  * Response: one `{ ticker, ttmYieldPct }` row per requested ticker, in request
    order. `ttmYieldPct` is trailing-12-month distributions over the latest
    share price, in percent points
  * Best-effort per ticker: an upstream failure for one ticker yields
    `ttmYieldPct: null` for that row instead of failing the batch

* `tradFiMarketData.getStablebondQuotes`
  * Purpose: yield, NAV, and FX for the Etherfuse sovereign stablebonds on the
    bonds desk
  * Input: none
  * Upstream endpoint:
    [`GET /lookup/bonds/cost`](https://docs.etherfuse.com/api-reference/lookup/list-stablebond-costs)
    on Etherfuse's **public** Lookup API. No API key: only `ETHERFUSE_BASE_URL`
    is configurable, so sandbox can be targeted without a code change.
  * Response: `quotes`, one entry per bond, with `mint` (the canonical Solana
    mint, which is the join key — note the `mint` *field* in Etherfuse's own
    payload is the payment token, not the bond), `symbol`, `currency`,
    `yieldPct` (their `current_basis_points` as percent points), `navFiat`,
    `navUsd`, and `fxRateUsd`
  * Yields and NAVs are denominated in the bond's own currency. A 12.76%
    TESOURO is 12.76% in BRL; consumers must carry the currency with the number.
  * Etherfuse publishes no rate limit and sits behind no CDN, so this is cached
    five minutes server-side: one upstream read serves every bond and every
    viewer, roughly 288 requests a day regardless of traffic. Upstream failures
    return an empty `quotes` list rather than an error.

* `tradFiMarketData.getTreasuryYieldCurve`
  * Purpose: the U.S. Treasury yield curve panel on the bonds desk
  * Input: none. The comparison curves are fixed at 30 and 365 days back, the
    pair rate desks quote.
  * Upstream endpoint:
    [`GET /fed/v1/treasury-yields`](https://massive.com/docs/rest/economy/treasury-yields)
  * Response: `configured`, one-hour `cache` metadata, and `curve`, which is
    `null` when the key is unset, the feed is unentitled, or no rows are
    published. Otherwise the curve carries `asOfDate`, `monthAgoDate`,
    `yearAgoDate` (each the closest published date on or before its lookback
    target, or `null`), and `points` with `label` ("1M", "10Y"),
    `tenorMonths`, `yieldPct`, `monthAgoYieldPct`, and `yearAgoYieldPct`
  * Massive documents eleven constant maturities but currently publishes seven
    (1M, 3M, 1Y, 2Y, 5Y, 10Y, 30Y). Tenors absent from a row are omitted from
    `points` rather than emitted as gaps.

* `tradFiMarketData.getStockMarketIntelligence`
  * Purpose: hydrate equity analyst-intelligence surfaces for symbol detail
    pages using the purchased Massive/Benzinga partner datasets
  * Input:
    * required `ticker`
    * optional `lookbackDays`, 1-365, default `90`
    * optional `ratingsLimit`, 1-50, default `12`
    * optional `insightsLimit`, 1-20, default `5`
  * Upstream endpoints:
    * [`GET /benzinga/v1/consensus-ratings/{ticker}`](https://massive.com/docs/rest/partners/benzinga/consensus-ratings)
    * [`GET /benzinga/v1/ratings`](https://massive.com/docs/rest/partners/benzinga/analyst-ratings)
    * [`GET /benzinga/v1/analyst-insights`](https://massive.com/docs/rest/partners/benzinga/analyst-insights)
    * [`GET /benzinga/v1/bulls-bears-say`](https://massive.com/docs/rest/partners/benzinga/bulls-bears-say)
    * existing Massive stock snapshot endpoint for the current price used in
      price-target upside calculations
  * Response includes normalized consensus rating counts, collapsed buy/hold/sell
    counts, high/average/low price targets, current-price upside percentages,
    recent rating actions, analyst commentary, bull and bear thesis summaries,
    and per-source status/cache metadata
  * Source statuses are fail-open. `not_entitled`, `empty`, or transient `error`
    for one Benzinga endpoint do not prevent the rest of the intelligence
    payload from rendering.

* `tradFiMarketData.getStockBusinessSegments`
  * Purpose: hydrate stock-page revenue-by-segment charts from the public
    TipRanks `stock-analysis` payload
  * Input:
    * required `ticker`
  * Upstream endpoint:
    * `GET https://www.tipranks.com/stocks/{slug}/stock-analysis/payload.json`
  * Response includes normalized segment groups, segment percentages, latest
    complete fiscal-year revenue basis, derived segment revenue, source URL,
    requested ticker, source ticker, alias metadata, update timestamp, and cache
    metadata.
  * Runtime validates the payload root ticker before caching. Known route
    fallbacks such as `GOOGL` using `GOOG` business-segment data are represented
    explicitly in `source.aliasApplied` and `source.sourceTicker`.

* `tradFiMarketData.getStockRiskFactors`
  * Purpose: hydrate stock-page risk-factor summaries from the public TipRanks
    `stock-risk-factors` payload
  * Input:
    * required `ticker`
  * Upstream endpoint:
    * `GET https://www.tipranks.com/stocks/{slug}/stock-risk-factors/payload.json`
  * Response includes normalized risk categories, subcategories, current report
    totals, recent report history, top keywords, individual risk-factor items,
    source identity metadata, and cache metadata.
  * Runtime validates the payload root ticker before caching and returns a
    successful empty payload if TipRanks has no usable model for a ticker.

## Runtime Notes

* Tickers are trimmed, validated, uppercased, and limited to alphanumeric
  symbols plus `.` and `-`.
* Index tickers are trimmed, validated, uppercased, and also allow `:` for
  Massive index symbols such as `I:SPX`.
* Dashboard stock news uses canonical RWA assets in `core.asset_canonical` with
  `asset_class` `equity` or `fund`, then requires an issuer product with at
  least one linked onchain asset before requesting/filtering Massive news
  through `getTradeableAssetNews`. This is issuer-neutral so Ondo, xStocks, or
  future issuer products can enter the news universe through data.
* If `MASSIVE_API_KEY` is not configured, procedures return successful empty
  payloads with `configured: false` so browser surfaces can degrade cleanly.
* If State Street SPY holdings are unavailable and no valid cached holdings payload exists,
  S\&P 500 heatmap and sector procedures return successful empty payloads rather
  than falling back to market cap, volume, price, or equal-weight sizing.
* Ticker overview lookup treats missing Massive reference rows as a successful
  `overview: null` response so symbol pages can still show issuer products,
  snapshots, or news when only part of the provider surface is available.
* Related-ticker lookup treats missing or non-entitled Massive responses as a
  successful empty result so symbol pages can render without blocking other
  market data.
* TipRanks stock insight payloads are treated as public CDN data, not an
  authenticated API. The backend sends stable browser-like request headers but
  does not store user/browser cookies or Cloudflare clearance tokens.
* S\&P 500 heatmap and sector performance use daily cached State Street SPY
  holdings for constituent weights and repo-owned S\&P 500 reference metadata for
  sector labels. Fast Massive snapshot responses provide price/change data and
  should not be stored in the 12-hour browser persistence bucket.
* Massive stock snapshots can include all-zero intraday bars outside an active
  market session. The API treats those bars as missing data and falls back to
  previous-day close for display surfaces instead of returning a `$0` price.
* Market-hours status is provider data, not browser-local schedule inference.
  If Massive market status is unavailable, clients should show an explicit
  unavailable state instead of guessing from local time.
* The platform API reads `MASSIVE_BASE_URL`, `MASSIVE_CACHE_TTL_SECONDS`,
  `SP500_HOLDINGS_URL`, and `SP500_HOLDINGS_CACHE_TTL_SECONDS` from environment
  config, defaulting to `https://api.massive.com`, `300`, State Street's SPY
  daily holdings workbook URL, and `86400` for the non-secret values.

## Example Calls

Fetch latest Glider-tradeable equity and ETF market news:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getTradeableAssetNews' \
  --header 'content-type: application/json' \
  --data '{"json":{"limit":4}}'
```

Fetch current canonical market-hours status:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getMarketStatus' \
  --header 'content-type: application/json' \
  --data '{"json":null}'
```

Fetch recent news for NVIDIA:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getStockDetails' \
  --header 'content-type: application/json' \
  --data '{"json":{"ticker":"NVDA","newsLimit":5}}'
```

Fetch snapshots for several tokenized equity underlyings:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getStockSnapshots' \
  --header 'content-type: application/json' \
  --data '{"json":{"tickers":["AAPL","MSFT","NVDA"],"includeOtc":false}}'
```

Fetch intraday aggregate bars for Apple:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getStockAggregateBars' \
  --header 'content-type: application/json' \
  --data '{"json":{"ticker":"AAPL","multiplier":5,"timespan":"minute","from":"2026-04-29","to":"2026-04-30","limit":500}}'
```

Fetch related ticker links for Tesla:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getRelatedTickers' \
  --header 'content-type: application/json' \
  --data '{"json":{"ticker":"TSLA"}}'
```

Fetch major market index snapshots:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getIndexSnapshots' \
  --header 'content-type: application/json' \
  --data '{"json":{"tickers":["I:SPX","I:NDX","I:DJI","I:RUT","I:VIX"]}}'
```

Fetch intraday aggregate bars for the S\&P 500 index:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getIndexAggregateBars' \
  --header 'content-type: application/json' \
  --data '{"json":{"ticker":"I:SPX","multiplier":15,"timespan":"minute","from":"2026-04-29","to":"2026-04-30","limit":120}}'
```

Fetch S\&P 500 heatmap data:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getSp500Heatmap' \
  --header 'content-type: application/json' \
  --data '{"json":{"availability":"all","limit":120}}'
```

Fetch equity sector performance:

```bash theme={null}
curl --request POST \
  --url 'https://api.glider.fi/v1/trpc/tradFiMarketData.getEquitySectorPerformance' \
  --header 'content-type: application/json' \
  --data '{"json":{"availability":"all"}}'
```
