# GET /v2/tickers/{ticker}

**Ticker state**

The full ticker row, every signal on the [schema page](/docs/schema), for one symbol or a comma list of up to 50. Right now, or with `asof`, as of any past date.

## Query / path parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `ticker` | path | string[] | yes | One symbol, or a comma-separated list of up to 50 for a batch response keyed by symbol. Case-insensitive. Equities are bare symbols (`AAPL`); every other class carries a prefix — rates (`R:SOFR`), crypto (`X:BTCUSD`), fx (`X:EURUSD`). Bare `BTC`/`ETH` are US-listed ETFs, not spot crypto. See [Tickers](/docs/tickers). Example: `AAPL`. |
| `asof` | query | string | no | Optional. Target moment as `YYYY-MM-DD` (that day's close) or an ISO timestamp (that intraday moment) — the same read as it stood then, unlimited depth. Full contract under [As of a past date](#as-of). Example: `2026-06-28`. |
| `interval` | query | string | no | Grain the past state is reconstructed at: `1m`, `1h`, `1d`, or `auto` (default). Only valid alongside `asof` — a live read with `interval` is a 400. Details under [As of a past date](#as-of). Enum: `1m`, `1h`, `1d`, `auto`. Default: `auto`. |

## Returns

- `as_of` (string) — Server time this response was assembled (ISO 8601).
- `ticker` (string) — The symbol you asked for, normalised. Single form only.
- `data` (object) — The full ticker row — every signal on the [schema page](/docs/schema). On the list form, an object keyed by symbol, one full row each.
- `requested` (string[]) — List form only — the canonical symbols asked for, de-duplicated, in request order.
- `count` (number) — List form only — how many of `requested` were found.
- `not_found` (string[]) — List form only — the requested symbols we do not track, in request order. An empty array when every symbol was found.
- `_meta` (object) — With `asof` only: how the read was resolved — the interval served and requested, whether rows blend intervals, sources and frozen fields. See the as-of read below.

## Status codes

- **200** — Success — the response shape is documented under Returns above.
- **400** — Invalid ticker format, malformed `asof`, or `interval` on a live read — `interval` selects the grain a PAST state is reconstructed at, so it is only valid alongside `asof`.
- **401** — Missing or invalid API key.
- **404** — Ticker not tracked, or no historical row at or before the requested date.

## Sample response

```json
{
  "as_of": "2026-08-11T20:02:59.802Z",
  "ticker": "AAPL",
  "data": {
    "ticker": "AAPL",
    "name": "Apple Inc.",
    "asset_type": "CS",
    "exchange": "NASDAQ",
    "country": "us",
    "sector": "Technology",
    "industry": "Consumer Electronics",
    "market_cap": 4572794419400,
    "price": 304.765,
    "change_1d_pct": -0.0113,
    "gap_pct": -0.0017,
    "volume_today": 28441673,
    "avg_volume_10d": 62351041,
    "relative_volume": 0.474,
    "pe_ratio": 37.31,
    "eps": 2.02,
    "shares_outstanding": 14594180000,
    "high_52w": 344.5699,
    "low_52w": 219.25,
    "rsi_14": 41.8329,
    "above_sma_50": false,
    "above_sma_200": true,
    "golden_cross": false,
    "earnings_this_week": false,
    "...": "(every other signal on the schema page)"
  }
}
```

## More examples

### A holdings list in one call

Request:

```shell
curl "https://api.tickerbot.io/v2/tickers/AAPL,MSFT,X:BTCUSD,ZZZNOTREAL" \
  -H "Authorization: Bearer YOUR_KEY"
```

Response (`200`):

```json
{
  "as_of": "2026-09-08T14:22:03.118Z",
  "requested": ["AAPL", "MSFT", "X:BTCUSD", "ZZZNOTREAL"],
  "count": 3,
  "data": {
    "AAPL":     { "ticker": "AAPL",     "name": "Apple Inc.",            "asset_class": "stocks", "price": 304.765, "change_1d_pct": -1.13, "rsi_14": 41.83, "...": "(full row)" },
    "MSFT":     { "ticker": "MSFT",     "name": "Microsoft Corporation", "asset_class": "stocks", "price": 512.21,  "change_1d_pct": 0.42,  "rsi_14": 55.10, "...": "(full row)" },
    "X:BTCUSD": { "ticker": "X:BTCUSD", "name": "Bitcoin / US Dollar",   "asset_class": "crypto", "price": 118402.5, "change_1d_pct": 2.07, "rsi_14": 61.44, "...": "(full row)" }
  },
  "not_found": ["ZZZNOTREAL"]
}
```

## Notes

- Numeric signals carry their current value and every boolean its current state, so one call answers both "what is it" and "what is it doing".
- For the same row as of a past date, add `?asof=` — see [Ticker state (as-of)](/docs/endpoints/tickers/state#as-of). It means the same thing on the list form.
- The list form is the batch read: `requested` echoes the canonical symbols, `count` is how many were found, `data` holds one full row per found symbol, and `not_found` lists the rest in request order. A symbol we do not track is simply absent from `data` — it never fails the request. Symbols are de-duplicated and canonicalised (`aapl` → `AAPL`).
- For the catalog — which symbols exist and what they are — use [`GET /v2/tickers`](/docs/endpoints/tickers/catalog). It is identity-only and never returns state.
- The row's `branding_icon_url` and `branding_logo_url` are image endpoints on this API (`GET /v2/tickers/{ticker}/icon`, `/logo`): request them with the same `Authorization: Bearer` header and you get the image bytes with their `Content-Type`. Null when the issuer has no image on file.

---

Interactive sandbox + parameter editor: https://tickerbot.io/docs/endpoints/tickers/state


---

## GET /v2/tickers/{ticker}?asof=

**Ticker state (as-of)**

The whole wide ticker row as of a past date: booleans, indicators, and the fundamentals known then.

### Query / path parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `ticker` | path | string[] | yes | One symbol, or a comma-separated list of up to 50 — the list form answers `data` keyed by symbol, with each symbol's reconstruction under `_meta` by symbol. Case-insensitive. Equities are bare symbols (`AAPL`); every other class carries a prefix — rates (`R:SOFR`), crypto (`X:BTCUSD`), fx (`X:EURUSD`). Bare `BTC`/`ETH` are US-listed ETFs, not spot crypto. See [Tickers](/docs/tickers). Example: `AAPL`. |
| `asof` | query | string | yes | Target moment as `YYYY-MM-DD` or full ISO timestamp `YYYY-MM-DDTHH:MM:SSZ`. A date returns the row at the close of that day; a timestamp returns the row at that moment. A single-ticker read MERGES PER SIGNAL: each signal comes from the finest grain that carries it and has a row at or before the instant, so `price` can be the 17:45 value while `rsi_14` is that morning's daily figure. The row is a blend — `_meta.interval` is the finest grain present (not the whole row's age), `_meta.blended` flags it, and `_meta.sources` / `_meta.column_intervals` give the breakdown. The response returns the most-recent snapshot within the staleness window (14 days for daily) — the SAME rule as `/v2/scan?asof=` and `/v2/signals/{signal}?asof=`, unified 2026-07-27: asof means "the state AT that instant" everywhere. A ticker with no fresh-enough state (delisted, data gap) 404s with `last_available` and a pointer at the series endpoint for "last known state". Unlimited depth. Example: `2026-06-28`. |
| `interval` | query | string | no | Grain the past state is reconstructed at: `1m`, `1h`, `1d`, or `auto` (default). Same name and values as [Series](/docs/endpoints/series/state), [Bars](/docs/endpoints/bars/get), [Scan](/docs/endpoints/scan/state#as-of) and [Signals](/docs/endpoints/signals/state#as-of) — one vocabulary for "which grain" across the API. `auto` merges PER COLUMN: each column comes from the finest grain that stores it and has a row for this ticker, so `price` can be the 17:45 value while `rsi_14` is that day's daily figure. An explicit grain turns the merge OFF — every column comes from that one tier, or you get a `400`/`404` naming what is missing. Pin it when you need a row that actually existed at one instant, or one comparable to a scan row. Only valid alongside `asof` — a live read with `interval` is a 400. Enum: `1m`, `1h`, `1d`, `auto`. Default: `auto`. |

### Returns

- `as_of` (string) — The moment you asked about — the date's close, or the timestamp you passed.
- `ticker` (string) — The symbol you asked for, normalised.
- `_meta` (object) — How the row was reconstructed: `interval` is the finest grain present, `blended` says whether it mixes grains, `sources` / `column_intervals` give the per-grain breakdown, and `frozen_fields` names the signals that are NOT historized — they are present in `data` carrying their CURRENT values.
- `data` (object) — The full ticker row as it stood at that instant — every signal on the [schema page](/docs/schema).

### Status codes

- **200** — Success — the response shape is documented under Returns above.
- **400** — `bad_request` — `asof` missing or not `YYYY-MM-DD` / `YYYY-MM-DDTHH:MM:SSZ`.
- **401** — Missing or invalid API key.
- **404** — `not_found` — the ticker has no historical state at or before the requested date.

### Sample response

```json
{
  "as_of": "2026-03-01",
  "ticker": "AAPL",
  "_meta": {
    "interval": "1d",
    "interval_requested": "auto",
    "blended": false,
    "intervals_present": ["1d"],
    "frozen_fields": ["name", "sector", "industry", "asset_type", "exchange", "asset_class", "ticker_category"],
    "resolution": "daily",
    "sources": { "1d": { "ts": "2026-02-27T00:00:00.000Z", "contributed": "all" } }
  },
  "data": {
    "ticker": "AAPL",
    "date": "2026-02-27T00:00:00.000Z",
    "price": 264.18,
    "change_1d_pct": -3.213,
    "volume_today": 72366505,
    "rsi_14": 47.65,
    "above_sma_50": false,
    "pe_ratio": 33.22,
    "eps": 2.84,
    "...": "(full daily row)"
  }
}
```

### Notes

- This is [`GET /v2/tickers/{ticker}`](/docs/endpoints/tickers/state) with `?asof=` — the same endpoint as the live read, the second tense of the same page because point-in-time is its own question. It is the sibling of [Market-wide scan (as-of)](/docs/endpoints/scan/state#as-of) and [Ticker matches (as-of)](/docs/endpoints/signals/state#as-of), under one staleness rule — see [As-of queries](/docs/asof).
- For a ticker's values *over time*, use [Series](/docs/endpoints/series) instead: as-of answers "what did the row look like at t", series answers "how did it evolve".
- A missing or malformed `asof` returns `400 bad_request`; a date with no fresh-enough state returns `404 not_found` with `last_available` — the row must be within the staleness window (14 days for daily), the same rule as every other asof surface (unified 2026-07-27).
- The returned `data.date` may be earlier than the requested `asof` (weekend/holiday/gap) — it is the latest daily state within the window on or before that date. See the example: `asof=2026-03-01` (a Sunday) returns the `2026-02-27` row.
- `frozen_fields` are not historized; they're snapshots of the *current* value. The other signals are correct as of the requested date.
- Identity follows the symbol's holder at that date. When a different company held the symbol then (a reused symbol, e.g. `SHLD` in 2010 was Sears, today an ETF), `name`, `cik` and `composite_figi` are that holder's, `held_at_asof` is true with its `tenure_start`/`tenure_end`, `_meta.identity` names it, and the current holder's `sector`, `industry`, `asset_type`, `exchange`, `asset_class` and `ticker_category` come back null rather than mislabelling the old company. `_meta.frozen_fields` is empty on such a read.

---

Interactive sandbox + parameter editor: https://tickerbot.io/docs/endpoints/tickers/state#as-of
