Every change Wellknown observed on this MCP server, newest first, with what it was before and what it became. Tool-surface changes carry the definition diff. Nothing here is edited after the fact.
Authorization required, Bearer, issuer https://api.tickerbot.io
Authorization required, Bearer, issuer https://api.tickerbot.io
Authorization required, Bearer, issuer https://api.tickerbot.io
Authorization required, Bearer, issuer https://api.tickerbot.io
Authorization required, Bearer, issuer https://api.tickerbot.io
Authorization not required → required, Bearer, issuer https://api.tickerbot.io
Authorization not required, issuer https://api.tickerbot.io
Authorization not required, issuer https://api.tickerbot.io
Changed the definition of "tickerbot_get_bars", "tickerbot_get_series", "tickerbot_get_ticker" and 1 more
⟨127 unchanged words⟩ not happened, so `1d` returns Tuesday's bar. A bare date on an intraday grid (`1m`, `1h`, …) is accepted and means the last bar of that UTC day. Returns one bar unless you also pass `limit`, ⟨17 unchanged words⟩ Mutually exclusive with `before` (400). Unlimited depth. Response time: under 1.5 s cold, under 0.5 s warm.","type":"string"},"before":{ ⟨316 unchanged words⟩
⟨143 unchanged words⟩ requested ticker is on the one page). A ticker with no row on the grid at or before the instant (outside the roughly 1,000-ticker minute tier, say) comes back as an empty array with `_meta.coverage[ticker].rows: 0`, never a 404. A bare date on the `1m`/`1h` grid is accepted and means the last row of that UTC day (the state reads 400 that combination; this grid read does not). The look-back is the grid's window: `1d` walks back without limit, `1h` 60 days and `1m` 7 days before the instant.
Changed the definition of "tickerbot_get_bars", "tickerbot_get_series", "tickerbot_get_signal" and 3 more
⟨141 unchanged words⟩ `limit`, which gives the last `limit` closedbars.bars; follow `next_cursor` with the same parameters to keep paging back. Mutually exclusive with`before`/`cursor``before` (400). Unlimited depth.","type":" ⟨318 unchanged words⟩
⟨111 unchanged words⟩ a trading gap gives the last row beforeit.
Changed the definition of "tickerbot_scan"
⟨441 unchanged words⟩ own. Omitted, the scan runs across all~21~23,963203 tracked tickers.","type":"string"}}, ⟨4 unchanged words⟩
Authorization not required, issuer https://api.tickerbot.io
Changed the definition of "tickerbot_list_events" and "tickerbot_scan"
⟨334 unchanged words⟩ kinds. Omitted → the five corporate kinds; `signal`, `news` and`news``estimate_revision` join only when named here.","enum": ⟨3 unchanged words⟩ ","analyst","earnings","signal","news","estimate_revision"],"type":"string"},"limit": ⟨303 unchanged words⟩
Only numbers and dates differ: this server embeds live figures in the definition, so the text moves without the contract changing.
Changed the definition of "tickerbot_scan"
Only numbers and dates differ: this server embeds live figures in the definition, so the text moves without the contract changing.
⟨442 unchanged words⟩ Omitted, the scan runs across all ~21,082122 tracked tickers.","type":"string"}}, ⟨4 unchanged words⟩
Authorization not required, issuer https://api.tickerbot.io
Changed the definition of "tickerbot_get_bars" and "tickerbot_get_ticker_coverage"
⟨68 unchanged words⟩ :"number"},"coverage":{"description":"Why the page looks the way it does:`covered` when bars were found, `no_data` whenthenothingvendorexistshasfornonetheforsymbol in the window (before its first session,`not_in_minute_tier`awhenmarket
Changed the definition of "tickerbot_list_events"
{"additionalProperties":false,"properties":{"_meta":{"description":"With `join=state` only: `state_interval`, the grain the joined state was read at, and `deprecated_columns` when a state column was named under its pre-2026-09-07 spelling and served under its current name (`requested`, `use`, `note`).","type":"object"},"as_of":{"description":"Server time this response ⟨148 unchanged words⟩
Changed the definition of "tickerbot_create_custom_signal", "tickerbot_create_webhook", "tickerbot_get_series" and 7 more
⟨91 unchanged words⟩ you read back: responses echo your expressionVERBATIMas stored, not its expansion. A signal referencing another ⟨19 unchanged words⟩ what a subscribe endpoint freezes into a webhook. The one rewrite: a column named under its pre-2026-09-07 spelling (`bollinger_pct_b`) is stored under its current name (`bollinger_b`) and reported in `_meta.deprecated_columns`.","type":"string"},"name":{ ⟨64 unchanged words⟩
{"additionalProperties":false,"properties":{"_meta":{"description":"Only when `expr` named a column under its pre-2026-09-07 spelling: `deprecated_columns` lists each one (`requested`, `use`, `note`). The stored `expr` carries the current name.","type":"object"},"as_of":{"description":"Server time this response
Authorization not required, issuer https://api.tickerbot.io
Authorization not required, issuer https://api.tickerbot.io
Changed the definition of "tickerbot_create_webhook", "tickerbot_get_etf_holdings", "tickerbot_subscribe_events" and 3 more
⟨527 unchanged words⟩ ,"next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}
⟨86 unchanged words⟩ as_of","ticker","is_etf","count","truncated","total","holdings"],"type":"object"}
Changed the definition of "tickerbot_get_bars", "tickerbot_list_tickers" and "tickerbot_scan"
⟨252 unchanged words⟩ "string"}},"required":["as_of","ticker","interval","adjusted","session","count"," ⟨4 unchanged words⟩
{"additionalProperties":false,"properties":{"_meta":{"description":"With `asset_class` only: `scope.asset_class` lists the classes the page was filtered to.","type":"object"},"as_of":{"description":"Server time this response ⟨72 unchanged words⟩
Changed the definition of "tickerbot_create_webhook", "tickerbot_get_signal" and "tickerbot_subscribe_signal"
⟨260 unchanged words⟩ condition":{"description":"signal: required fornumericeverysignalsnon-boolean signal — a single bound typed like`>70`;the signal: `>70` (numeric), `<YYYY-MM-DDTHH:MM:SSZ` (timestamp), `>=YYYY-MM-DD` (date), `=ETF` (string); sending one with a boolean or custom signal ⟨249 unchanged words⟩
Authorization not required, issuer https://api.tickerbot.io
Changed the definition of "tickerbot_scan"
Only numbers and dates differ: this server embeds live figures in the definition, so the text moves without the contract changing.
⟨442 unchanged words⟩ Omitted, the scan runs across all ~21,066072 tracked tickers.","type":"string"}}, ⟨4 unchanged words⟩
Changed the definition of "tickerbot_scan"
Only numbers and dates differ: this server embeds live figures in the definition, so the text moves without the contract changing.
⟨442 unchanged words⟩ Omitted, the scan runs across all ~21,053066 tracked tickers.","type":"string"}}, ⟨4 unchanged words⟩
Authorization not required, issuer https://api.tickerbot.io
Changed the definition of "tickerbot_get_bars"
OHLCV bars from 1-second through monthly. Thefeedprices underneath the table.
Authorization not required, issuer https://api.tickerbot.io
Changed the definition of "tickerbot_scan"
Only numbers and dates differ: this server embeds live figures in the definition, so the text moves without the contract changing.
⟨442 unchanged words⟩ Omitted, the scan runs across all ~21,040053 tracked tickers.","type":"string"}}, ⟨4 unchanged words⟩
Changed the definition of "tickerbot_create_custom_signal", "tickerbot_create_universe", "tickerbot_create_webhook" and 26 more
before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"signal":{"description":"The stored signal: `name`, `kind` (`custom`), `description`, `expr` (your predicate as stored), `created_at`, `updated_at`.","type":"object"}},"required":["as_of","signal"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"created_at":{"description":"Creation timestamp.","type":"number"},"description":{"description":"Free-form notes; `\"\"` when unset.","type":"string"},"effective_at":{"description":"System universes only; absent on yours.","type":"number"},"id":{"description":"The slug — the universe's handle in `?universe=`.","type":"string"},"name":{"description":"Display label.","type":"string"},"next_rebalance_at":{"description":"System universes only; absent on yours.","type":"number"},"rebalance_method":{"description":"System universes only; absent on yours.","type":"string"},"size":{"description":"Member count.","type":"number"},"system":{"description":"`false` — this is your universe.","type":"boolean"},"tickers":{"description":"Members, after this call.","items":{"type":"string"},"type":"array"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","description","tickers","size","system","created_at","updated_at"],"type":"object"}Authorization not required, issuer https://api.tickerbot.io
Added "tickerbot_get_bars", "tickerbot_get_etf_holdings", "tickerbot_get_etf_sectors" and 3 more; removed "tickerbot_get_signals_match", "tickerbot_get_ticker_bars", "tickerbot_get_ticker_history" and 5 more; changed the definition of "tickerbot_create_custom_signal", "tickerbot_create_universe", "tickerbot_create_webhook" and 23 more (34 tools before, 32 now)
Save a SQL WHERE expression as aA namedcustom signalbooleanthepredicatecalleryou can referencebyanywherenameainbuilt-infuturesignal
Changed the definition of "tickerbot_get_series", "tickerbot_get_signals_match", "tickerbot_get_ticker" and 6 more
THE series primitive: cross-ticker,multi-columnmulti-signal time series on one aligned grid. Pick up to 25columnssignals (price, OHLCV, indicators like rsi_14,boolean flagsbooleans, custom signals) and up to 50 tickers; ⟨13 unchanged words⟩ …}), cursor-paged backward. `transitions_only=true` with booleancolumnssignals returns only the rows where aflagboolean CHANGED — "every golden_cross flip this year" ⟨20 unchanged words⟩
Authorization not required, issuer https://api.tickerbot.io
Removed "tickerbot_list_signal_events"; changed the definition of "tickerbot_get_ticker_bars" and "tickerbot_list_events" (35 tools before, 34 now)
{"properties":{"adjusted":{"description":"Default true: prices split-adjusted (restated after each later split, as the tape is). false = the price as it printed on the tape that day — what a broker fill or a chart from that time shows. Volume scales the other way.","type":"boolean"},"asof":{"description":"Return a single bar ⟨96 unchanged words⟩ N bars. Default 100.","type":"integer"},"session":{"description":"Sub-hour intervals only. `all` (default) includes pre/post-market; `regular` keeps 09:30–16:00 ET bars, which drops late-reported off-exchange (Form T) prints that land in early-morning minutes.","enum":["all","regular"],"type":"string"},"ticker":{"description":"Symbol, ⟨46 unchanged words⟩
Authorization not required, issuer https://api.tickerbot.io
Certificate recorded, valid to 2026-12-11
Authorization not required, issuer https://api.tickerbot.io
First tool surface recorded: 35 tools (server version 0.2.0)
Showing the latest 40 events. The API returns up to 500 and filters by kind: ?kind=tool_surface_changed
⟨113 unchanged words⟩ response: one grain is read instead ofthree,three.andOneverythistickersingle-tickerisreadcapturedaonpinned grain returns thesamecolumnsclock.thatAgrainsignalstoresthe(`rsi_14`,pinnedfundamentalsgrainanddoesvaluationnotratiosstoreareis`1d`-only, so they are absent under `1h`/`1m` rather than refused), and a`400graininterval_unavailable`withnamingnotherowgrainsforthatthecarrytickeritwithin(`rsi_14`,itsfundamentals5-dayandwindowvaluationisratiosaare`404`1d`-only).interval_unavailable`. Only valid alongside `asof`: a live read ⟨71 unchanged words⟩
⟨296 unchanged words⟩ the grain does not store is a `400`. The names accepted are the daily table's columns at every grain (an hourly- or minute-only signal is unknown here even pinned to `1m`). Reported as `_meta.state_interval` (`auto` with `_meta.state_blended: true`, ⟨386 unchanged words⟩
⟨10 unchanged words⟩ close) or an ISO timestamp (that intradaymomentmoment; daily-only signals then carry the previous session's close, never that day's) — the same read as it stood ⟨200 unchanged words⟩ ,"description":"Grain the past state isreconstructedread at: `1m`, `1h`, `1d`, or `auto` (default).Only`auto`validblends:alongsideeach`asof`signal—comes from its freshest grain at or before the instant (minute, then hourly, then the last closed daily session), so nothing is refused for grain and no ticker is dropped; `_meta.blended` and `_meta.intervals_present` say what contributed. Pin alivegrain for the fastest response: one grain is readwithinstead`interval`of three, and every ticker is captured on the same clock. A signal the pinned grain does not store is a400.`400Detailsinterval_unavailable`undernamingAstheofgrains that carry it (`rsi_14`, fundamentals and valuation ratios are `1d`-only). Only valid alongside `asof`: apastlivedate.read with `interval` is a 400.","enum":["1m","1h"," ⟨103 unchanged words⟩
⟨10 unchanged words⟩ close) or an ISO timestamp (that intradaymomentmoment; daily-only signals then carry the previous session's close, never that day's) — the same read as it stood ⟨16 unchanged words⟩ ,"description":"Grain the past state isreconstructedread at: `1m`, `1h`, `1d`, or `auto` (default).Only`auto`validblends:alongsideeach`asof`signal—comes from its freshest grain at or before the instant (minute, then hourly, then the last closed daily session), so nothing is refused for grain and no ticker is dropped; `_meta.blended` and `_meta.intervals_present` say what contributed. Pin alivegrain for the fastest response: one grain is readwithinstead`interval`of three, and every ticker is captured on the same clock. A signal the pinned grain does not store is a400.`400Detailsinterval_unavailable`undernamingAstheofgrains that carry it (`rsi_14`, fundamentals and valuation ratios are `1d`-only). Only valid alongside `asof`: apastlivedate.read with `interval` is a 400.","enum":["1m","1h"," ⟨63 unchanged words⟩
⟨212 unchanged words⟩ ,"description":"Grain the per-event state isreconstructedread at, when `join=state`: `1m`, `1h`, `1d`, or `auto` (default). Under `auto`,resolvesrowtoreads`1d`blend—eachthesignaleventatset'sitstickersfreshestaregrainnotatknownor before thequeryeventrunsacross hourly and the last closed daily session, and`1d``group_by`isreads use theonlydailytiersession;coveringeventsthejoinwholestateuniverse,oncesoperitevent,isso theonlyminute grainguaranteedistoreachedsatisfybyeverypinningevent.`1m`.AnAexplicitpinned`1m`/`1h`graintradesreadscoveragethatforgrainprecisiononly: events on tickers absent fromthatatierpinned `1m`/`1h` join to`null`.`null`,Aandreferenceda column the grain does not store is a `400`. Reportedbackas`_meta.state_interval`.`_meta.state_interval` (`auto` with `_meta.state_blended: true`, or the pinned grain).","enum":["1m","1h"," ⟨14 unchanged words⟩ `q`/`select`/`group_by`/`having`, evaluated as of each event's timestamp(at daily resolution).: an event on day D sees the daily state through D-1, never D's close.","enum":["state"],"type": ⟨337 unchanged words⟩
⟨10 unchanged words⟩ close) or an ISO timestamp (that intradaymomentmoment; daily-only signals then carry the previous session's close, never that day's) — the same read as it stood ⟨212 unchanged words⟩ ,"description":"Grain the past state isreconstructedread at: `1m`, `1h`, `1d`, or `auto` (default).Only`auto`validblends:alongsideeach`asof`signal—comes from its freshest grain at or before the instant (minute, then hourly, then the last closed daily session), so nothing is refused for grain and no ticker is dropped; `_meta.blended` and `_meta.intervals_present` say what contributed. Pin alivegrain for the fastest response: one grain is readwithinstead`interval`of three, and every ticker is captured on the same clock. A signal the pinned grain does not store is a400.`400Detailsinterval_unavailable`undernamingAstheofgrains that carry it (`rsi_14`, fundamentals and valuation ratios are `1d`-only). Only valid alongside `asof`: apastlivedate.read with `interval` is a 400.","enum":["1m","1h"," ⟨167 unchanged words⟩ Omitted, the scan runs across all ~23,203212 tracked tickers.","type":"string"}}, ⟨4 unchanged words⟩
⟨23 unchanged words⟩ gap in bars or series as an outage.`minute_tier.included: false`Anwithabsent`on_demand:`minute`true`span is not a gap — sub-hour barsfetchloadfromon theproviderfirstonrequestfirstforrequest.a symbol.
⟨49 unchanged words⟩ :"array"},"minute_tier":{"description":"Whether this ticker isDeprecatedin(see theminute tier (`included`changelog)and its `rank` within it. `included:false`is NOT \"noanintradayinternaldata\":precomputetherosterobjectthatthenhascarriesno`on_demand:bearingtrue`,on`first_call_latency`what(`\"3-10s\"`)barsandyou`window_days`can(31)read — sub-hour barsfor the symbolarefetched from the provider on first request and stored, so theavailablefirstforcalleveryisactiveslowsymbol.andDolaternotonesbranchareonsub-second.it.","type":"object"},"name":{ ⟨35 unchanged words⟩
{"additionalProperties":false,"properties":{"_meta":{"description":"Returned on create only, and only when the rule or `columns` named a column under its pre-2026-09-07 spelling: `deprecated_columns` lists each one (`requested`, `use`, `note`). The stored rule carries the current name.","type":"object"},"as_of":{"description":"Server time this response ⟨524 unchanged words⟩
⟨22 unchanged words⟩ `non_trading_days_dropped` / `transitions_only` / `from_defaulted` when they apply. `deprecated_columns` lists any column you named under its pre-2026-09-07 spelling that was served under its current name (`requested`, `use`, `note`).","type":"object"},"as_of":{ ⟨107 unchanged words⟩
⟨3 unchanged words⟩ ":{"_meta":{"description":"With `asof`only: how the read was resolved — interval served and requested, blending, sources, frozenfields.fieldsSee(see the as-of readbelow.below). On any read, `deprecated_columns` when you named the signal under its pre-2026-09-07 spelling and it was served under its current name.","type":"object"},"as_of":{ ⟨100 unchanged words⟩
⟨34 unchanged words⟩ match\". `scope` additionally describes an explicit `universe`. `deprecated_columns` lists any column you named under its pre-2026-09-07 spelling that was served under its current name (`requested`, `use`, `note`).","type":"object"},"as_of":{ ⟨110 unchanged words⟩
{"additionalProperties":false,"properties":{"_meta":{"description":"Returned on create only, and only when the rule or `columns` named a column under its pre-2026-09-07 spelling: `deprecated_columns` lists each one (`requested`, `use`, `note`). The stored rule carries the current name.","type":"object"},"as_of":{"description":"Server time this response ⟨524 unchanged words⟩
{"additionalProperties":false,"properties":{"_meta":{"description":"Returned on create only, and only when the rule or `columns` named a column under its pre-2026-09-07 spelling: `deprecated_columns` lists each one (`requested`, `use`, `note`). The stored rule carries the current name.","type":"object"},"as_of":{"description":"Server time this response ⟨524 unchanged words⟩
{"additionalProperties":false,"properties":{"_meta":{"description":"Returned on create only, and only when the rule or `columns` named a column under its pre-2026-09-07 spelling: `deprecated_columns` lists each one (`requested`, `use`, `note`). The stored rule carries the current name.","type":"object"},"as_of":{"description":"Server time this response ⟨524 unchanged words⟩
{"additionalProperties":false,"properties":{"_meta":{"description":"Returned on create only, and only when the rule or `columns` named a column under its pre-2026-09-07 spelling: `deprecated_columns` lists each one (`requested`, `use`, `note`). The stored rule carries the current name.","type":"object"},"as_of":{"description":"Server time this response ⟨524 unchanged words⟩
⟨49 unchanged words⟩ functions beyond `abs`/`coalesce`/`round`/`least`/`greatest`. The response echoes your expressionverbatimas stored, not itsexpansion.expansion (a pre-2026-09-07 column spelling is stored under its current name and reported in `_meta.deprecated_columns`).","type":"string"},"new_name":{ ⟨79 unchanged words⟩
{"additionalProperties":false,"properties":{"_meta":{"description":"Only when `expr` named a column under its pre-2026-09-07 spelling: `deprecated_columns` lists each one (`requested`, `use`, `note`). The stored `expr` carries the current name.","type":"object"},"as_of":{"description":"Server time this response ⟨30 unchanged words⟩
⟨527 unchanged words⟩ ,"next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}
⟨527 unchanged words⟩ ,"next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}
⟨527 unchanged words⟩ ,"next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}
⟨527 unchanged words⟩ ,"next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}
Only numbers and dates differ: this server embeds live figures in the definition, so the text moves without the contract changing.
⟨442 unchanged words⟩ Omitted, the scan runs across all ~21,072082 tracked tickers.","type":"string"}}, ⟨4 unchanged words⟩
⟨25 unchanged words⟩ market, one call. Booleans need no `condition`;numericseveryneedother type needs one, typed like the signal: ">70" (numeric), "<YYYY-MM-DDTHH:MM:SSZ" (timestamp), ">=YYYY-MM-DD" (date), "=ETF" (string). Sorted by signal value desc fornumerics.non-booleans.
⟨38 unchanged words⟩ },"condition":{"description":"Required fornumericeverysignals.non-boolean signal; the shape follows the signal's `type` in the catalog. Single bound,format`<op><value>`.Operatorsnumeric: `>70`, `<=200`, `!=0` (operators `>`, `>=`, `=`, `!=`, `<`,`<=`.`<=`).Examplestimestamp:`>70`,an`<=200`ISO instant,`!=0`.`<YYYY-MM-DDTHH:MM:SSZ` or `>=YYYY-MM-DD` (a bare date is midnight UTC). date: `>=YYYY-MM-DD` or `=YYYY-MM-DD`. string: `=ETF` or `!=ETF` (`=` and `!=` only; quotes optional). A relative window (\"older than 15 minutes\") is a `/v2/scan` query: `price_asof < now() - interval '15 minutes'`. Sendingonea condition with a boolean or custom signal returns 400 ⟨153 unchanged words⟩ (e.g. `golden_cross`, `above_sma_50`) are detected automatically;numericsevery other type (e.g.numeric `rsi_14`,`market_cap`timestamp `price_asof`,`pe_ratio`date `earnings_date`, string `asset_class`)requirerequires acondition.`condition`.","type":"string"},"sort_by":{ ⟨60 unchanged words⟩
⟨160 unchanged words⟩ },"condition":{"description":"Required fornumericeverysignals.non-booleanShapesignal; the shape follows the signal's `type`. Numeric: `\">70\"`, `\"<30\"`, `\">=100\"`. Timestamp: `\"<YYYY-MM-DDTHH:MM:SSZ\"`,(or a bare date). Date: `\"=50\>=YYYY-MM-DD\"`. String: `\"=ETF\"` or `\"!=ETF\"`. Sending one with a boolean or custom ⟨231 unchanged words⟩
before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"cadence":{"description":"How often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.","type":"string"},"channel":{"description":"Where deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.","type":"string"},"channel_config":{"description":"Returned on create only: the channel-specific delivery settings as stored (e.g. the Discord URL, the device id).","type":"object"},"created_at":{"description":"Creation timestamp.","type":"number"},"delivery":{"description":"Legacy alias of `channel`, kept aligned for older readers.","type":"string"},"dir":{"description":"Sort direction for that list; `null` means the default (`desc`).","type":"string"},"event_kinds":{"description":"Event-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).","items":{"type":"string"},"type":"array"},"event_q":{"description":"Event-trigger webhooks only: the payload filter, or `null`.","type":"string"},"event_tickers":{"description":"Event-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.","items":{"type":"string"},"type":"array"},"fields":{"description":"Extra signals carried on each fired match row; `null` means the standard set.","type":"string"},"id":{"description":"The webhook id — `wh_…`, the handle for every other call on this record.","type":"string"},"last_error":{"description":"The last evaluation error; `null` on a healthy hook. The answer to \"why is my webhook not firing?\".","type":"string"},"last_eval_error_at":{"description":"When the last evaluation error happened; `null` on a healthy hook.","type":"number"},"last_evaluated_at":{"description":"When it was last evaluated; `null` until the first run.","type":"number"},"last_fired":{"description":"When a delivery last went out; `null` if it never has.","type":"number"},"last_match_set":{"description":"Tickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.","items":{"type":"string"},"type":"array"},"last_predicate_value":{"description":"The trigger's value at the last evaluation; `null` until it has run.","type":"string"},"name":{"description":"Your label for the subscription.","type":"string"},"next_eval_at":{"description":"When the evaluator will next consider this subscription.","type":"number"},"order":{"description":"Sort signal for the payload row list; `null` means the evaluator default (`market_cap`).","type":"string"},"q":{"description":"The stored predicate. Custom signals appear expanded: the SQL is frozen at creation.","type":"string"},"rule_id":{"description":"Legacy link to a v1 alert rule; `null` on everything created through v2.","type":"string"},"signing_secret":{"description":"Returned on create only — shown once, never again. HMAC key for verifying the `X-Tickerbot-Signature` header on deliveries.","type":"string"},"source":{"description":"Which API version created the record; `v2` for anything you create today.","type":"string"},"status":{"description":"`active` or `disabled`. Auto-disable follows repeated delivery failure.","type":"string"},"subscription_origin":{"description":"Which door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.","type":"object"},"target_url":{"description":"Your HTTPS endpoint; `null` on every channel except `webhook`.","type":"string"},"test_url":{"description":"Returned on create only: the `POST /v2/webhooks/{id}/test` URL for this record.","type":"string"},"trigger_kind":{"description":"Event-trigger webhooks only: `event`.","type":"string"},"universe_id":{"description":"Universe the trigger is scoped to, or `null` for the whole market.","type":"string"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","q","rule_id","fields","order","dir","universe_id","cadence","channel","target_url","delivery","status","source","subscription_origin","last_predicate_value","created_at","updated_at","last_fired","last_match_set","next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"cadence":{"description":"How often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.","type":"string"},"channel":{"description":"Where deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.","type":"string"},"created_at":{"description":"Creation timestamp.","type":"number"},"delivery":{"description":"Legacy alias of `channel`, kept aligned for older readers.","type":"string"},"dir":{"description":"Sort direction for that list; `null` means the default (`desc`).","type":"string"},"event_kinds":{"description":"Event-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).","items":{"type":"string"},"type":"array"},"event_q":{"description":"Event-trigger webhooks only: the payload filter, or `null`.","type":"string"},"event_tickers":{"description":"Event-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.","items":{"type":"string"},"type":"array"},"fields":{"description":"Extra signals carried on each fired match row; `null` means the standard set.","type":"string"},"id":{"description":"The webhook id — `wh_…`, the handle for every other call on this record.","type":"string"},"last_error":{"description":"The last evaluation error; `null` on a healthy hook. The answer to \"why is my webhook not firing?\".","type":"string"},"last_eval_error_at":{"description":"When the last evaluation error happened; `null` on a healthy hook.","type":"number"},"last_evaluated_at":{"description":"When it was last evaluated; `null` until the first run.","type":"number"},"last_fired":{"description":"When a delivery last went out; `null` if it never has.","type":"number"},"last_match_set":{"description":"Tickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.","items":{"type":"string"},"type":"array"},"last_predicate_value":{"description":"The trigger's value at the last evaluation; `null` until it has run.","type":"string"},"name":{"description":"Your label for the subscription.","type":"string"},"next_eval_at":{"description":"When the evaluator will next consider this subscription.","type":"number"},"order":{"description":"Sort signal for the payload row list; `null` means the evaluator default (`market_cap`).","type":"string"},"q":{"description":"The stored predicate. Custom signals appear expanded: the SQL is frozen at creation.","type":"string"},"rule_id":{"description":"Legacy link to a v1 alert rule; `null` on everything created through v2.","type":"string"},"source":{"description":"Which API version created the record; `v2` for anything you create today.","type":"string"},"status":{"description":"`active` or `disabled`. Auto-disable follows repeated delivery failure.","type":"string"},"subscription_origin":{"description":"Which door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.","type":"object"},"target_url":{"description":"Your HTTPS endpoint; `null` on every channel except `webhook`.","type":"string"},"trigger_kind":{"description":"Event-trigger webhooks only: `event`.","type":"string"},"universe_id":{"description":"Universe the trigger is scoped to, or `null` for the whole market.","type":"string"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","q","rule_id","fields","order","dir","universe_id","cadence","channel","target_url","delivery","status","source","subscription_origin","last_predicate_value","created_at","updated_at","last_fired","last_match_set","next_eval_at","last_evaluated_at"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"adjusted":{"description":"Whether the bars are split-adjusted — `true` unless you passed `adjusted=false`.","type":"boolean"},"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"bars":{"description":"OHLCV bars, chronological, in the compact array shape. Bulk requests key this by symbol instead.","items":{"type":"string"},"type":"array"},"count":{"description":"Bars returned in single-symbol mode; the number of SYMBOLS in bulk mode.","type":"number"},"coverage":{"description":"Why the page looks the way it does: `covered` when bars were found, `no_data` when the vendor has none for the window, `not_in_minute_tier` when a sub-hour interval was asked of a symbol the minute store does not carry.","type":"string"},"interval":{"description":"The bar size served.","type":"string"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Absent on bulk (comma-list) requests, which are unpaged. Absent on bulk requests — page bulk symbol-by-symbol.","type":"string"},"note":{"description":"Present only when there is something to disclose about how the page was served: the first on-demand fetch for an untiered symbol (explains the latency; later calls are stored), or a `1s` page served from the local store because the provider could not be reached. Bulk responses carry `notes[symbol]` instead.","type":"string"},"notes":{"description":"Bulk (comma-list) requests only: the per-symbol disclosures, keyed by symbol, in place of `note`.","type":"object"},"session":{"description":"The session filter applied: `all` (default) or `regular` (09:30–16:00 ET, sub-hour intervals only).","type":"string"},"ticker":{"description":"The symbol you asked for.","type":"string"}},"required":["as_of","ticker","interval","adjusted","session","count","coverage","bars"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Holdings in this page.","type":"number"},"holdings":{"description":"Constituents, heaviest first, each with its weight.","items":{"type":"string"},"type":"array"},"is_etf":{"description":"Whether the symbol is an ETF, from the instrument type on its ticker record.","type":"boolean"},"ticker":{"description":"The ETF you asked for.","type":"string"},"total":{"description":"Total constituents held, before `limit`.","type":"number"},"truncated":{"description":"`true` when `limit` cut the list short.","type":"boolean"}},"required":["as_of","ticker","is_etf","count","truncated","total","holdings"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Sectors returned.","type":"number"},"is_etf":{"description":"Whether the symbol is an ETF, from the instrument type on its ticker record.","type":"boolean"},"sectors":{"description":"Sector weights, heaviest first, in the vendor's ETF-profile vocabulary.","items":{"type":"string"},"type":"array"},"ticker":{"description":"The ETF you asked for.","type":"string"}},"required":["as_of","ticker","is_etf","count","sectors"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"_meta":{"description":"Per-column `sources` (`bars`, `state`, or `custom` for your own signals; `earnings`/`statements` at 1q) and per-ticker `coverage`, plus `non_trading_days_dropped` / `transitions_only` / `from_defaulted` when they apply.","type":"object"},"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"columns":{"description":"Columns in the response, echoed.","items":{"type":"string"},"type":"array"},"count":{"description":"Rows per ticker in this page.","type":"number"},"interval":{"description":"The grid granularity served.","type":"string"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.","type":"string"},"series":{"description":"Keyed by ticker: an array of flat rows, chronological, each keyed `t` plus the columns you asked for.","type":"object"},"tickers":{"description":"Symbols in the response, echoed.","items":{"type":"string"},"type":"array"}},"required":["as_of","interval","tickers","columns","count","next_cursor","_meta","series"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"_meta":{"description":"With `asof` only: how the read was resolved — interval served and requested, blending, sources, frozen fields. See the as-of read below.","type":"object"},"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"condition":{"description":"The bound you passed, echoed; `null` for boolean and custom signals.","type":"string"},"count":{"description":"Rows in this page.","type":"number"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.","type":"string"},"results":{"description":"Matching tickers with the signal value.","items":{"type":"string"},"type":"array"},"signal":{"description":"The signal you asked for.","type":"string"},"universe":{"description":"The universe you scoped to, echoed; `null` when unscoped.","type":"string"}},"required":["as_of","signal","condition","universe","count","next_cursor","results"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"_meta":{"description":"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.","type":"object"},"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"List form only — how many of `requested` were found.","type":"number"},"data":{"description":"The full ticker row — every signal on the schema page. On the list form, an object keyed by symbol, one full row each.","type":"object"},"not_found":{"description":"List form only — the requested symbols we do not track, in request order. An empty array when every symbol was found.","type":"string"},"requested":{"description":"List form only — the canonical symbols asked for, de-duplicated, in request order.","type":"string"},"ticker":{"description":"The symbol you asked for, normalised. Single form only.","type":"string"}},"required":["as_of","data"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"measured_fields":{"description":"Per-field measured depth where the backfill engine has probed — `field`, the grain it was measured at (`daily`, `hourly`, `minute`), `first_date`, `last_date`, `pct_complete`. Capped at 1500 rows.","items":{"type":"string"},"type":"array"},"minute_tier":{"description":"Whether this ticker is in the minute tier (`included`) and its `rank` within it. `included:false` is NOT \"no intraday data\": the object then carries `on_demand: true`, `first_call_latency` (`\"3-10s\"`) and `window_days` (31) — sub-hour bars for the symbol are fetched from the provider on first request and stored, so the first call is slow and later ones are sub-second.","type":"object"},"name":{"description":"Company or instrument name.","type":"string"},"spans":{"description":"Per resolution — `oldest`, `newest`, `rows`.","type":"object"},"ticker":{"description":"The symbol you asked for.","type":"string"}},"required":["as_of","ticker","name","minute_tier","spans","measured_fields"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"created_at":{"description":"Creation timestamp.","type":"number"},"description":{"description":"Free-form notes; `\"\"` when unset.","type":"string"},"effective_at":{"description":"System universes only: when this membership took effect.","type":"number"},"id":{"description":"The slug — the universe's handle in `?universe=`.","type":"string"},"name":{"description":"Display label.","type":"string"},"next_rebalance_at":{"description":"System universes only: when membership is next recomputed.","type":"number"},"rebalance_method":{"description":"System universes only: how membership is chosen.","type":"string"},"size":{"description":"Member count.","type":"number"},"system":{"description":"`true` for a built-in universe, `false` for one you created.","type":"boolean"},"tickers":{"description":"Members.","items":{"type":"string"},"type":"array"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","description","tickers","size","system","created_at","updated_at"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"cadence":{"description":"How often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.","type":"string"},"channel":{"description":"Where deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.","type":"string"},"created_at":{"description":"Creation timestamp.","type":"number"},"delivery":{"description":"Legacy alias of `channel`, kept aligned for older readers.","type":"string"},"dir":{"description":"Sort direction for that list; `null` means the default (`desc`).","type":"string"},"event_kinds":{"description":"Event-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).","items":{"type":"string"},"type":"array"},"event_q":{"description":"Event-trigger webhooks only: the payload filter, or `null`.","type":"string"},"event_tickers":{"description":"Event-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.","items":{"type":"string"},"type":"array"},"fields":{"description":"Extra signals carried on each fired match row; `null` means the standard set.","type":"string"},"id":{"description":"The webhook id — `wh_…`, the handle for every other call on this record.","type":"string"},"last_error":{"description":"The last evaluation error; `null` on a healthy hook. The answer to \"why is my webhook not firing?\".","type":"string"},"last_eval_error_at":{"description":"When the last evaluation error happened; `null` on a healthy hook.","type":"number"},"last_evaluated_at":{"description":"When it was last evaluated; `null` until the first run.","type":"number"},"last_fired":{"description":"When a delivery last went out; `null` if it never has.","type":"number"},"last_match_set":{"description":"Tickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.","items":{"type":"string"},"type":"array"},"last_predicate_value":{"description":"The trigger's value at the last evaluation; `null` until it has run.","type":"string"},"name":{"description":"Your label for the subscription.","type":"string"},"next_eval_at":{"description":"When the evaluator will next consider this subscription.","type":"number"},"order":{"description":"Sort signal for the payload row list; `null` means the evaluator default (`market_cap`).","type":"string"},"q":{"description":"The stored predicate. Custom signals appear expanded: the SQL is frozen at creation.","type":"string"},"rule_id":{"description":"Legacy link to a v1 alert rule; `null` on everything created through v2.","type":"string"},"source":{"description":"Which API version created the record; `v2` for anything you create today.","type":"string"},"status":{"description":"`active` or `disabled`. Auto-disable follows repeated delivery failure.","type":"string"},"subscription_origin":{"description":"Which door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.","type":"object"},"target_url":{"description":"Your HTTPS endpoint; `null` on every channel except `webhook`.","type":"string"},"trigger_kind":{"description":"Event-trigger webhooks only: `event`.","type":"string"},"universe_id":{"description":"Universe the trigger is scoped to, or `null` for the whole market.","type":"string"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","q","rule_id","fields","order","dir","universe_id","cadence","channel","target_url","delivery","status","source","subscription_origin","last_predicate_value","created_at","updated_at","last_fired","last_match_set","next_eval_at","last_evaluated_at"],"type":"object"}⟨345 unchanged words⟩ only when named here.","enum":["earnings","dividend","split","insider","analyst","newsearnings","signal","news"],"type":"string"},"limit": ⟨303 unchanged words⟩
before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Rows in this page.","type":"number"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Carries `q_truncated: true` alongside it when an oversized `q` could not ride the token — resend `q` on later pages.","type":"string"},"query":{"description":"Your filters, echoed exactly as you sent them — `q`, `select`, `group_by` and `having` come back in your spelling, not the SQL they compile to — including `join` and its grain when you passed `join=state`.","type":"object"},"results":{"description":"One row per event (`ticker`, `ts`, `kind`, `payload`), or rollup rows plus `truncated: true` when an aggregate exceeds `limit`.","items":{"type":"string"},"type":"array"},"truncated":{"description":"Aggregate mode only (`group_by`): `true` when the rollup stopped at its row cap. Aggregate responses are unpaged, so `next_cursor` is absent there.","type":"boolean"}},"required":["as_of","query","count","results"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Rows in this page — the canonical count, equal to `count_builtin` + `count_custom`.","type":"number"},"count_builtin":{"description":"Built-in signals in the catalog.","type":"number"},"count_custom":{"description":"Your custom signals.","type":"number"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.","type":"string"},"signals":{"description":"The catalog, your custom signals first, then built-ins. Built-ins carry `kind: builtin` plus their taxonomy membership — `category`/`category_label`/`group`/`group_label` (slugs are stable, switch on those; labels are display strings) — yours carry `kind: custom` with the `expr`.","items":{"type":"string"},"type":"array"},"taxonomy":{"description":"Absent when the page holds no built-ins (`kind=custom`). The signal taxonomy tree, once per response: `groups[]` in derivation-ladder order (record → behavior → indicator → company side), each with `slug`, `label`, `derivation`, `description`, and its `categories[]` (`slug`, `label`, `description`). Definitions live here and only here — rows carry pointers, never the descriptions. Omitted on `kind=custom`.","type":"object"}},"required":["as_of","count","count_builtin","count_custom","next_cursor","signals"],"type":"object"}⟨201 unchanged words⟩ over 16 chars) is a 400.","enum":["NASDAQ","NYSE","NYSE Arca","Cboe BZX","NYSE American","OTC Link"],"type":"string"},"limit":{"default" ⟨64 unchanged words⟩
before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Rows in this page.","type":"number"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page.","type":"string"},"results":{"description":"One identity row per symbol — the thirteen signals named above, nothing else. `active: false` rows carry `delisted_utc`; they are still addressable on the state route with `asof`.","items":{"type":"string"},"type":"array"}},"required":["as_of","count","next_cursor","results"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Rows in this page.","type":"number"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.","type":"string"},"universes":{"description":"The universes in scope. Every row carries `system: true|false`.","items":{"type":"string"},"type":"array"}},"required":["as_of","count","next_cursor","universes"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Rows in this page.","type":"number"},"deliveries":{"description":"Attempts, newest first: status, attempt, response code, error, and `body_string` — the exact JSON POSTed.","items":{"type":"string"},"type":"array"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.","type":"string"}},"required":["as_of","count","next_cursor","deliveries"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Rows in this page.","type":"number"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.","type":"string"},"webhooks":{"description":"Your subscriptions, newest first, each with its `subscription_origin` and health fields. `signing_secret` is stripped — it is shown only on create.","items":{"type":"string"},"type":"array"}},"required":["as_of","count","next_cursor","webhooks"],"type":"object"}⟨442 unchanged words⟩ Omitted, the scan runs across all ~21,033040 tracked tickers.","type":"string"}}, ⟨4 unchanged words⟩
before
—after
{"additionalProperties":false,"properties":{"_meta":{"description":"`null_coverage` reports, per signal in the predicate, how many in-scope rows are NULL and therefore never evaluated — absence from `results` means \"no value\", not \"did not match\". `scope` additionally describes an explicit `universe`.","type":"object"},"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Rows in this page.","type":"number"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.","type":"string"},"query":{"description":"Your query, echoed — `q`, `order`, `dir`, `limit`, and any scope.","type":"object"},"results":{"description":"One row per match — every signal on the schema page, plus any you named.","items":{"type":"string"},"type":"array"},"truncated":{"description":"Aggregate mode only (`group_by`): `true` when the rollup stopped at its row cap. Aggregate responses are unpaged, so `next_cursor` is absent there.","type":"boolean"}},"required":["as_of","query","count","results"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"count":{"description":"Rows in this page.","type":"number"},"next_cursor":{"description":"Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.","type":"string"},"query":{"description":"Your filters, echoed.","type":"object"},"results":{"description":"Article rows, or rollup rows when you passed `group_by`. Aggregate responses add `truncated: true` when `limit` cut the group list.","items":{"type":"string"},"type":"array"},"truncated":{"description":"Aggregate mode only (`group_by`): `true` when the rollup stopped at its row cap.","type":"boolean"}},"required":["as_of","query","count","next_cursor","results"],"type":"object"}⟨108 unchanged words⟩ array or comma list.","enum":["earnings","dividend","split","insider","analyst","earnings"],"type":"string"},"name": ⟨120 unchanged words⟩
before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"cadence":{"description":"How often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.","type":"string"},"channel":{"description":"Where deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.","type":"string"},"channel_config":{"description":"Returned on create only: the channel-specific delivery settings as stored (e.g. the Discord URL, the device id).","type":"object"},"created_at":{"description":"Creation timestamp.","type":"number"},"delivery":{"description":"Legacy alias of `channel`, kept aligned for older readers.","type":"string"},"dir":{"description":"Sort direction for that list; `null` means the default (`desc`).","type":"string"},"event_kinds":{"description":"Event-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).","items":{"type":"string"},"type":"array"},"event_q":{"description":"Event-trigger webhooks only: the payload filter, or `null`.","type":"string"},"event_tickers":{"description":"Event-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.","items":{"type":"string"},"type":"array"},"fields":{"description":"Extra signals carried on each fired match row; `null` means the standard set.","type":"string"},"id":{"description":"The webhook id — `wh_…`, the handle for every other call on this record.","type":"string"},"last_error":{"description":"The last evaluation error; `null` on a healthy hook. The answer to \"why is my webhook not firing?\".","type":"string"},"last_eval_error_at":{"description":"When the last evaluation error happened; `null` on a healthy hook.","type":"number"},"last_evaluated_at":{"description":"When it was last evaluated; `null` until the first run.","type":"number"},"last_fired":{"description":"When a delivery last went out; `null` if it never has.","type":"number"},"last_match_set":{"description":"Tickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.","items":{"type":"string"},"type":"array"},"last_predicate_value":{"description":"The trigger's value at the last evaluation; `null` until it has run.","type":"string"},"name":{"description":"Your label for the subscription.","type":"string"},"next_eval_at":{"description":"When the evaluator will next consider this subscription.","type":"number"},"order":{"description":"Sort signal for the payload row list; `null` means the evaluator default (`market_cap`).","type":"string"},"q":{"description":"The stored predicate. Custom signals appear expanded: the SQL is frozen at creation.","type":"string"},"rule_id":{"description":"Legacy link to a v1 alert rule; `null` on everything created through v2.","type":"string"},"signing_secret":{"description":"Returned on create only — shown once, never again. HMAC key for verifying the `X-Tickerbot-Signature` header on deliveries.","type":"string"},"source":{"description":"Which API version created the record; `v2` for anything you create today.","type":"string"},"status":{"description":"`active` or `disabled`. Auto-disable follows repeated delivery failure.","type":"string"},"subscription_origin":{"description":"Which door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.","type":"object"},"target_url":{"description":"Your HTTPS endpoint; `null` on every channel except `webhook`.","type":"string"},"test_url":{"description":"Returned on create only: the `POST /v2/webhooks/{id}/test` URL for this record.","type":"string"},"trigger_kind":{"description":"Event-trigger webhooks only: `event`.","type":"string"},"universe_id":{"description":"Universe the trigger is scoped to, or `null` for the whole market.","type":"string"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","q","rule_id","fields","order","dir","universe_id","cadence","channel","target_url","delivery","status","source","subscription_origin","last_predicate_value","created_at","updated_at","last_fired","last_match_set","next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"cadence":{"description":"How often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.","type":"string"},"channel":{"description":"Where deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.","type":"string"},"channel_config":{"description":"Returned on create only: the channel-specific delivery settings as stored (e.g. the Discord URL, the device id).","type":"object"},"created_at":{"description":"Creation timestamp.","type":"number"},"delivery":{"description":"Legacy alias of `channel`, kept aligned for older readers.","type":"string"},"dir":{"description":"Sort direction for that list; `null` means the default (`desc`).","type":"string"},"event_kinds":{"description":"Event-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).","items":{"type":"string"},"type":"array"},"event_q":{"description":"Event-trigger webhooks only: the payload filter, or `null`.","type":"string"},"event_tickers":{"description":"Event-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.","items":{"type":"string"},"type":"array"},"fields":{"description":"Extra signals carried on each fired match row; `null` means the standard set.","type":"string"},"id":{"description":"The webhook id — `wh_…`, the handle for every other call on this record.","type":"string"},"last_error":{"description":"The last evaluation error; `null` on a healthy hook. The answer to \"why is my webhook not firing?\".","type":"string"},"last_eval_error_at":{"description":"When the last evaluation error happened; `null` on a healthy hook.","type":"number"},"last_evaluated_at":{"description":"When it was last evaluated; `null` until the first run.","type":"number"},"last_fired":{"description":"When a delivery last went out; `null` if it never has.","type":"number"},"last_match_set":{"description":"Tickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.","items":{"type":"string"},"type":"array"},"last_predicate_value":{"description":"The trigger's value at the last evaluation; `null` until it has run.","type":"string"},"name":{"description":"Your label for the subscription.","type":"string"},"next_eval_at":{"description":"When the evaluator will next consider this subscription.","type":"number"},"order":{"description":"Sort signal for the payload row list; `null` means the evaluator default (`market_cap`).","type":"string"},"q":{"description":"The stored predicate. Custom signals appear expanded: the SQL is frozen at creation.","type":"string"},"rule_id":{"description":"Legacy link to a v1 alert rule; `null` on everything created through v2.","type":"string"},"signing_secret":{"description":"Returned on create only — shown once, never again. HMAC key for verifying the `X-Tickerbot-Signature` header on deliveries.","type":"string"},"source":{"description":"Which API version created the record; `v2` for anything you create today.","type":"string"},"status":{"description":"`active` or `disabled`. Auto-disable follows repeated delivery failure.","type":"string"},"subscription_origin":{"description":"Which door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.","type":"object"},"target_url":{"description":"Your HTTPS endpoint; `null` on every channel except `webhook`.","type":"string"},"test_url":{"description":"Returned on create only: the `POST /v2/webhooks/{id}/test` URL for this record.","type":"string"},"trigger_kind":{"description":"Event-trigger webhooks only: `event`.","type":"string"},"universe_id":{"description":"Universe the trigger is scoped to, or `null` for the whole market.","type":"string"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","q","rule_id","fields","order","dir","universe_id","cadence","channel","target_url","delivery","status","source","subscription_origin","last_predicate_value","created_at","updated_at","last_fired","last_match_set","next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"cadence":{"description":"How often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.","type":"string"},"channel":{"description":"Where deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.","type":"string"},"channel_config":{"description":"Returned on create only: the channel-specific delivery settings as stored (e.g. the Discord URL, the device id).","type":"object"},"created_at":{"description":"Creation timestamp.","type":"number"},"delivery":{"description":"Legacy alias of `channel`, kept aligned for older readers.","type":"string"},"dir":{"description":"Sort direction for that list; `null` means the default (`desc`).","type":"string"},"event_kinds":{"description":"Event-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).","items":{"type":"string"},"type":"array"},"event_q":{"description":"Event-trigger webhooks only: the payload filter, or `null`.","type":"string"},"event_tickers":{"description":"Event-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.","items":{"type":"string"},"type":"array"},"fields":{"description":"Extra signals carried on each fired match row; `null` means the standard set.","type":"string"},"id":{"description":"The webhook id — `wh_…`, the handle for every other call on this record.","type":"string"},"last_error":{"description":"The last evaluation error; `null` on a healthy hook. The answer to \"why is my webhook not firing?\".","type":"string"},"last_eval_error_at":{"description":"When the last evaluation error happened; `null` on a healthy hook.","type":"number"},"last_evaluated_at":{"description":"When it was last evaluated; `null` until the first run.","type":"number"},"last_fired":{"description":"When a delivery last went out; `null` if it never has.","type":"number"},"last_match_set":{"description":"Tickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.","items":{"type":"string"},"type":"array"},"last_predicate_value":{"description":"The trigger's value at the last evaluation; `null` until it has run.","type":"string"},"name":{"description":"Your label for the subscription.","type":"string"},"next_eval_at":{"description":"When the evaluator will next consider this subscription.","type":"number"},"order":{"description":"Sort signal for the payload row list; `null` means the evaluator default (`market_cap`).","type":"string"},"q":{"description":"The stored predicate. Custom signals appear expanded: the SQL is frozen at creation.","type":"string"},"rule_id":{"description":"Legacy link to a v1 alert rule; `null` on everything created through v2.","type":"string"},"signing_secret":{"description":"Returned on create only — shown once, never again. HMAC key for verifying the `X-Tickerbot-Signature` header on deliveries.","type":"string"},"source":{"description":"Which API version created the record; `v2` for anything you create today.","type":"string"},"status":{"description":"`active` or `disabled`. Auto-disable follows repeated delivery failure.","type":"string"},"subscription_origin":{"description":"Which door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.","type":"object"},"target_url":{"description":"Your HTTPS endpoint; `null` on every channel except `webhook`.","type":"string"},"test_url":{"description":"Returned on create only: the `POST /v2/webhooks/{id}/test` URL for this record.","type":"string"},"trigger_kind":{"description":"Event-trigger webhooks only: `event`.","type":"string"},"universe_id":{"description":"Universe the trigger is scoped to, or `null` for the whole market.","type":"string"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","q","rule_id","fields","order","dir","universe_id","cadence","channel","target_url","delivery","status","source","subscription_origin","last_predicate_value","created_at","updated_at","last_fired","last_match_set","next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"cadence":{"description":"How often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.","type":"string"},"channel":{"description":"Where deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.","type":"string"},"channel_config":{"description":"Returned on create only: the channel-specific delivery settings as stored (e.g. the Discord URL, the device id).","type":"object"},"created_at":{"description":"Creation timestamp.","type":"number"},"delivery":{"description":"Legacy alias of `channel`, kept aligned for older readers.","type":"string"},"dir":{"description":"Sort direction for that list; `null` means the default (`desc`).","type":"string"},"event_kinds":{"description":"Event-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).","items":{"type":"string"},"type":"array"},"event_q":{"description":"Event-trigger webhooks only: the payload filter, or `null`.","type":"string"},"event_tickers":{"description":"Event-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.","items":{"type":"string"},"type":"array"},"fields":{"description":"Extra signals carried on each fired match row; `null` means the standard set.","type":"string"},"id":{"description":"The webhook id — `wh_…`, the handle for every other call on this record.","type":"string"},"last_error":{"description":"The last evaluation error; `null` on a healthy hook. The answer to \"why is my webhook not firing?\".","type":"string"},"last_eval_error_at":{"description":"When the last evaluation error happened; `null` on a healthy hook.","type":"number"},"last_evaluated_at":{"description":"When it was last evaluated; `null` until the first run.","type":"number"},"last_fired":{"description":"When a delivery last went out; `null` if it never has.","type":"number"},"last_match_set":{"description":"Tickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.","items":{"type":"string"},"type":"array"},"last_predicate_value":{"description":"The trigger's value at the last evaluation; `null` until it has run.","type":"string"},"name":{"description":"Your label for the subscription.","type":"string"},"next_eval_at":{"description":"When the evaluator will next consider this subscription.","type":"number"},"order":{"description":"Sort signal for the payload row list; `null` means the evaluator default (`market_cap`).","type":"string"},"q":{"description":"The stored predicate. Custom signals appear expanded: the SQL is frozen at creation.","type":"string"},"rule_id":{"description":"Legacy link to a v1 alert rule; `null` on everything created through v2.","type":"string"},"signing_secret":{"description":"Returned on create only — shown once, never again. HMAC key for verifying the `X-Tickerbot-Signature` header on deliveries.","type":"string"},"source":{"description":"Which API version created the record; `v2` for anything you create today.","type":"string"},"status":{"description":"`active` or `disabled`. Auto-disable follows repeated delivery failure.","type":"string"},"subscription_origin":{"description":"Which door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.","type":"object"},"target_url":{"description":"Your HTTPS endpoint; `null` on every channel except `webhook`.","type":"string"},"test_url":{"description":"Returned on create only: the `POST /v2/webhooks/{id}/test` URL for this record.","type":"string"},"trigger_kind":{"description":"Event-trigger webhooks only: `event`.","type":"string"},"universe_id":{"description":"Universe the trigger is scoped to, or `null` for the whole market.","type":"string"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","q","rule_id","fields","order","dir","universe_id","cadence","channel","target_url","delivery","status","source","subscription_origin","last_predicate_value","created_at","updated_at","last_fired","last_match_set","next_eval_at","last_evaluated_at","channel_config","signing_secret","test_url"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"created_at":{"description":"When the ping was sent (ISO 8601).","type":"string"},"delivered":{"description":"Whether your endpoint accepted the ping (2xx within the timeout).","type":"boolean"},"elapsed_ms":{"description":"Round-trip time of the ping.","type":"number"},"error":{"description":"Why delivery failed, in words; `null` on success.","type":"string"},"http_status":{"description":"The status your endpoint returned; `null` when it could not be reached.","type":"number"},"id":{"description":"Delivery id of the test — `dl_…`, the same shape as a real delivery on the deliveries route.","type":"string"},"status":{"description":"The delivery record's status: `delivered` or `permanent_failure` (a test is never retried).","type":"string"},"test":{"description":"`true` — this delivery was a synthetic ping, not a trigger firing.","type":"boolean"},"webhook_id":{"description":"The webhook that was tested.","type":"string"}},"required":["as_of","id","webhook_id","test","delivered","http_status","elapsed_ms","error","status","created_at"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"signal":{"description":"The stored signal: `name`, `kind` (`custom`), `description`, `expr` (your predicate as stored), `created_at`, `updated_at`.","type":"object"}},"required":["as_of","signal"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"created_at":{"description":"Creation timestamp.","type":"number"},"description":{"description":"Free-form notes; `\"\"` when unset.","type":"string"},"effective_at":{"description":"System universes only; absent on yours.","type":"number"},"id":{"description":"The slug — the universe's handle in `?universe=`.","type":"string"},"name":{"description":"Display label.","type":"string"},"next_rebalance_at":{"description":"System universes only; absent on yours.","type":"number"},"rebalance_method":{"description":"System universes only; absent on yours.","type":"string"},"size":{"description":"Member count.","type":"number"},"system":{"description":"`false` — this is your universe.","type":"boolean"},"tickers":{"description":"Members, after this call.","items":{"type":"string"},"type":"array"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","description","tickers","size","system","created_at","updated_at"],"type":"object"}before
—after
{"additionalProperties":false,"properties":{"as_of":{"description":"Server time this response was assembled (ISO 8601).","type":"string"},"cadence":{"description":"How often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.","type":"string"},"channel":{"description":"Where deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.","type":"string"},"created_at":{"description":"Creation timestamp.","type":"number"},"delivery":{"description":"Legacy alias of `channel`, kept aligned for older readers.","type":"string"},"dir":{"description":"Sort direction for that list; `null` means the default (`desc`).","type":"string"},"event_kinds":{"description":"Event-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).","items":{"type":"string"},"type":"array"},"event_q":{"description":"Event-trigger webhooks only: the payload filter, or `null`.","type":"string"},"event_tickers":{"description":"Event-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.","items":{"type":"string"},"type":"array"},"fields":{"description":"Extra signals carried on each fired match row; `null` means the standard set.","type":"string"},"id":{"description":"The webhook id — `wh_…`, the handle for every other call on this record.","type":"string"},"last_error":{"description":"The last evaluation error; `null` on a healthy hook. The answer to \"why is my webhook not firing?\".","type":"string"},"last_eval_error_at":{"description":"When the last evaluation error happened; `null` on a healthy hook.","type":"number"},"last_evaluated_at":{"description":"When it was last evaluated; `null` until the first run.","type":"number"},"last_fired":{"description":"When a delivery last went out; `null` if it never has.","type":"number"},"last_match_set":{"description":"Tickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.","items":{"type":"string"},"type":"array"},"last_predicate_value":{"description":"The trigger's value at the last evaluation; `null` until it has run.","type":"string"},"name":{"description":"Your label for the subscription.","type":"string"},"next_eval_at":{"description":"When the evaluator will next consider this subscription.","type":"number"},"order":{"description":"Sort signal for the payload row list; `null` means the evaluator default (`market_cap`).","type":"string"},"q":{"description":"The stored predicate. Custom signals appear expanded: the SQL is frozen at creation.","type":"string"},"rule_id":{"description":"Legacy link to a v1 alert rule; `null` on everything created through v2.","type":"string"},"source":{"description":"Which API version created the record; `v2` for anything you create today.","type":"string"},"status":{"description":"`active` or `disabled`. Auto-disable follows repeated delivery failure.","type":"string"},"subscription_origin":{"description":"Which door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.","type":"object"},"target_url":{"description":"Your HTTPS endpoint; `null` on every channel except `webhook`.","type":"string"},"trigger_kind":{"description":"Event-trigger webhooks only: `event`.","type":"string"},"universe_id":{"description":"Universe the trigger is scoped to, or `null` for the whole market.","type":"string"},"updated_at":{"description":"Last modification timestamp.","type":"number"}},"required":["as_of","id","name","q","rule_id","fields","order","dir","universe_id","cadence","channel","target_url","delivery","status","source","subscription_origin","last_predicate_value","created_at","updated_at","last_fired","last_match_set","next_eval_at","last_evaluated_at"],"type":"object"}{"properties":{"description":{"description":"OptionalFree-formhumannotes.description.Max 500 chars. Absent or empty comes back as `\"\"` rather than null.","type":"string"},"expr":{"description":"Boolean SQLWHEREpredicate.expression.MaySamereference built-in signals and other custom signals you own. Must evaluate to true/false. Max 4000 chars. Stricter grammarasthan scan`q`.`q`: comparisons, `AND`/`OR`/`NOT`, `IN`, `BETWEEN`, `IS [NOT] NULL`, arithmetic, and the functions `abs`/`coalesce`/`round`/`least`/`greatest` only — no `LIKE`/`ILIKE`, no `CASE`, no `::` casts, no other functions. An expression that scans fine can still be rejected here with `compile_failed`. What you send is what you read back: responses echo your expression VERBATIM, not its expansion. A signal referencing another custom of yours returns the reference as you typed it — the inlined SQL exists only internally, and is what a subscribe endpoint freezes into a webhook.","type":"string"},"name":{"description":"Snake_caseSlugidentifier.— `^[a-z][a-z0-9_]{0,63}$`. Must not collide with any built-in signal name, and 15 names are reserved outright: `columns`, plus the `/v2/series` OHLCV aliases `open`/`high`/`low`/`close`/`volume`/`vwap`/`trades` and `o`/`h`/`l`/`c`/`v`/`vw`/`n` (those resolve to bars before custom lookup). This is the signal's API handle: it's what you reference in `q` and in the CRUD path.","type":"string"}},"required": ⟨4 unchanged words⟩
Create anew universe (namedset oftickertickers)listforownedscopingbyfutureyourscans.account.
{"properties":{"description":{"description":"OptionalFree-formfree-formnotes,notes.up to 500 characters. Stored as `\"\"` when omitted.","type":"string"},"id":{"description":"Optional slug(lowercase—lettersbecomes the universe's permanent handle everywhere (`?universe=`,digitssubscribe `universe`,underscoreCRUD path).Auto-generatedPatternfrom`^[a-z][a-z0-9_]{0,62}$`name—ifstartsomitted.with a lowercase letter, then lowercase letters/digits/underscore, 63 chars max; the value is trimmed and lowercased before validation. `top_10` and `top_100` are reserved for system universes and rejected with 400. Must be unique withintheyour account. Generated (`u_…`) if omitted.","type":"string"},"name":{"description":"Human-readablename.label, up to 80 characters. Display-only — never used to reference the universe.","type":"string"},"tickers":{"description":"ListTickerofsymbols,tickerupsymbols.to 10,000. Validated against the active universe. `[]` is accepted — a shell universe you can fill later via PATCH.","items":{"type":"string"}, ⟨7 unchanged words⟩
The canonical webhookCanonical create— POST /v2/webhooks with an explicit `trigger` object:{ type: "scan" | "ticker" | "signal" | "event", … } plus delivery fields. The subscribe tools above are flat sugar over exactly this; use this formawhenwebhookcomposingisthea triggerprogrammatically or whenplus asugar door doesn't fit.delivery. Trigger shapes: scan {type:"scan", ⟨19 unchanged words⟩ "event", kinds, tickers?, universe?, event_q?}. The subscribe tools are flat sugar over exactly this. Webhooks need a paid plan (Free has no webhook slots).
{"properties":{"cadence":{"default":"realtime","description":"Evaluationcadence.cadenceDefault—realtime.a(`1m`useracceptedpreferenceas—aneverdeprecatedgated.aliasEventoftriggersrealtime.deliver on ingest — only `realtime` is accepted on them (400 otherwise).","enum":["realtime","hourly"," ⟨3 unchanged words⟩ },"channel":{"description":"Delivery channel.Inferred from the URL you passSeeifDeliveryomitted.channels.","enum":["webhook","discord"," ⟨3 unchanged words⟩ :"string"},"columns":{"description":"Comma list of extraExtra columnsto includeechoedwithineachfireddeliveredpayloads' match rows (`fields` accepted as an alias). Not accepted on `event` triggers (400) — event deliveries carry the event payload, not state rows.","type":"string"},"device_id":{"description":"Registered device idfrom(channelthe`mobile_push`,mobileseeapp/v2/devices).","type":"string"},"dir":{"default":"desc","description":"Sort(channeldirectionmobile_pushfor `order`. Not accepted on `event` triggers (400).","enum":["asc","desc"],"type":"string"},"discord_url":{"description":"Discordincoming-webhookwebhook URL (channeldiscord`discord`).","type":"string"},"name":{"description":"Displayname.name, max 80 characters. Defaults to an auto-generated one from the trigger.","type":"string"},"order":{"default":"market_cap","description":"Signal the fired payload's match lists are sorted by before the 100-row cap is applied — so a truncated list is the deterministic top 100, not an arbitrary sample. Same contract as `POST /v2/scan`. Not accepted on `event` triggers (they deliver one event at a time).","type":"string"},"target_url":{"description":"HTTPS delivery URL (the `webhook` channel)., max 1024 characters. Omit forin-app.in-app delivery, or use `channel` + `discord_url`/`device_id` for other channels.","type":"string"},"trigger":{"description":"What fires thewebhookwebhook. A discriminated object — `trigger.type` picks the shape, and the fields below belong inside it. Each shape is also available as a flat-params shortcut: `POST /v2/scan/subscribe`, `/v2/tickers/{t}/subscribe`,type`/v2/signals/{s}/subscribe`, `/v2/events/subscribe`.","properties":{"condition":{"description":"signal:\required for numeric signals — a single bound like `>70`; sending one with a boolean or custom signal returns 400 (it does not apply). ticker: accepted as the original alias of `trigger.q`."scan\,"type":"string"},"event_q":{"description":"event:|optional\event-CONTENT filter in the `/v2/events` grammar over `(ticker, ts, kind, payload)` — e.g. `payload->>'firm' = 'Goldman Sachs'`. Composes with `trigger.q`."ticker\,"type":"string"},"kinds":{"description":"event:|required\— event kinds to fire on, array or comma list (e.g. `split,analyst`)."signal\,"type":"string"},"q":{"description":"scan:|required\— the SQL WHERE any ticker must match to fire. ticker: required — WHERE fragment evaluated for that ticker (auto-scoped; don't add `ticker = …` yourself; `trigger.condition` accepted as an alias). event: optional row-STATE filter on the event's ticker at fire time (`market_cap > 1e10`)."event\,"type":"string"},"signal":{"description":"signal:…required — a built-in signal name (e.g. `rsi_14`) or one of your custom signals (custom SQL is expanded and frozen at creation).","type":"string"},"ticker":{"description":"ticker: required —seethe symbol to watch (e.g. `NVDA`). signal: optional — restrict thetoolsignal to one symbol (omit to watch the whole universe).","type":"string"},"tickers":{"description":"event:foroptionaleachsymbolshape.list, max 50 (e.g. `AAPL,NVDA`). Mutually exclusive with `trigger.universe`.","type":"string"},"type":{"description":"Which trigger shape the rest of the object uses.","enum":["scan","ticker","signal","event"],"type":"string"},"universe":{"description":"scan / signal / event: optional universe slug (`top_10`, `top_100`, or one of yours) scoping which tickers can fire. Mutually exclusive with `trigger.tickers` on event.","type":"string"}},"required":["type"],"type":"object"}},"required":[ ⟨3 unchanged words⟩
Delete one ofthe caller'syour custom signals.Cascade-safeRefused by default:refused with 409if anothercustom signal references it (the error lists theofreferencingyour signals).Pass `force: true` to delete anyway — existingreferenceswill break on next recompile. Available on every plan.it.
{"properties":{"force":{"default":false,"description":"Whentrue`true`, skip the reference check anddeletedelete.anyway.ReferencesDefaultwillfalse.break on next recompile.","type":"boolean"},"namesignal":{"description":"Custom signalslug.slug (the signal name). A built-in name answers 404 — built-ins are read-only.","type":"string"}},"required":["namesignal"],"type":"object"}
DeletePermanently delete one ofthe caller'syour universes.System universes (`top_10`/`top_100`) cannot be deleted.Webhooks that reference the deleted universewillfail on their next eval,so— clean those up first.
{"properties":{"force":{"default":false,"description":"A universe still referenced by live webhooks refuses to delete with `409 universe_referenced`. Pass `force=true` to delete anyway — those webhooks will match nothing until re-pointed or deleted.","type":"boolean"},"id":{"description":"Universe slug.","type ⟨5 unchanged words⟩
Delete a webhook subscriptionby id. Use after listing webhooks when the,userandwantsitstodeliveryremovehistoryanwithalert.it.
{"properties":{"id":{"description":"Webhookid (looks like `wh_…`).id.","type":"string"}},"required": ⟨3 unchanged words⟩
Re-enable a disabled webhook—andflipsstart itback to `active` and clearsclean.itsClears match-state, so the next eval treats every currently-matching ticker as new.Use after fixing whatever caused auto-disable. No-op on an already-active webhook.
THE series primitive:Anycross-ticker,signalsmulti-signalfortimeanyseriestickers on onealignedsharedgrid.timePickgrid — up to25 signals (price, OHLCV, indicators like rsi_14, booleans, custom signals)50andtickersupbyto2550columnstickers;pergetcall.oneOne flat row per ticker per interval step({ticker,t, price, rsi_14, …}),cursor-paged backward.`transitions_only=true``transitions_only: true` with boolean signals returns only the rows where a booleanCHANGED — "every golden_cross flip this year" in one call. All-time on every plan. Replaces looping asof snapshots per date, and replaces the sunset per-ticker history routes.flipped.
{"properties":{"columnsasof":{"description":"CommaPoint-in-timelistread:ofONEcolumnsrow(maxper25ticker — the state at that instant — rather than a range. `YYYY-MM-DD` or a full ISO timestamp, the same meaning `asof` carries on `/v2/tickers`, `/v2/scan` and `/v2/signals`. Cannot be combined with `from`/`to` or `cursor` (400).`fields`—isa point and apermanentwindowalias.areDefaultscontradictory,to
Get theThe fullcurrent row for oneticker—row, every signal on the schema(pricepage,change,forindicatorsonelikesymbolrsi_14,oreveryabooleancommalikelistabove_sma_50of up to 50. Right now,fundamentalsorlikewithpe_ratio).`asof`, as of any past date. Pass acomma-separatedcomma list of up to 50 symbols(AAPL,MSFT,NVDA)for a batch:the response carries(`data` keyed by symbol plus`not_found`. Pass `asof` (YYYY-MM-DD or ISO`not_found`).timestampCryptolikeis2026-07-20T15:30:00Z)theforX-prefixedthepairrow(sX:BTCUSD)as of that past date—date-only gives thebarecloseBTC/ETHofarethatUS-listedday.ETFs.
{"properties":{"asof":{"description":"OptionalOptional.YYYY-MM-DDTarget moment as `YYYY-MM-DD` (that day's close) or an ISOtimestamp.timestampDate-only(thatreturnsintraday moment) — therowsameatreadcloseasofitthatstoodday;then, unlimited depth. Full contract under As of atimestamppast
Data-coverage report forFor one ticker,—whatwhichweintervalshold andsignalshowexist,farfrombackwhen,—atsowhatandepth.emptyTheresulthonestyisendpoint:neveraskambiguous. Ask this beforeassumingtreating a gap inbars/series is a databarsoutageorvs.seriesgenuinely-never-coveredas(e.g.anfundamentalsoutage.on`minute_tier.included:non-equities).false`NOTEwithminute_tier.included`on_demand:falsetrue` isNOTnot a gap:it comes with on_demand:true— sub-hour barsfor that symbol are fetchedfetch from the provider on firstrequest (~3-10s, up to window_days per call) and served sub-second after.request.
{"properties":{"ticker":{"description":"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.","type":"string"}},"required": ⟨3 unchanged words⟩
GetReturnsonethe universebydoc. Use `top_10`/`top_100` to fetch a system universe; any other slug,includingmustitsbetickeronelist.your account owns.
Fetch one webhook subscription by idThe(current state,match-set, schedule). Account-scoped: any key on the account can read anyoftheoneaccount'swebhookwebhooks.subscription.
{"properties":{"id":{"description":"Webhook id returned by a subscribe endpoint (looks`POSTlike/v2/tickers/{T}/subscribe`,`wh_…`etc.).","type":"string"}},"required ⟨3 unchanged words⟩
THE events primitive — oneOne timelineoveracross everyeventticker:logearnings,cross-ticker:dividends, splits, insidertransactionsfilings,andanalyst actions("all splits this month","every analyst action in my universe this week", "AAPL's full corporate history" via `ticker`),plustwoopt-inkinds that join only when named: `signal` (booleansignal firings)and`news`. Rows are { ticker,news.ts,Requireskind,atpayloadleast},onenewestbound:first.aAnalysttickerpayloadsscope (history to 2012ticker/tickers/universe)carry firm/analyst/action/rating/price_target; filter them with `firm=`/`action=` (structured,case-insensitive —a`q` payload matchtimeiswindowcase-SENSITIVE(from/to)— actions: upgrades,downgrades, initiates_coverage_on, maintains, reiterates, assumes, reinstates, suspends,orterminates_coverage_on.firm/actionUse— `q`for other payload conditions: italonespeaksisthenotSQLagrammarbound.over`firm`/`action`exactlymatch(ticker,case-insensitively;ts,akind,`q` payloadjsonb); `group_by`/`select`/`having` roll the stream upmatch(aggregatesisreturncase-sensitive.`truncated`join:true` instead of paginating); `join=state`state` attaches theticker'sticker state as of each event.Requires at least one bound: a ticker scope (ticker/tickers/universe), a time window (from/to), or firm/action — q alone is not a bound.
{"properties":{"action":{"description":"kind=analystAnalyst-onlyonly.structuredExactfilterrating-action—filter.requires `kind=analyst` alone. Same `action` vocabulary as Analyst actions.","enum":["upgrades","downgrades"," ⟨9 unchanged words⟩ "cursor":{"description":"Opaque cursor fromathepriorprevious response — carries the original filters,pass(andit`q`alonewhen(longshort),qsovaluespass
TheEvery symbolcatalog: an identity walk over every trackedwesymboltrack,(activeandor delisted),alphabetical with `cursor` pagination. Rowsascarryone identityonly — ticker, name, asset_class, asset_type, exchange, exchange_mic, currency_name, country, cik, composite_figi, list_date, delisted_utc, active — never price or signals. Filters: search (exactrowtickereach.→Use `/v2/tickers/{tickerprefix → name match), asset_class, asset_type, exchange.}`Forfor the fullSTATE of named symbols use tickerbot_get_ticker with a comma list; for a universe's members use tickerbot_scan with universe.row.
⟨9 unchanged words⟩ `rates`, `crypto`, `fx`, or a comma-separatedlist.list (the live classes today; validated for shape, not against a fixed list, so a well-formed class we don't track simply matches nothing — same contract as scan). Omit for every class.DistinctThis is the class of INSTRUMENT, distinct fromasset_type`asset_type` below (the instrument type within equities). Every row carries its `asset_class`, so a non-equity row identifies itself.","type":"string"},"asset_type":{"description":"Filter byINSTRUMENTinstrumentTYPEtypewithinWITHIN equities:— the stored `asset_type` value (CS`CS`,ETF`ETF`,ADRC
ListEveryuniversesuniverse—you can reference: yoursavedownonesnamedand/orticker lists and the built-insystemones. `owner: system` lists the built-in universes (top_10, top_100). Filter with;`owner``all`(likeliststheboth.signalsUsecatalog'sa`kind`):slug`me`as(default,`universe`youronown)scan,`system` (built-ins)signal,or `all` (both). Each row carriesand`system:subscribetrue|false`.tools.
{"properties":{"cursor":{"description":"Opaquecursor.cursor from the previous response.","type":"string"},"limit":{"default":50,"description":"Page size (applies to yourown; system universes are a small fixed set returned in full on the first pageown). Max 100.","type":"integer"},"owner":{"default":"me","description":"Which universes tolist.list: `me` (your own), `system` (built-ins), or `all` (both).","enum":["me","system"," ⟨5 unchanged words⟩
List recentRecent deliveries(pings and fires)foraone webhook,newest-first—for diagnosing failures. Returns metadata only (status, attempt,whatresponsewascodesent,error); the POST bodyandiswhatnotcamestored.back.
⟨17 unchanged words⟩ seconds, epoch milliseconds (13+ digits), or an ISOdatetime.datetime (90-day`since`retentionisonacceptedeveryasplan.an alias). Delivery history is retained for 90 days; deleting a webhook deletes its delivery history with it.","type":"string"},"id":{ ⟨3 unchanged words⟩ ,"type":"string"},"limit":{"default":50,"description":"Page size. Max 100.Default 50.","type":"integer"},"status":{ ⟨16 unchanged words⟩ at/before this moment — same value grammar as`from`;`from`.aA date-only value means through the end of that UTC day. `from` after `to` is a 400.","type":"string"}},"required": ⟨3 unchanged words⟩
List the caller'sEvery webhooksubscriptions (rules created viasubscriptiontheonsubscribethistools)account,newest-first. Use `status` to filter to active or disablednewestrules.first.
{"properties":{"cursor":{"description":"Opaquecursor.cursor from the previous response.","type":"string"},"limit":{"default":50,"description":"Page size. Max 100.Default 50.","type":"integer"},"status":{"description":"Filter by status: `active` or`disabled`.`disabled` — the only two states a webhook has (`disabled` covers both a user pause and the automatic disable after repeated delivery failures; `consecutive_failures`/`last_error` on each record say which). Omit for all.","enum":["active" ⟨5 unchanged words⟩
RunEvery ticker matching a SQL WHEREclause againstclause.theRightlivenow,tickeroruniversewith(or`asof`, as of any pastdate with `asof` — unlimited depth on every plan). Returns matching tickers sorted by chosen column, ORdate.—Thewith`q``group_by`grammar—isaggregatearollupsflatinsteadSQLofWHERErowsover(breadthsignalstatsnames:"count of tickersAND/OR/NOT,abovecomparisons,theirnumeric200dmaandbystringsector"literals,"mediancustomRSIsignals bysector on 2026-03-03"). The `q` grammar isname.aNoflatJOINWHERE:orcolumnsubqueries.namesWithfrom`group_by` theschema,resultAND/OR/NOT,iscomparisonrollupoperatorsrows,numeric/string literals. No JOIN ornotsubqueries.tickers. Example: `gap_up AND market_cap < 2000000000 AND NOT earnings_this_week`.
{"properties":{"asof":{"description":"OptionalOptional.YYYY-MM-DDTarget moment as `YYYY-MM-DD` (that day's close) or an ISO timestampfor(thataintradayhistoricalmoment)scan.—Unlimitedthedepthsameonreadeveryasplan.it stood then, unlimited depth. Full contract under As of a past date.","type":"string"},"cursorasset_class":{"description":"OpaqueOne
Search the news archive (back to 2015) with aSQLWHERE clause. Available on every plan. Columns on news_article include `time_published`, `title`,query`summary`,over`source`,the`source_domain`,news`category`,archive.`authors`,Article`topics`rows,`tickers`or(array),rollups`overall_sentiment_score`,when`overall_sentiment_label`,you`url`.groupTothem.filterFilter toonea tickerusewith`'NVDA'the=`ticker`ANY(tickers)`param, or in `q` via the auto-unnest alias `tk = 'NVDA'`.Example: `q=tk='NVDA' AND time_published >=`search`NOW()is-full-textINTERVALover'1titleday'`.andSupportssummary.group_byRollups+withhavinggroup_by/havingforreturnaggregation`truncated:(e.g.true`countinstead ofarticles per day).paging.
{"properties":{"cursor":{"description":"Opaquecursor.pagination cursor from a prior response's `next_cursor`.","type":"string"},"dir":{"default":"desc","description":"Sort direction.","enum":["asc","desc"],"type":"string"},"from":{"description":"Earliest `time_published` (inclusive) — strict ISO: `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM[:SS]Z`. (`since` accepted as an alias.)","type":"string"},"group_by":{"description":"Comma-separatedAGGREGATEcolumnsMODE:forcomma-separatedaggregation.groupAliaskeys, 1-6 (max 1000 chars). Switches the response to rollup rows. Use `tk` to roll up per ticker without writing the UNNEST. Name a key with `AS` tonamechoose its JSON key; an un-namedexpressionsexpressionareis named foryou.you rather than returned as `?column?`.
Create anPushevent-triggernewwebhookevents:fireswewhenPOSTNEWyoureventsendpointlandwhen—eventsdividends,ofsplits,theinsiderkindsfilings,youanalystchoseactionsland("everyinsplittheinarchives.myWebhooksuniverse",need"Goldmanadowngradespaidonplanlarge(Freecaps").hasTWOnocomposablewebhookfilters:slots). `q` filters theevent's TICKER STATE (market_cap >ticker1e10);STATE; `event_q` filters the EVENTCONTENTpayload in the /v2/eventsgrammar (payload->>'firm' = 'Goldman Sachs'). Paid plans (webhook slots). Deliveries carry event: "events.fired" with an events array.grammar. Latency=is the ingest cadence:(analyst ≤1h, corporate kinds daily— NOT sub-minute like),statenotwebhooks.sub-minute.
{"properties":{"channel":{"description":"Delivery channel. `slack` is reserved and returns `501`.","enum":["webhook","discord"," ⟨3 unchanged words⟩ :"string"},"device_id":{"description":"RegisteredDevicedevicetoidnotify, fromthe`POSTmobile/v2/devices/register`.appRequired(channelwhenmobile_push).`channel` is `mobile_push`; unknown ids are a 404 `device_not_found`.","type":"string"},"discord_url":{"description":"Discord incoming-webhookURLURL. Required when `channel` is `discord`. Stored as a posting credential: the create response echoes it back under `channel_config`, but every later read (channellist,discordget, deliveries
Register a webhook that fires when matches forPush ascanwhole querychange. Pass `target_url` for an https POST, or `channel:"discord"`+ `discord_url` to postweanPOSTembedyourtoendpointDiscord;everyomittimeforthein-appmatchdeliverysetinchanges.theWebhooksdashboard.need`cadence`aispaidreal-timeplan (1m) by default; throttleFreetohashourlynoorwebhooknyse_open.slots). Useto satisfyfor "alert me when this happens"prompts.requests.
{"properties":{"cadence":{"description":"Evaluation`realtime`cadence.(theDefaultdefault)realtime;ishourly/nyse_openevaluatedthrottle.on every data refresh (`1m`~1×/min);accepted`hourly`asand `nyse_open` throttle to a batch schedule. `1m` is a deprecated aliasofforrealtime.)`realtime`.","enum":["realtime","hourly"," ⟨2 unchanged words⟩ string"},"channel":{"description":"Deliverychannel:channel.
RegisterPushaonewebhooksignal:thatwefiresPOSTwhenyouraendpointsignalwheneverturnsanytrueticker(booleans)startsormatchingitsit.valueWebhookscrossesneed aconditionpaid(numerics).planOptional(Free`ticker`hasrestrictsnotowebhookoneslots).symbol;Omitomit`ticker` to watch the whole universe.Pass `target_url` for an https POST, or `channel:"discord"` + `discord_url` to post to Discord; omit for in-app.
{"properties":{"cadence":{"description":"Evaluation`realtime`cadence.(theDefaultdefault)realtime;ishourly/nyse_openevaluatedthrottle.on every data refresh (`1m`~1×/min);accepted`hourly`asand `nyse_open` throttle to a batch schedule. `1m` is a deprecated aliasofforrealtime.)`realtime`.","enum":["realtime","hourly"," ⟨2 unchanged words⟩ string"},"channel":{"description":"Deliverychannel:channel.
Register a webhook that fires whenPush one ticker:matchesweaPOSTcondition.your`condition`endpointiswheneveraitSQLmatchesWHERE-clausethefragmentconditionscopedyoutogive.thatWebhookstickerneed(e.g.a"rsi_14paid>plan70(FreeANDhasrelative_volumeno>webhook2"slots).PassOmit `target_url` foran https POST, or `channel:"discord"` + `discord_url` to post to Discord; omit forin-appin-app.delivery.
{"properties":{"cadence":{"description":"EvaluationHowcadence.oftenDefaulttorealtime;evaluate.hourly/nyse_open`realtime`throttle.(the default) is evaluated on every data refresh (`1m`~1×/min);accepted`hourly`asand `nyse_open` throttle to a batch schedule. `1m` is a deprecated aliasofforrealtime.)`realtime`.","enum":["realtime","hourly"," ⟨2 unchanged words⟩ string"},"channel":{"description":"Deliverychannel:
Send a real-shape`webhook.fired`test POST tothe webhook's target_url synchronously, right now. The body is byte-identical to a real fire (same signing); the test marker rides in an `X-Tickerbot-Test: true` header. Returns the inline outcome (`delivered`, `http_status`,your`elapsed_ms`endpoint,`error`).instantly. One-shot—: a failed test never retries and never auto-disables the webhook.Fails with400ifwhen the webhook has notarget_url (in-app deliveries have nothing to fire over the wire).target_url.
Edit oneUpdateofathecustomcaller'ssignalcustomyousignalsown —supply `expr`,its`description`expression,`new_name`description, orany combination. Providing `expr` recompiles it against the live signal whitelist. Renaming is refused (409) while other custom signals reference the currentname.Built-in signals are read-only; only custom signals the caller owns can be patched. Available on every plan.
{"properties":{"description":{"description":"New description. Not derived from `expr` — change both if the prose describes a threshold you are moving.","type":"string"},"expr":{"description":"New SQLWHEREexpression. Re-validatedonandsave.re-inlined against your other custom signals. Same strict grammar as create — no `LIKE`/`ILIKE`, `CASE`, `::` casts, or functions beyond `abs`/`coalesce`/`round`/`least`/`greatest`. The response echoes your expression verbatim, not its expansion.","type":"string"},"namenew_name":{"description":"CURRENTNew slug —identifiesrenameswhichthe signaltoandedit.changes its API handle everywhere (same validation as create). Refused while other custom signals reference the current name. `name` is accepted as an alias (new_name wins when both are sent), but new_name is the unambiguous spelling since the URL already carries the current name.","type":"string"},"new_namesignal":{"description":"Rename theCustom signalto this
Update one oftheyourcaller'suniverses:universes.itsPassname,`name`/`description`description,toorrelabel,members. `tickers`to replacereplaces the wholelist, orlist; `add`/`remove`toadjustsubsets without replacing.it. System universes(`top_10`/`top_100`)cannot be edited.
⟨13 unchanged words⟩ "},"description":{"description":"New notes. Max 500 characters.","type":"string"},"id":{ ⟨5 unchanged words⟩ "},"name":{"description":"New label. Non-empty, max 80 characters.","type":"string"},"remove":{ ⟨10 unchanged words⟩ ":{"description":"Replace the full tickerlist.list (up to 10,000; validated against the active universe). Does not combine with `add`/`remove` (400).","items":{"type":"string"}, ⟨6 unchanged words⟩
OHLCV bars from 1-second through monthly. The feed underneath the table.
Returns an ETF's constituents and their weights, heaviest first. When the ticker is not an ETF, `is_etf` is false and `holdings` is empty; `is_etf: true` with zero holdings means a real ETF whose holdings are not ingested yet. The reverse lookup ("which ETFs hold NVDA") is a scan filter on `etf_holders`, not this tool.
Returns an ETF's sector weights, heaviest first. Always complete, since sector breakdowns are small. When the ticker is not an ETF, `is_etf` is false and `sectors` is empty.
The state of a signal is the set of tickers matching it right now, or with `asof`, as of any moment. One name, the whole market, one call. Booleans need no `condition`; numerics need one like ">70". Sorted by signal value desc for numerics.
Every signal you can name in a query — the built-in signals and your own custom signals, in one catalog. Use to discover the signal names and `q` vocabulary before composing a scan; custom signals appear with `kind: custom`.
Edit a webhook in place — send only the fields you want to change. The trigger and channel are immutable — delete and re-create to change what fires or where it delivers. Unknown fields are a 400.
Find tickers that match a single signal right now (or as of any past date with `asof`). Booleans need no condition. Numerics need a `condition` like ">70" or "<=200". Sorted by signal value desc for numerics.
Get OHLCV (open/high/low/close/volume) bars for one or more symbols at a given interval, oldest-first. Pass a comma-separated `ticker` list (up to 50) for a bulk response keyed by symbol. Use `asof` for a single point-in-time bar, or `before`+`limit` to back-page. `1d`/`1h` cover the full universe with full history; sub-hour intervals back-fill on demand.
Time-travel SNAPSHOT: the full wide row for one ticker as it stood at a past date (one row, not a series — for a multi-signal time SERIES use tickerbot_get_series). Returns indicators, booleans, and the most-recent fundamentals known on that date. Unlimited depth on every plan.
Get an ETF's constituent holdings and their weights, heaviest first. When the ticker is not an ETF, `is_etf` is false and `holdings` is empty; `is_etf: true` with zero holdings means a real ETF whose holdings aren't ingested yet. (The reverse lookup "which ETFs hold NVDA" is a scan filter on the `etf_holders` column, not this tool.)
Get an ETF's sector allocation (sector weights, heaviest first). When the ticker is not an ETF, `is_etf` is false and `sectors` is empty; `is_etf: true` with zero sectors means a real ETF whose sector data isn't ingested yet.
List the unified signal catalog: every built-in signal on the schema (`kind: builtin`) plus the caller's custom signals (`kind: custom`). Built-in rows carry the audited spec metadata — description, category, update cadence, ticker coverage (`ticker_scope`), history depth (`history`/`history_since`), queryable resolutions, and asset classes. Use to discover what `q=` clauses and signal names are available before composing a scan.
List the built-in system universes (`top_10`, `top_100` — the most-actively-traded tickers by 30-day trailing dollar volume, rebalanced monthly). Available to every account regardless of plan. Use these slugs as `universe` in scans/signals or `universe_id` when subscribing.
Edit a webhook in place: `name`, `cadence`, `target_url`, `enabled` (pausing/resuming without losing match-state). The trigger (q) and channel are immutable by design — delete and re-create to change what fires or where it delivers. Unknown fields are a 400, never silently ignored.
Find tickers that match a single signal right now (oratasaof any pastmomentdate with `asof`). Booleans need no condition. Numerics ⟨15 unchanged words⟩
Get the full current row for one ticker — everycolumnsignal on the schema (price, change, indicators like rsi_14, every booleanflaglike above_sma_50, fundamentals like pe_ratio). Pass a ⟨30 unchanged words⟩ 30:00Z) for the row(s) asthey stood atof that pastmomentdate — date-only gives the close of that day.
Data-coverage report for one ticker — which intervals andcolumnssignals exist, from when, at what depth. The ⟨57 unchanged words⟩
⟨17 unchanged words⟩ row, not a series — for amulti-columnmulti-signal time SERIES use tickerbot_get_series). Returns indicators,boolean flagsbooleans, and the most-recent fundamentals known on that ⟨6 unchanged words⟩
⟨39 unchanged words⟩ kinds that join only when named: `signal` (boolean-flagboolean firings) and `news`. Rows are { ticker, ⟨99 unchanged words⟩
⟨243 unchanged words⟩ opt-in and join only when named: `signal` (boolean-flagboolean firings) and `news`.","type":"string" ⟨22 unchanged words⟩ ). Interval-union before unpivoting: runs of theflagboolean separated by ≤ N seconds collapse into one, so aflagboolean with thousands of per-tick fragments yields one enter and one exit per real run (3600 for hourlyflagsbooleans, 86400 for daily). Default 0 = ⟨216 unchanged words⟩
List the unified signal catalog: every built-incolumnsignal on the schema (`kind: builtin`) plus ⟨45 unchanged words⟩
Run a SQL WHERE clause against the live ticker universe (oragainstasaof any pastmomentdate with `asof` — unlimited depth on every plan ⟨65 unchanged words⟩
⟨14 unchanged words⟩ combination. Providing `expr` recompiles it against the livecolumnsignal whitelist. Renaming is refused (409) while other ⟨23 unchanged words⟩
⟨38 unchanged words⟩ (snake_case, must not collide with a built-incolumnsignal or another of your signals).","type ⟨5 unchanged words⟩
Occurrence SPANS of a boolean signal for one ticker, newest-first. For STATE flags (above_sma_50, in_uptrend) each row is a true-WINDOW: started_at when it flipped true, ended_at when it flipped back (null while still true), with prices at both ends. For EVENT flags (golden_cross, gap_up) each row is a point firing (started_at = ended_at). "Golden crosses in June" is from=2026-06-01&to=2026-06-30. Built-in booleans only — numerics and custom signals have no precomputed spans (use tickerbot_get_series).