Subscribe to events
https://api.tickerbot.io/ v2/ events/ subscribePush new events: we POST your endpoint when events of the kinds you chose land in the archives.
Body parameters
enum[]requiredEvent kinds to fire on — array or comma list.
earnings | Quarterly earnings reports — reported vs estimated EPS and the surprise, timestamped at the report date. |
dividend | Cash-dividend declarations, timestamped at the ex-dividend date. |
split | Stock splits and reverse splits, timestamped at the execution date. |
insider | Officer and director trades — one event per reported Form 4 transaction. |
analyst | Upgrades, downgrades, initiations, and price-target changes. Lands within the hour, 24/7. |
string[]Scope to specific tickers (max 50). Mutually exclusive with universe — and with the singular alias ticker (sending both is a 400). Omit both for all tickers.
stringSingle-symbol shorthand for tickers.
stringScope to a universe slug (top_10, top_100, or one of yours). universe_id accepted as an alias.
stringOptional row-STATE filter evaluated against the event's ticker at fire time. Same grammar as scan q; custom signals are expanded and frozen at creation. See the signals catalog for columns + flags you can compose.
stringOptional event-CONTENT filter in the /v2/events grammar — only ticker, ts, kind, payload may appear. Composes with q.
stringHTTPS delivery URL; or use channel + discord_url/device_id. Omit for in-app.
enumDelivery channel. slack is reserved and returns 501.
webhook | POST the payload to an HTTPS endpoint you own, signed with X-Tickerbot-Signature. |
in_app | Deliver to the in-app feed. No external receiver, so nothing to validate and no test_url. |
discord | Post to a Discord channel via its webhook URL. Delivered as a Discord embed, never HMAC-signed — the URL is itself the credential. |
mobile_push | Push to a registered device. Requires a device_id from Register a device. |
stringDiscord incoming-webhook URL. Required when channel is discord. Stored as a posting credential: the create response echoes it back under channel_config, but every later read (list, get, deliveries) strips it and sets channel_config_present: true instead.
stringDevice to notify, from POST /v2/devices/register. Required when channel is mobile_push; unknown ids are a 404 device_not_found.
stringDisplay name. Defaults to events: <kinds> · <scope>.
Headers
stringOptional unique string (≤255 chars). A retry carrying the same key within 24h replays the original response (Idempotency-Replayed: true header) instead of creating a duplicate; a concurrent duplicate gets 409 idempotency_in_flight; reusing a key for a *different* request (another method or path) gets 422 idempotency_key_reused. 5xx responses are not stored — those retries re-execute.
Returns
as_ofstringServer time this response was assembled (ISO 8601).
idstringThe webhook id — `wh_…`, the handle for every other call on this record.
namestringYour label for the subscription.
qstringThe stored predicate. Custom signals appear expanded: the SQL is frozen at creation.
rule_idstringLegacy link to a v1 alert rule; `null` on everything created through v2.
fieldsstringExtra signals carried on each fired match row; `null` means the standard set.
orderstringSort signal for the payload row list; `null` means the evaluator default (`market_cap`).
dirstringSort direction for that list; `null` means the default (`desc`).
universe_idstringUniverse the trigger is scoped to, or `null` for the whole market.
cadencestringHow often the trigger is evaluated — `realtime`, `hourly`, or `nyse_open`.
channelstringWhere deliveries go: `webhook`, `discord`, `in_app`, or `mobile_push`.
target_urlstringYour HTTPS endpoint; `null` on every channel except `webhook`.
deliverystringLegacy alias of `channel`, kept aligned for older readers.
statusstring`active` or `disabled`. Auto-disable follows repeated delivery failure.
sourcestringWhich API version created the record; `v2` for anything you create today.
subscription_originobjectWhich door created it — `type` (`ticker`/`signal`/`scan`/`event`), its `ref`, and the `condition` in display form.
last_predicate_valuestringThe trigger's value at the last evaluation; `null` until it has run.
created_atnumberCreation timestamp.
updated_atnumberLast modification timestamp.
last_firednumberWhen a delivery last went out; `null` if it never has.
last_match_setarrayTickers matching at the last evaluation — the set the next run is diffed against, which is what makes firing edge-triggered.
last_eval_error_atnumberWhen the last evaluation error happened; `null` on a healthy hook.
last_errorstringThe last evaluation error; `null` on a healthy hook. The answer to "why is my webhook not firing?".
next_eval_atnumberWhen the evaluator will next consider this subscription.
last_evaluated_atnumberWhen it was last evaluated; `null` until the first run.
event_kindsarrayEvent-trigger webhooks only: the kinds subscribed (`split`, `dividend`, `insider`, `analyst`, `earnings`).
event_qstringEvent-trigger webhooks only: the payload filter, or `null`.
event_tickersarrayEvent-trigger webhooks only: the symbols the trigger is scoped to, or `null` for the universe / whole market.
trigger_kindstringEvent-trigger webhooks only: `event`.
channel_configobjectReturned on create only: the channel-specific delivery settings as stored (e.g. the Discord URL, the device id).
signing_secretstringReturned on create only — shown once, never again. HMAC key for verifying the `X-Tickerbot-Signature` header on deliveries.
test_urlstringReturned on create only: the `POST /v2/webhooks/{id}/test` URL for this record.
_metaobjectReturned 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.
Status codes
201test_url.400bad_request — missing/unknown kinds, >50 tickers, tickers+universe together, or invalid q. Also: cadence, order, dir, and columns are not parameters here — event deliveries are ingest-driven and carry the event payload, not ranked state rows, so sending one is a 400 (unknown_parameter), never silently ignored.403webhook_tier_required (Free) or webhook_limit_reached (at cap) — event webhooks consume the same plan slots.404409idempotency_in_flight — a concurrent request carried the same Idempotency-Key.422idempotency_key_reused — the Idempotency-Key was already used for a different request.501channel_not_implemented — channel: "slack" is reserved.Notes
- Sugar for
POST /v2/webhookswithtrigger: { type: "event", … }— the webhook is listed, updated, and deleted at/v2/webhookslike any other. No polling on your side: "every split in my universe", "Goldman downgrades on tickers I hold". - Two optional, composable filters, answering different questions about different objects. `q` filters the event's TICKER STATE at fire time — "downgrades, but only where
market_cap > 1e10" — in scan grammar, with custom signals expanded and frozen at creation. `event_q` filters the EVENT CONTENT — "only wherepayload->>'firm' = 'Goldman Sachs'" — in the/v2/eventsgrammar over exactly(ticker, ts, kind, payload). - Latency is ingest cadence, not sub-minute. Analyst actions land within an hour (the archive refreshes hourly, 24/7); earnings, dividend, split, and insider kinds refresh daily in the evening ET pipeline. Only genuinely new events fire — historical backfills never do.
- Delivery payloads use
event: "events.fired"(notwebhook.fired) with aneventsarray of{ ticker, ts, kind, payload }rows, the same shapesGET /v2/eventsserves — receivers handling both webhook types should branch on theeventfield.