Ticker matches (as-of)
https://api.tickerbot.io/ v2/ signals/ {signal}?asof=The set of tickers that matched one signal at a past moment.
Query parameters
stringrequiredA 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.
stringrequiredTarget moment as YYYY-MM-DD (the close of that day) or full ISO timestamp (that intraday moment). Unlimited depth.
enumdefault autoGrain 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.
1m | One minute. The finest stored tier; carries the intraday column subset and ~1,100 of ~13,700 tickers. |
1h | One hour. Stored tier, intraday column subset, full universe. |
1d | One day. The full-history, full-column tier — the only grain that carries daily-only columns (SMAs, RSI, fundamentals). |
autodefault | Let the server pick the finest grain whose columns and ticker coverage both work out, resolving upward on a miss. Reported in _meta.interval. |
stringRequired for numeric signals. Single-bounded condition: <op><value>. Operators: >, >=, =, !=, <, <=. Sending one with a boolean flag or custom signal returns 400 (it does not apply).
stringScope to a system or caller-owned universe slug.
integerdefault 50Page size. Max 200.
stringOpaque cursor from the previous response.
Returns
as_ofstringThe moment you asked about — the date's close, or the timestamp you passed.
signalstringThe signal you asked for.
conditionstringThe bound you passed, echoed; `null` for boolean and custom signals.
universestringThe universe you scoped to, echoed; `null` when unscoped.
_metaobjectGrain served (`interval`), why (`interval_reason`), `frozen_fields`, and `coverage_gap` when one applies. `_meta.resolution` is a deprecated alias of `interval`.
countnumberRows in this page.
next_cursorstringOpaque token for the next page; `null` on the last page. Pass it back as `cursor`.
resultsarrayTickers that matched at that instant.
Status codes
200400asof, numeric signal called without condition, or invalid cursor.404Notes
- 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_metadescribing the grain served and why. - Pass
asofas aYYYY-MM-DDdate (that day's close) or a full ISO timestamp (that intraday moment), and pick the grain withinterval. A match set is a cross-section, so it resolves to ONE grain — and1mis only servable for a scopeduniverse, 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 andX:FX/crypto instruments appear alongside equities — the example above is topped by Fed funds rates, not stocks. Scope withuniverse(or filterasset_classvia /v2/scan) when you want one class. - Static fields aren't historized —
name,sector,industry,asset_type, andexchangereflect their *current* values._meta.frozen_fieldslists 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
asofresolves to the close of that day. A full ISO timestamp (…T15:30:00Z) resolves intraday at the grain you name withinterval(1m/1h/1d/auto)._meta.intervalreports the grain served and_meta.interval_reasonwhy; tickers with no row at that grain are disclosed in_meta.coverage_gapwith a sample. Illiquid instruments (SPAC warrants, units, rights) routinely have no intraday print, so a smallcoverage_gapat1m/1his 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 Saturdayasofreturns Friday's values, not an empty set. Beyond the window you get an emptyresultsarray with the echoedasof. (/v2/tickers/{ticker}?asof=applies the identical staleness rule since 2026-07-27, and 404s withlast_availablewhen 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.
More examples
curl "https://api.tickerbot.io/v2/signals/at_52w_high?asof=2024-02-23&limit=3" \
-H "Authorization: Bearer YOUR_KEY"{
"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 }
]
}