---
title: "Consolidated ticker snapshot (price, metrics, debt, capital allocation, sparkline)"
method: GET
path: "/api/data"
tags: ["Market Data"]
---

# Consolidated ticker snapshot (price, metrics, debt, capital allocation, sparkline)

`GET /api/data`

## Request

- Base URL: `https://www.oxfordledge.com` (the document declares no server; this is the origin it was published from)
- URL: `https://www.oxfordledge.com/api/data`
- Auth: none declared

Full ticker data snapshot. The main data endpoint.

## Query parameters

- `ticker` string, nullable
- `symbol` string, nullable
- `nocache` string, nullable
- `fields` string, nullable

## Response `200`

Successful Response

- TickerDataResponse: Consolidated ticker snapshot returned by GET /api/data. Fields that downstream serializers return as dicts (price, sparkline, metrics, debtInfo, capitalAllocation, news, filings, etc.) are typed as Any/Dict here. Earlier strict typing (price: float, sparkline: List[float]) was wrong and made every /api/data response fail Pydantic validation with a 500 — the actual payload is `price: {current, change, ...}` and `sparkline: {prices, volumes, dates}`. _Base allows `extra` so every other field passes through unmodified. F4 (2026-04-29): `ticker` tightened to required. Every code path (cache-hit, in-memory cache, fresh fetch, fields-filtered) echoes the resolved ticker symbol; making it required activates the F2.2 boundary test as a real assertion. Other fields stay Optional — the response is genuinely heterogeneous (BDCs lack EPS, REITs lack inventory turnover, etc.) and tightening more would cause false positives.
  - `ticker` string, required
  - `company` string, nullable
  - `name` string, nullable
  - `sector` string, nullable
  - `industry` string, nullable
  - `ceo` string, nullable
  - `website` string, nullable
  - `description` string, nullable
  - `exchange` string, nullable
  - `currency` string, nullable
  - `cik` string, nullable
  - `employees` integer, nullable
  - `price` object, nullable
  - `metrics` object, nullable
  - `financials` object, nullable
  - `debtInfo` object, nullable
  - `capitalAllocation` object, nullable
  - `sparkline` object, nullable
  - `news` object[], nullable
  - `filings` object[], nullable
  - `analyst_consensus` AnalystConsensus: Mean analyst price target with its source and the date we fetched it. OWNER ruling 4 (2026-09-28 + 2026-10-04): the only analyst figures /api/data serves. Target + source + fetch date come from ONE provider response or the block is null; `count` appears only when that same response carried it. `as_of` is the date OXFORD LEDGE FETCHED the figure (`as_of_basis` = "fetched"), not the analysts' own date. No Buy/Hold/Sell rating and no upside % exist on this payload (services/analyst_consensus.py).
    - `mean_target` number, required: Mean analyst price target, USD.
    - `source` string, required: The provider that supplied the target (e.g. FMP, Finnhub).
    - `as_of` string, required: YYYY-MM-DD date Oxford Ledge fetched the target -- NOT the analysts' own date.
    - `as_of_basis` string: Always 'fetched': as_of is our fetch date.
    - `count` integer, nullable: Analysts behind the target, only when the same provider response supplied it.
  - `technicals` object, nullable: Measures computed locally from price_history (perf_*, avgVolume, relVolume, sma50, sma200). Formerly named `finviz`; carries no buy/sell/hold label.
  - `_source` string, nullable
  - `fetchedAt` string, nullable
  - `cached` boolean, nullable
  - `fresh_as_of` string, nullable
  - `quote_freshness` unknown

## Other responses

- `400`: Missing or invalid ticker parameter
- `404`: Ticker not found
- `422`: Invalid ticker format
- `429`: Rate limit exceeded
- `500`: Upstream data provider error

---

[API](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api.md) · [All operations](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/llms.txt) · [OpenAPI document](https://skmtc.dev/oxfordledge/apis/oxford-ledge-api/revisions/e832a1260f0b?raw)
