Skip to main content
Glama

Server Details

The stock market, in SQL — scan, replay, or subscribe across ~12k US tickers and top 100 cryptos.

Glama couldn't complete the latest health check. If this server requires authentication, missing or expired test credentials may be the cause. A test profile lets Glama authenticate for health checks and discover tools; it is separate from your personal connections.

If you are the author, claim ownership, then add or update a test profile under Admin → Test Profile.

Status
Unhealthy
Uptime
86.9% over 58 days
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP
URL
Repository
tickerbot/tickerbot-mcp
GitHub Stars
0
Server Listing
Tickerbot MCP Server

TDQS

B3.4/5.0

Scored across 32 tools

Disambiguation3/5

Most tools target distinct resources or actions, but the four subscribe_* tools are explicitly 'flat sugar' over create_webhook, yielding five overlapping ways to set up webhook delivery. Descriptions help, but an agent may still hesitate between create_webhook and the subscribe variants.

Naming Consistency5/5

All tools use snake_case with a consistent tickerbot_ prefix and predominantly verb_noun structure (create_, get_, list_, update_, delete_, subscribe_). The only minor deviation is tickerbot_scan, which lacks an explicit noun but remains readable and predictable.

Tool Count2/5

32 tools is well beyond the typical 3-15 range and exceeds the 25+ threshold for 'too many'; the four redundant subscribe_* aliases inflate the count. The domain is complex, but the set is heavier than necessary.

Completeness4/5

The surface covers market data, signals, universes, and webhooks with create/get/list/update/delete lifecycles, plus subscriptions and testing. Minor gaps include no explicit disable_webhook (only enable_webhook), though update_webhook may cover it; overall the core workflows are complete.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updates
    • Changedtickerbot_get_bars1 field changed
      • changedInput schema / properties / asof / description
        Previous value: -"Point-in-time: the most recent bar whose period had closed at or before that moment. A bare `YYYY-MM-DD` means that day's close. A full timestamp means the last FINISHED bar — at 10:00 ET on a Wednesday the day's close has not happened, so `1d` returns Tuesday's bar. Returns one bar unless you also pass `limit`, which gives the last `limit` closed bars; follow `next_cursor` with the same parameters to keep paging back. Mutually exclusive with `before` (400). Unlimited depth."New value: +"Point-in-time: the most recent bar whose period had closed at or before that moment. A bare `YYYY-MM-DD` means that day's close. A full timestamp means the last FINISHED bar — at 10:00 ET on a Wednesday the day's close has 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`, which gives the last `limit` closed bars; follow `next_cursor` with the same parameters to keep paging back. Mutually exclusive with `before` (400). Unlimited depth. Response time: under 1.5 s cold, under 0.5 s warm."
    • Changedtickerbot_get_series2 fields changed
      • changedInput schema / properties / asof / description
        Previous value: -"Point-in-time read: ONE row per ticker — 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) — a point and a window are contradictory, and `limit` has no meaning under it. It also resolves WHICH COMPANY held the symbol at that instant: a ticker that changed hands returns the row of whoever traded it then, so `tickers=SHLD&asof=2010-06-30` returns Sears Holdings' price and `asof=2026-01-01` returns the Global X defence ETF. Returns the most recent row at or before the instant, so a date inside a trading gap gives the last row before it; on the `1d` and `1w` grids a timestamp returns the previous session's row, never that day's close. Also: `next_cursor` is always `null` (every requested ticker is on the one page). At `interval=1q` the anchor is the date the quarter was REPORTED (earnings release / filing), not fiscal period end — you get the latest quarter that was public knowledge at the instant, with restatements after it excluded."New value: +"Point-in-time read: ONE row per ticker — 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) — a point and a window are contradictory, and `limit` has no meaning under it. It also resolves WHICH COMPANY held the symbol at that instant: a ticker that changed hands returns the row of whoever traded it then, so `tickers=SHLD&asof=2010-06-30` returns Sears Holdings' price and `asof=2026-01-01` returns the Global X defence ETF. Returns the most recent row at or before the instant, so a date inside a trading gap gives the last row before it; on the `1d` and `1w` grids a timestamp returns the previous session's row, never that day's close. Also: `next_cursor` is always `null` (every 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. At `interval=1q` the anchor is the date the quarter was REPORTED (earnings release / filing), not fiscal period end — you get the latest quarter that was public knowledge at the instant, with restatements after it excluded. Response time: under 1.5 s cold, under 0.5 s warm."
      • changedInput schema / properties / interval / description
        Previous value: -"Grid granularity. `1w` resamples the daily tier weekly (Monday-keyed); `1q` is the fiscal-quarter grid."New value: +"Grid granularity. `1w` resamples the daily tier weekly (Monday-keyed); `1q` is the fiscal-quarter grid. This is the grid, not a state tier: there is no `auto` here and nothing blends — under `asof` you get the last row on this grid, and a column the grid does not carry is a `400`."
    • Changedtickerbot_get_ticker1 field changed
      • changedInput schema / properties / interval / description
        Previous value: -"Grain the past state is read at: `1m`, `1h`, `1d`, or `auto` (default). `auto` blends: each 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 a grain for the fastest response: one grain is read instead of three, and every ticker is captured on the same clock. A signal the pinned grain does not store is a `400 interval_unavailable` naming the grains that carry it (`rsi_14`, fundamentals and valuation ratios are `1d`-only). Only valid alongside `asof`: a live read with `interval` is a 400."New value: +"Grain the past state is read at: `1m`, `1h`, `1d`, or `auto` (default). `auto` blends: each 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 a grain for the fastest response: one grain is read instead of three. On this single-ticker read a pinned grain returns the columns that grain stores (`rsi_14`, fundamentals and valuation ratios are `1d`-only, so they are absent under `1h`/`1m` rather than refused), and a grain with no row for the ticker within its 5-day window is a `404 interval_unavailable`. Only valid alongside `asof`: a live read with `interval` is a 400."
    • Changedtickerbot_list_events1 field changed
      • changedInput schema / properties / interval / description
        Previous value: -"Grain the per-event state is read at, when `join=state`: `1m`, `1h`, `1d`, or `auto` (default). Under `auto`, row reads blend each signal at its freshest grain at or before the event across hourly and the last closed daily session, and `group_by` reads use the daily session; events join state once per event, so the minute grain is reached by pinning `1m`. A pinned grain reads that grain only: events on tickers absent from a pinned `1m`/`1h` join to `null`, and a column the grain does not store is a `400`. Reported as `_meta.state_interval` (`auto` with `_meta.state_blended: true`, or the pinned grain)."New value: +"Grain the per-event state is read at, when `join=state`: `1m`, `1h`, `1d`, or `auto` (default). Under `auto`, row reads blend each signal at its freshest grain at or before the event across hourly and the last closed daily session, and `group_by` reads use the daily session; events join state once per event, so the minute grain is reached by pinning `1m`. A pinned grain reads that grain only: events on tickers absent from a pinned `1m`/`1h` join to `null`, and a column 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`, or the pinned grain)."
  2. 4 tool updates
    • Changedtickerbot_get_signal1 field changed
      • changedInput schema / properties / interval / description
        Previous value: -"Grain the past state is reconstructed at: `1m`, `1h`, `1d`, or `auto` (default). Only valid alongside `asof` — a live read with `interval` is a 400. Details under As of a past date."New value: +"Grain the past state is read at: `1m`, `1h`, `1d`, or `auto` (default). `auto` blends: each 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 a grain for the fastest response: one grain is read instead of three, and every ticker is captured on the same clock. A signal the pinned grain does not store is a `400 interval_unavailable` naming the grains that carry it (`rsi_14`, fundamentals and valuation ratios are `1d`-only). Only valid alongside `asof`: a live read with `interval` is a 400."
    • Changedtickerbot_get_ticker1 field changed
      • changedInput schema / properties / interval / description
        Previous value: -"Grain the past state is reconstructed at: `1m`, `1h`, `1d`, or `auto` (default). Only valid alongside `asof` — a live read with `interval` is a 400. Details under As of a past date."New value: +"Grain the past state is read at: `1m`, `1h`, `1d`, or `auto` (default). `auto` blends: each 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 a grain for the fastest response: one grain is read instead of three, and every ticker is captured on the same clock. A signal the pinned grain does not store is a `400 interval_unavailable` naming the grains that carry it (`rsi_14`, fundamentals and valuation ratios are `1d`-only). Only valid alongside `asof`: a live read with `interval` is a 400."
    • Changedtickerbot_list_events1 field changed
      • changedInput schema / properties / interval / description
        Previous value: -"Grain the per-event state is reconstructed at, when `join=state`: `1m`, `1h`, `1d`, or `auto` (default). `auto` resolves to `1d` — the event set's tickers are not known before the query runs, and `1d` is the only tier covering the whole universe, so it is the only grain guaranteed to satisfy every event. An explicit `1m`/`1h` trades coverage for precision: events on tickers absent from that tier join to `null`. A referenced column the grain does not store is a `400`. Reported back as `_meta.state_interval`."New value: +"Grain the per-event state is read at, when `join=state`: `1m`, `1h`, `1d`, or `auto` (default). Under `auto`, row reads blend each signal at its freshest grain at or before the event across hourly and the last closed daily session, and `group_by` reads use the daily session; events join state once per event, so the minute grain is reached by pinning `1m`. A pinned grain reads that grain only: events on tickers absent from a pinned `1m`/`1h` join to `null`, and a column the grain does not store is a `400`. Reported as `_meta.state_interval` (`auto` with `_meta.state_blended: true`, or the pinned grain)."
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / interval / description
        Previous value: -"Grain the past state is reconstructed at: `1m`, `1h`, `1d`, or `auto` (default). Only valid alongside `asof` — a live read with `interval` is a 400. Details under As of a past date."New value: +"Grain the past state is read at: `1m`, `1h`, `1d`, or `auto` (default). `auto` blends: each 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 a grain for the fastest response: one grain is read instead of three, and every ticker is captured on the same clock. A signal the pinned grain does not store is a `400 interval_unavailable` naming the grains that carry it (`rsi_14`, fundamentals and valuation ratios are `1d`-only). Only valid alongside `asof`: a live read with `interval` is a 400."
  3. 6 tool updates
    • Changedtickerbot_get_bars1 field changed
      • changedInput schema / properties / asof / description
        Previous value: -"Point-in-time: the most recent bar whose period had closed at or before that moment. A bare `YYYY-MM-DD` means that day's close. A full timestamp means the last FINISHED bar — at 10:00 ET on a Wednesday the day's close has not happened, so `1d` returns Tuesday's bar. Returns one bar unless you also pass `limit`, which gives the last `limit` closed bars. Mutually exclusive with `before`/`cursor` (400). Unlimited depth."New value: +"Point-in-time: the most recent bar whose period had closed at or before that moment. A bare `YYYY-MM-DD` means that day's close. A full timestamp means the last FINISHED bar — at 10:00 ET on a Wednesday the day's close has not happened, so `1d` returns Tuesday's bar. Returns one bar unless you also pass `limit`, which gives the last `limit` closed bars; follow `next_cursor` with the same parameters to keep paging back. Mutually exclusive with `before` (400). Unlimited depth."
    • Changedtickerbot_get_series1 field changed
      • changedInput schema / properties / asof / description
        Previous value: -"Point-in-time read: ONE row per ticker — 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) — a point and a window are contradictory, and `limit` has no meaning under it. It also resolves WHICH COMPANY held the symbol at that instant: a ticker that changed hands returns the row of whoever traded it then, so `tickers=SHLD&asof=2010-06-30` returns Sears Holdings' price and `asof=2026-01-01` returns the Global X defence ETF. Returns the most recent row at or before the instant, so a date inside a trading gap gives the last row before it. At `interval=1q` the anchor is the date the quarter was REPORTED (earnings release / filing), not fiscal period end — you get the latest quarter that was public knowledge at the instant, with restatements after it excluded."New value: +"Point-in-time read: ONE row per ticker — 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) — a point and a window are contradictory, and `limit` has no meaning under it. It also resolves WHICH COMPANY held the symbol at that instant: a ticker that changed hands returns the row of whoever traded it then, so `tickers=SHLD&asof=2010-06-30` returns Sears Holdings' price and `asof=2026-01-01` returns the Global X defence ETF. Returns the most recent row at or before the instant, so a date inside a trading gap gives the last row before it; on the `1d` and `1w` grids a timestamp returns the previous session's row, never that day's close. Also: `next_cursor` is always `null` (every requested ticker is on the one page). At `interval=1q` the anchor is the date the quarter was REPORTED (earnings release / filing), not fiscal period end — you get the latest quarter that was public knowledge at the instant, with restatements after it excluded."
    • Changedtickerbot_get_signal1 field changed
      • changedInput schema / properties / asof / description
        Previous value: -"Optional. Target moment as `YYYY-MM-DD` (that day's close) or an ISO timestamp (that intraday moment) — the same read as it stood then, unlimited depth. Full contract under As of a past date."New value: +"Optional. Target moment as `YYYY-MM-DD` (that day's close) or an ISO timestamp (that intraday moment; daily-only signals then carry the previous session's close, never that day's) — the same read as it stood then, unlimited depth. Full contract under As of a past date."
    • Changedtickerbot_get_ticker1 field changed
      • changedInput schema / properties / asof / description
        Previous value: -"Optional. Target moment as `YYYY-MM-DD` (that day's close) or an ISO timestamp (that intraday moment) — the same read as it stood then, unlimited depth. Full contract under As of a past date."New value: +"Optional. Target moment as `YYYY-MM-DD` (that day's close) or an ISO timestamp (that intraday moment; daily-only signals then carry the previous session's close, never that day's) — the same read as it stood then, unlimited depth. Full contract under As of a past date."
    • Changedtickerbot_list_events1 field changed
      • changedInput schema / properties / join / description
        Previous value: -"Set to `state` to allow ticker-state signals in `q`/`select`/`group_by`/`having`, evaluated as of each event's timestamp (daily resolution)."New value: +"Set to `state` to allow ticker-state signals in `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."
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / asof / description
        Previous value: -"Optional. Target moment as `YYYY-MM-DD` (that day's close) or an ISO timestamp (that intraday moment) — the same read as it stood then, unlimited depth. Full contract under As of a past date."New value: +"Optional. Target moment as `YYYY-MM-DD` (that day's close) or an ISO timestamp (that intraday moment; daily-only signals then carry the previous session's close, never that day's) — the same read as it stood then, unlimited depth. Full contract under As of a past date."
  4. 1 tool update
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~23,203 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~23,212 tracked tickers."
  5. 1 tool update
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,963 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~23,203 tracked tickers."
  6. 1 tool update
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,122 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,963 tracked tickers."
  7. 1 tool update
    • Changedtickerbot_list_events2 fields changed
      • changedInput schema / properties / kind / description
        Previous value: -"Comma list of kinds. Omitted → the five corporate kinds; `signal` and `news` join only when named here."New value: +"Comma list of kinds. Omitted → the five corporate kinds; `signal`, `news` and `estimate_revision` join only when named here."
      • changedInput schema / properties / kind / enum
        Previous value: -[
        -  "dividend",
        -  "split",
        -  "insider",
        -  "analyst",
        -  "earnings",
        -  "signal",
        -  "news"
        -]New value: +[
        +  "dividend",
        +  "split",
        +  "insider",
        +  "analyst",
        +  "earnings",
        +  "signal",
        +  "news",
        +  "estimate_revision"
        +]
  8. 1 tool update
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,082 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,122 tracked tickers."
  9. 2 tool updates
    • Changedtickerbot_get_bars2 fields changed
      • changedOutput schema / properties / coverage / description
        Previous value: -"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."New value: +"`covered` when bars were found, `no_data` when nothing exists for the symbol in the window (before its first session, a market holiday, a thin name with no prints). A page that could not be completed is never a 200: it is a `503 unavailable` with `Retry-After`."
      • changedOutput schema / properties / note / description
        Previous value: -"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."New value: +"Present only when there is something to disclose about how the page was served: the first request for a symbol at a sub-hour interval loads and stores its bars, so that one call is slower than later ones, and the note says so. Bulk responses carry `notes[symbol]` instead."
    • Changedtickerbot_get_ticker_coverage1 field changed
      • changedOutput schema / properties / minute_tier / description
        Previous value: -"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."New value: +"Deprecated (see the changelog): an internal precompute roster that has no bearing on what bars you can read — sub-hour bars are available for every active symbol. Do not branch on it."
  10. 1 tool update
    • Changedtickerbot_list_events1 field changed
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "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"
        +}
  11. 10 tool updates
    • Changedtickerbot_create_custom_signal2 fields changed
      • changedInput schema / properties / expr / description
        Previous value: -"Boolean SQL predicate. May reference built-in signals and other custom signals you own. Must evaluate to true/false. Max 4000 chars. Stricter grammar than scan `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."New value: +"Boolean SQL predicate. May reference built-in signals and other custom signals you own. Must evaluate to true/false. Max 4000 chars. Stricter grammar than scan `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 as stored, 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. 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`."
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "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"
        +}
    • Changedtickerbot_create_webhook1 field changed
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "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"
        +}
    • Changedtickerbot_get_series1 field changed
      • changedOutput schema / properties / _meta / description
        Previous value: -"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."New value: +"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. `deprecated_columns` lists any column you named under its pre-2026-09-07 spelling that was served under its current name (`requested`, `use`, `note`)."
    • Changedtickerbot_get_signal1 field changed
      • changedOutput schema / properties / _meta / description
        Previous value: -"With `asof` only: how the read was resolved — interval served and requested, blending, sources, frozen fields. See the as-of read below."New value: +"With `asof`: how the read was resolved — interval served and requested, blending, sources, frozen fields (see the as-of read 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."
    • Changedtickerbot_scan1 field changed
      • changedOutput schema / properties / _meta / description
        Previous value: -"`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`."New value: +"`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`. `deprecated_columns` lists any column you named under its pre-2026-09-07 spelling that was served under its current name (`requested`, `use`, `note`)."
    • Changedtickerbot_subscribe_events1 field changed
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "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"
        +}
    • Changedtickerbot_subscribe_scan1 field changed
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "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"
        +}
    • Changedtickerbot_subscribe_signal1 field changed
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "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"
        +}
    • Changedtickerbot_subscribe_ticker1 field changed
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "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"
        +}
    • Changedtickerbot_update_custom_signal2 fields changed
      • changedInput schema / properties / expr / description
        Previous value: -"New SQL expression. Re-validated and 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."New value: +"New SQL expression. Re-validated and 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 as stored, not its expansion (a pre-2026-09-07 column spelling is stored under its current name and reported in `_meta.deprecated_columns`)."
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "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"
        +}
  12. 6 tool updates
    • Changedtickerbot_create_webhook1 field changed
      • changedOutput schema / required
        Previous value: -[
        -  "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"
        -]New value: +[
        +  "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"
        +]
    • Changedtickerbot_get_etf_holdings1 field changed
      • changedOutput schema / required
        Previous value: -[
        -  "as_of",
        -  "ticker",
        -  "is_etf",
        -  "count",
        -  "truncated",
        -  "total",
        -  "holdings"
        -]New value: +[
        +  "as_of",
        +  "ticker",
        +  "is_etf",
        +  "count",
        +  "holdings"
        +]
    • Changedtickerbot_subscribe_events1 field changed
      • changedOutput schema / required
        Previous value: -[
        -  "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"
        -]New value: +[
        +  "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"
        +]
    • Changedtickerbot_subscribe_scan1 field changed
      • changedOutput schema / required
        Previous value: -[
        -  "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"
        -]New value: +[
        +  "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"
        +]
    • Changedtickerbot_subscribe_signal1 field changed
      • changedOutput schema / required
        Previous value: -[
        -  "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"
        -]New value: +[
        +  "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"
        +]
    • Changedtickerbot_subscribe_ticker1 field changed
      • changedOutput schema / required
        Previous value: -[
        -  "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"
        -]New value: +[
        +  "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"
        +]
  13. 3 tool updates
    • Changedtickerbot_get_bars1 field changed
      • changedOutput schema / required
        Previous value: -[
        -  "as_of",
        -  "ticker",
        -  "interval",
        -  "adjusted",
        -  "session",
        -  "count",
        -  "coverage",
        -  "bars"
        -]New value: +[
        +  "as_of",
        +  "interval",
        +  "adjusted",
        +  "session",
        +  "count",
        +  "coverage",
        +  "bars"
        +]
    • Changedtickerbot_list_tickers1 field changed
      • addedOutput schema / properties / _meta
        Added value: +{
        +  "description": "With `asset_class` only: `scope.asset_class` lists the classes the page was filtered to.",
        +  "type": "object"
        +}
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,072 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,082 tracked tickers."
  14. 3 tool updates
    • Changedtickerbot_create_webhook1 field changed
      • changedInput schema / properties / trigger / properties / condition / description
        Previous value: -"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`."New value: +"signal: required for every non-boolean signal — a single bound typed like the signal: `>70` (numeric), `<YYYY-MM-DDTHH:MM:SSZ` (timestamp), `>=YYYY-MM-DD` (date), `=ETF` (string); sending one with a boolean or custom signal returns 400 (it does not apply). ticker: accepted as the original alias of `trigger.q`."
    • Changedtickerbot_get_signal2 fields changed
      • changedInput schema / properties / condition / description
        Previous value: -"Required for numeric signals. Single bound, format `<op><value>`. Operators: `>`, `>=`, `=`, `!=`, `<`, `<=`. Examples: `>70`, `<=200`, `!=0`. Sending one with a boolean or custom signal returns 400 (it does not apply)."New value: +"Required for every non-boolean signal; the shape follows the signal's `type` in the catalog. Single bound, `<op><value>`. numeric: `>70`, `<=200`, `!=0` (operators `>`, `>=`, `=`, `!=`, `<`, `<=`). timestamp: an ISO instant, `<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'`. Sending a condition with a boolean or custom signal returns 400 (it does not apply)."
      • changedInput schema / properties / signal / description
        Previous value: -"A signal name. Booleans (e.g. `golden_cross`, `above_sma_50`) are detected automatically; numerics (e.g. `rsi_14`, `market_cap`, `pe_ratio`) require a condition."New value: +"A signal name. Booleans (e.g. `golden_cross`, `above_sma_50`) are detected automatically; every other type (numeric `rsi_14`, timestamp `price_asof`, date `earnings_date`, string `asset_class`) requires a `condition`."
    • Changedtickerbot_subscribe_signal1 field changed
      • changedInput schema / properties / condition / description
        Previous value: -"Required for numeric signals. Shape: `\">70\"`, `\"<30\"`, `\">=100\"`, `\"=50\"`. Sending one with a boolean or custom signal returns 400 (it does not apply)."New value: +"Required for every non-boolean signal; the shape follows the signal's `type`. Numeric: `\">70\"`, `\"<30\"`, `\">=100\"`. Timestamp: `\"<YYYY-MM-DDTHH:MM:SSZ\"` (or a bare date). Date: `\">=YYYY-MM-DD\"`. String: `\"=ETF\"` or `\"!=ETF\"`. Sending one with a boolean or custom signal returns 400 (it does not apply)."
  15. 1 tool update
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,066 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,072 tracked tickers."
  16. 1 tool update
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,053 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,066 tracked tickers."
  17. 1 tool update
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,040 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,053 tracked tickers."
  18. 29 tool updates
    • Changedtickerbot_create_custom_signal1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_create_universe1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_create_webhook1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_enable_webhook1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_bars1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_etf_holdings1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_etf_sectors1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_series1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_signal1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_ticker1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_ticker_coverage1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_universe1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_get_webhook1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_list_events1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_list_signals1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_list_tickers1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_list_universes1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_list_webhook_deliveries1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_list_webhooks1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_scan1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_search_news1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_subscribe_events1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_subscribe_scan1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_subscribe_signal1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_subscribe_ticker1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_test_webhook1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_update_custom_signal1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_update_universe1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
    • Changedtickerbot_update_webhook1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "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"
        +}
  19. 4 tool updates
    • Changedtickerbot_list_events1 field changed
      • changedInput schema / properties / kind / enum
        Previous value: -[
        -  "earnings",
        -  "dividend",
        -  "split",
        -  "insider",
        -  "analyst",
        -  "news",
        -  "signal"
        -]New value: +[
        +  "dividend",
        +  "split",
        +  "insider",
        +  "analyst",
        +  "earnings",
        +  "signal",
        +  "news"
        +]
    • Changedtickerbot_list_tickers1 field changed
      • removedInput schema / properties / exchange / enum
        Removed value: -[
        -  "NASDAQ",
        -  "NYSE",
        -  "NYSE Arca",
        -  "Cboe BZX",
        -  "NYSE American",
        -  "OTC Link"
        -]
    • Changedtickerbot_scan1 field changed
      • changedInput schema / properties / universe / description
        Previous value: -"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,033 tracked tickers."New value: +"Slug of a system universe (`top_10`, `top_100`) or one of your own. Omitted, the scan runs across all ~21,040 tracked tickers."
    • Changedtickerbot_subscribe_events1 field changed
      • changedInput schema / properties / kinds / enum
        Previous value: -[
        -  "earnings",
        -  "dividend",
        -  "split",
        -  "insider",
        -  "analyst"
        -]New value: +[
        +  "dividend",
        +  "split",
        +  "insider",
        +  "analyst",
        +  "earnings"
        +]

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    C
    maintenance
    Read-only SQL MCP server for quantitative finance data (DuckDB) with stock quotes, financials, and historical K-lines, enabling cross-database JOIN queries.
    1
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides US stock market data for AI agents, including intraday and daily bars, SEC fundamentals, filings, and insider data, with pay-per-query via USDC on Base.
    1
    MIT
  • A
    license
    B
    quality
    F
    maintenance
    Real-time crypto, stock, and prediction-market data for agents — prices, indicators, funding rates, DeFi TVL, macro calendar, and an AI momentum score. Configure one Base wallet key and it just works. No signup, no dashboard, no subscription.
    22
    396 npm
    MIT
  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    Real-time financial market data MCP server. Stocks, crypto, technicals, sentiment, FDA calendar. No API keys required.
    -
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.