Skip to main content
Glama

tickerbot_create_webhook

Canonical create: a webhook is a trigger plus a delivery. Trigger shapes: scan {type:"scan", q, universe?}; ticker {type:"ticker", ticker, condition}; signal {type:"signal", signal, ticker?, universe?, condition?}; event {type:"event", kinds, tickers?, universe?, event_q?}. The subscribe tools are flat sugar over exactly this. Webhooks need a paid plan (Free has no webhook slots).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dirNoSort direction for `order`. Not accepted on `event` triggers (400).desc
nameNoDisplay name, max 80 characters. Defaults to an auto-generated one from the trigger.
orderNoSignal the fired payload's match lists are sorted by before the 100-row cap is applied — so a truncated list is the deterministic top 100, not an arbitrary sample. Same contract as `POST /v2/scan`. Not accepted on `event` triggers (they deliver one event at a time).market_cap
cadenceNoEvaluation cadence — a user preference — never gated. Event triggers deliver on ingest — only `realtime` is accepted on them (400 otherwise).realtime
channelNoDelivery channel. See Delivery channels.
columnsNoExtra columns echoed in fired payloads' match rows (`fields` accepted as an alias). Not accepted on `event` triggers (400) — event deliveries carry the event payload, not state rows.
triggerYesWhat fires the webhook. A discriminated object — `trigger.type` picks the shape, and the fields below belong inside it. Each shape is also available as a flat-params shortcut: `POST /v2/scan/subscribe`, `/v2/tickers/{t}/subscribe`, `/v2/signals/{s}/subscribe`, `/v2/events/subscribe`.
device_idNoRegistered device id (channel `mobile_push`, see /v2/devices).
target_urlNoHTTPS delivery URL (the `webhook` channel), max 1024 characters. Omit for in-app delivery, or use `channel` + `discord_url`/`device_id` for other channels.
discord_urlNoDiscord webhook URL (channel `discord`).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
qYesThe stored predicate. Custom signals appear expanded: the SQL is frozen at creation.
idYesThe webhook id — `wh_…`, the handle for every other call on this record.
dirYesSort direction for that list; `null` means the default (`desc`).
nameYesYour label for the subscription.
as_ofYesServer time this response was assembled (ISO 8601).
orderYesSort signal for the payload row list; `null` means the evaluator default (`market_cap`).
fieldsYesExtra signals carried on each fired match row; `null` means the standard set.
sourceYesWhich API version created the record; `v2` for anything you create today.
statusYes`active` or `disabled`. Auto-disable follows repeated delivery failure.
cadenceYesHow often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.
channelYesWhere deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.
event_qNoEvent-trigger webhooks only: the payload filter, or `null`.
rule_idYesLegacy link to a v1 alert rule; `null` on everything created through v2.
deliveryYesLegacy alias of `channel`, kept aligned for older readers.
test_urlYesReturned on create only: the `POST /v2/webhooks/{id}/test` URL for this record.
created_atYesCreation timestamp.
last_errorNoThe last evaluation error; `null` on a healthy hook. The answer to "why is my webhook not firing?".
last_firedYesWhen a delivery last went out; `null` if it never has.
target_urlYesYour HTTPS endpoint; `null` on every channel except `webhook`.
updated_atYesLast modification timestamp.
event_kindsNoEvent-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).
universe_idYesUniverse the trigger is scoped to, or `null` for the whole market.
next_eval_atYesWhen the evaluator will next consider this subscription.
trigger_kindNoEvent-trigger webhooks only: `event`.
event_tickersNoEvent-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.
channel_configYesReturned on create only: the channel-specific delivery settings as stored (e.g. the Discord URL, the device id).
last_match_setYesTickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.
signing_secretYesReturned on create only — shown once, never again. HMAC key for verifying the `X-Tickerbot-Signature` header on deliveries.
last_evaluated_atYesWhen it was last evaluated; `null` until the first run.
last_eval_error_atNoWhen the last evaluation error happened; `null` on a healthy hook.
subscription_originYesWhich door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.
last_predicate_valueYesThe trigger's value at the last evaluation; `null` until it has run.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema 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`."
  2. Changed1 schema 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"
      +}
  3. Changed13 schema fields changed
    • addedInput schema / properties / cadence / default
      Added value: +"realtime"
    • changedInput schema / properties / cadence / description
      Previous value: -"Evaluation cadence. Default realtime. (`1m` accepted as a deprecated alias of realtime.)"New value: +"Evaluation cadence — a user preference — never gated. Event triggers deliver on ingest — only `realtime` is accepted on them (400 otherwise)."
    • changedInput schema / properties / channel / description
      Previous value: -"Delivery channel. Inferred from the URL you pass if omitted."New value: +"Delivery channel. See Delivery channels."
    • changedInput schema / properties / columns / description
      Previous value: -"Comma list of extra columns to include with each delivered match (`fields` accepted as alias)."New value: +"Extra columns echoed in fired payloads' match rows (`fields` accepted as an alias). Not accepted on `event` triggers (400) — event deliveries carry the event payload, not state rows."
    • changedInput schema / properties / device_id / description
      Previous value: -"Registered device id from the mobile app (channel mobile_push)."New value: +"Registered device id (channel `mobile_push`, see /v2/devices)."
    • addedInput schema / properties / dir
      Added value: +{
      +  "default": "desc",
      +  "description": "Sort direction for `order`. Not accepted on `event` triggers (400).",
      +  "enum": [
      +    "asc",
      +    "desc"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / discord_url / description
      Previous value: -"Discord incoming-webhook URL (channel discord)."New value: +"Discord webhook URL (channel `discord`)."
    • changedInput schema / properties / name / description
      Previous value: -"Display name. Defaults from the trigger."New value: +"Display name, max 80 characters. Defaults to an auto-generated one from the trigger."
    • addedInput schema / properties / order
      Added value: +{
      +  "default": "market_cap",
      +  "description": "Signal the fired payload's match lists are sorted by before the 100-row cap is applied — so a truncated list is the deterministic top 100, not an arbitrary sample. Same contract as `POST /v2/scan`. Not accepted on `event` triggers (they deliver one event at a time).",
      +  "type": "string"
      +}
    • changedInput schema / properties / target_url / description
      Previous value: -"HTTPS delivery URL (`webhook` channel). Omit for in-app."New value: +"HTTPS delivery URL (the `webhook` channel), max 1024 characters. Omit for in-app delivery, or use `channel` + `discord_url`/`device_id` for other channels."
    • changedInput schema / properties / trigger / description
      Previous value: -"What fires the webhook: { type: \"scan\" | \"ticker\" | \"signal\" | \"event\", … } — see the tool description for each shape."New value: +"What fires the webhook. A discriminated object — `trigger.type` picks the shape, and the fields below belong inside it. Each shape is also available as a flat-params shortcut: `POST /v2/scan/subscribe`, `/v2/tickers/{t}/subscribe`, `/v2/signals/{s}/subscribe`, `/v2/events/subscribe`."
    • addedInput schema / properties / trigger / properties
      Added value: +{
      +  "condition": {
      +    "description": "signal: required for numeric signals — a single bound like `>70`; sending one with a boolean or custom signal returns 400 (it does not apply). ticker: accepted as the original alias of `trigger.q`.",
      +    "type": "string"
      +  },
      +  "event_q": {
      +    "description": "event: optional event-CONTENT filter in the `/v2/events` grammar over `(ticker, ts, kind, payload)` — e.g. `payload->>'firm' = 'Goldman Sachs'`. Composes with `trigger.q`.",
      +    "type": "string"
      +  },
      +  "kinds": {
      +    "description": "event: required — event kinds to fire on, array or comma list (e.g. `split,analyst`).",
      +    "type": "string"
      +  },
      +  "q": {
      +    "description": "scan: required — the SQL WHERE any ticker must match to fire. ticker: required — WHERE fragment evaluated for that ticker (auto-scoped; don't add `ticker = …` yourself; `trigger.condition` accepted as an alias). event: optional row-STATE filter on the event's ticker at fire time (`market_cap > 1e10`).",
      +    "type": "string"
      +  },
      +  "signal": {
      +    "description": "signal: required — a built-in signal name (e.g. `rsi_14`) or one of your custom signals (custom SQL is expanded and frozen at creation).",
      +    "type": "string"
      +  },
      +  "ticker": {
      +    "description": "ticker: required — the symbol to watch (e.g. `NVDA`). signal: optional — restrict the signal to one symbol (omit to watch the whole universe).",
      +    "type": "string"
      +  },
      +  "tickers": {
      +    "description": "event: optional symbol list, max 50 (e.g. `AAPL,NVDA`). Mutually exclusive with `trigger.universe`.",
      +    "type": "string"
      +  },
      +  "type": {
      +    "description": "Which trigger shape the rest of the object uses.",
      +    "enum": [
      +      "scan",
      +      "ticker",
      +      "signal",
      +      "event"
      +    ],
      +    "type": "string"
      +  },
      +  "universe": {
      +    "description": "scan / signal / event: optional universe slug (`top_10`, `top_100`, or one of yours) scoping which tickers can fire. Mutually exclusive with `trigger.tickers` on event.",
      +    "type": "string"
      +  }
      +}
    • addedInput schema / properties / trigger / required
      Added value: +[
      +  "type"
      +]
  4. Added

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden, and it steps up: it discloses the paid-plan gating (a real behavioral constraint), the canonical-vs-sugar relationship, and how the discriminated trigger selects its shape. It doesn't mention idempotency or failure behavior, but for a create operation with an output schema present, the key disclosures (plan gate, trigger discrimination) are genuinely additive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with zero waste. Purpose is front-loaded ('Canonical create'), the trigger taxonomy is packed into one sentence, and the sibling-relationship and plan constraints get their own crisp clauses. Every sentence earns its place — this is model concision, not under-specification.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter tool with a nested discriminated union and an output schema, the description covers the conceptual frame, the trigger shapes, the sibling routing, and the plan gate. The output schema covers return values, so the description doesn't need to. Missing minor items like rate limits, but the combination of description plus schema plus output schema is largely sufficient for an agent to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real value beyond the schema: it explains the 'trigger plus delivery' mental model, summarizes each trigger shape's fields (scan/ticker/signal/event), and clarifies how the discriminated object maps to the flat subscribe shortcuts. This conceptual glue is exactly what the raw schema lacks, especially for the nested trigger object.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Canonical create') and defines the core concept ('a webhook is a trigger plus a delivery'). It names sibling subscribe tools and asserts they are 'flat sugar over exactly this', clearly differentiating this canonical tool from those flat variants. The trigger-shape taxonomy is laid out compactly, leaving no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes between the canonical create and the subscribe sugar: 'The subscribe tools are flat sugar over exactly this' tells an agent when to prefer which. It also discloses the paid-plan requirement ('Webhooks need a paid plan (Free has no webhook slots)'). It could be slightly more explicit about when-not-to-use, but the subscribe relationship plus plan gating covers the main decisions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.