View as markdown
Endpoints · Signals

Ticker matches (as-of)

GEThttps://api.tickerbot.io/v2/signals/{signal}?asof=

The set of tickers that matched one signal at a past moment.

stringrequired

A column on ticker. Boolean flags (e.g. golden_cross, above_sma_50) are detected automatically; numerics (e.g. rsi_14, market_cap, pe_ratio) require a condition.

stringrequired

Target moment as YYYY-MM-DD (the close of that day) or full ISO timestamp (that intraday moment). Unlimited depth.

enumdefault auto

Grain the past state is reconstructed at: 1m, 1h, 1d, or auto (default). Same name and values as Series and Bars. Not every column exists at every grain (rsi_14, fundamentals and valuation ratios are 1d-only), and a cross-section must resolve to ONE grain — so without this, one 1d-only column in the projection silently re-dated every other column in the request. With it set, that case is a 400 interval_unavailable naming the column and the grains that carry it. auto picks the finest servable grain and reports which in _meta.interval / _meta.interval_reason.

1mOne minute. The finest stored tier; carries the intraday column subset and ~1,100 of ~13,700 tickers.
1hOne hour. Stored tier, intraday column subset, full universe.
1dOne day. The full-history, full-column tier — the only grain that carries daily-only columns (SMAs, RSI, fundamentals).
autodefaultLet the server pick the finest grain whose columns and ticker coverage both work out, resolving upward on a miss. Reported in _meta.interval.
string

Required for numeric signals. Single-bounded condition: <op><value>. Operators: >, >=, =, !=, <, <=. Sending one with a boolean flag or custom signal returns 400 (it does not apply).

string

Scope to a system or caller-owned universe slug.

integerdefault 50

Page size. Max 200.

string

Opaque cursor from the previous response.

as_ofstring

The moment you asked about — the date's close, or the timestamp you passed.

signalstring

The signal you asked for.

conditionstring

The bound you passed, echoed; `null` for boolean and custom signals.

universestring

The universe you scoped to, echoed; `null` when unscoped.

_metaobject

Grain served (`interval`), why (`interval_reason`), `frozen_fields`, and `coverage_gap` when one applies. `_meta.resolution` is a deprecated alias of `interval`.

countnumber

Rows in this page.

next_cursorstring

Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.

resultsarray

Tickers that matched at that instant.

200
Success — the response shape is documented under Returns above.
400
Missing/malformed asof, numeric signal called without condition, or invalid cursor.
404
Signal name does not exist on the schema.
  • This is GET /v2/signals/{signal} with ?asof=as-of at one-signal scope, on its own page because point-in-time is its own question. The response envelope matches the live call, plus _meta describing the grain served and why.
  • Pass asof as a YYYY-MM-DD date (that day's close) or a full ISO timestamp (that intraday moment), and pick the grain with interval. A match set is a cross-section, so it resolves to ONE grain — and 1m is only servable for a scoped universe, since the minute tier carries ~1,100 of ~13,700 tickers.
  • Custom signals: {signal} may be one of your custom signals — it resolves as a boolean signal. See Create a custom signal.
  • A match set spans every asset class the signal is defined for, so R: rates and X: FX/crypto instruments appear alongside equities — the example above is topped by Fed funds rates, not stocks. Scope with universe (or filter asset_class via /v2/scan) when you want one class.
  • Static fields aren't historized — name, sector, industry, asset_type, and exchange reflect their *current* values. _meta.frozen_fields lists exactly which ones.
  • For per-ticker time series of one signal across many bars (not a point-in-time snapshot), use Series?ticker={t}&columns={signal}.
  • Unlimited depth.
  • A date-only asof resolves to the close of that day. A full ISO timestamp (…T15:30:00Z) resolves intraday at the grain you name with interval (1m/1h/1d/auto). _meta.interval reports the grain served and _meta.interval_reason why; tickers with no row at that grain are disclosed in _meta.coverage_gap with a sample. Illiquid instruments (SPAC warrants, units, rights) routinely have no intraday print, so a small coverage_gap at 1m/1h is normal rather than a fault. If there is no state exactly at the requested moment (weekend, holiday, or a gap), the server carries forward the most-recent row within the lookback window (14 days at daily resolution, 5 days for intraday granularities) — a Saturday asof returns Friday's values, not an empty set. Beyond the window you get an empty results array with the echoed asof. (/v2/tickers/{ticker}?asof= applies the identical staleness rule since 2026-07-27, and 404s with last_available when nothing is fresh enough.)
  • Membership is point-in-time (survivorship-safe): the as-of set includes tickers that were listed and not yet delisted at that instant, so a since-delisted name can legitimately appear. The live read of this same endpoint returns currently-active tickers only.
Boolean flag — who was at a 52-week high that day
curl "https://api.tickerbot.io/v2/signals/at_52w_high?asof=2024-02-23&limit=3" \
  -H "Authorization: Bearer YOUR_KEY"
Response
{
  "as_of": "2024-02-23",
  "signal": "at_52w_high",
  "condition": null,
  "universe": null,
  "_meta": {
    "interval": "1d",
    "interval_requested": "auto",
    "interval_reason": "date-only asof resolves to the daily close",
    "resolution": "daily",
    "frozen_fields": ["name", "sector", "industry", "asset_type", "exchange", "asset_class", "ticker_category"]
  },
  "count": 3,
  "next_cursor": "eyJhZnRlcl90aWNrZXIiOiJBRkxHIn0",
  "results": [
    { "ticker": "ABEQ", "name": "Absolute Select Value ETF",              "value": true },
    { "ticker": "ACR",  "name": "ACRES Commercial Realty Corp.",          "value": true },
    { "ticker": "AFLG", "name": "First Trust Active Factor Large Cap ETF", "value": true }
  ]
}