List events
https://api.tickerbot.io/v2/eventsThe unified cross-ticker event stream — "all splits this month", "every analyst action in my universe this week" — one call instead of one per ticker. Four kinds, each backed by its own archive: dividend, split, insider, analyst. Rows are { ticker, ts, kind, payload }, newest first; payload fields per kind are identical to [/v2/tickers/{ticker}/events](/docs/endpoints/tickers/events) (corporate kinds) and [/v2/analyst/events](/docs/endpoints/analyst/events) (analyst), so consumers can switch scope without reshaping.
Those two endpoints remain as the single-ticker and analyst-specialized (firm/action filters) views of the same data.
The endpoint speaks the SQL grammar over a normalized projection of exactly four columns — ticker, ts, kind, and payload (jsonb). Optional q filters rows (kind='analyst' AND payload->>'action'='downgrades'); group_by (with optional select/having) switches to aggregate rollups (group_by=payload->>'firm' AS firm). Payload fields are reached with jsonb operators and cast as needed: (payload->>'shares')::numeric > 1e6. No other identifiers are accepted — this is the event log's own grammar, not the ticker-state scan grammar. Aggregates don't paginate: past limit you get truncated: true — narrow the window instead.
Requires at least one bound — a ticker scope or a time window (q alone does not count); a bare kind over millions of rows is refused. Both GET and POST are supported; POST takes the same parameters in the body for long queries. Pagination note: the cursor pages strictly *older* than the last row's timestamp, and the corporate archives are date-grained — same-date remainders can fall on a page boundary. Raise limit (max 1000) to avoid boundaries. A q longer than 600 chars is not carried inside the cursor — resend q alongside cursor on later pages.
Plan access
Available on every plan, alongside the live `last_rating_date` / `last_rating_firm` / `last_rating_action` columns on the ticker object and the `recent_*` analyst flags on /v2/scan.
Rate limit
Hobby 600/min · Pro 6,000/min · Scale 60,000/min.
Per-call cap
1000 rows per call on every plan. History back to 2012.
Query parameters
stringComma list of kinds to include.
stringSingle-ticker filter.
stringComma list of tickers (max 50). Mutually exclusive with `universe`.
stringUniverse slug (`top_10`, `top_100`, or one of yours) to scope the stream. Mutually exclusive with `tickers`.
stringEvents at/after this ISO date or datetime.
stringEvents strictly before this ISO date or datetime.
stringSQL WHERE over the projection — only `ticker`, `ts`, `kind`, `payload` may appear. Max 4000 chars. ANDs with the filter params. See the schema for columns + flags you can compose.
stringAggregate-mode output columns (requires `group_by`). Default: group keys + `COUNT(*) AS events`.
stringComma list of rollup keys — switches the response to aggregate rows.
stringPost-aggregation filter. Requires `group_by`.
stringAggregate-mode sort column or alias. Default: `events`. (Row mode is always newest-first.)
stringdefault descAggregate-mode sort direction.
integerdefault 50Page size (row modes) / max rollup rows (aggregate mode). Max 1000.
stringOpaque cursor from the previous response — carries the original filters (and `q` when short), so pass it alone. Not valid with `group_by`.
Status codes
200query, count, next_cursor, and results of { ticker, ts, kind, payload } (row modes) or rollup rows plus truncated: true when the aggregate exceeds limit.400kind, >50 tickers, tickers+universe together, no bound at all, invalid timestamps/cursor, or invalid_query — an identifier outside the four projection columns, a disallowed function, select/having/order without group_by, or cursor with group_by.404universe does not exist.