# GET /v2/events

**All events**

The unified cross-ticker event stream — "all splits this month", "every analyst action in my universe this week" — one call instead of one per ticker. The default stream is the four corporate kinds, each backed by its own archive: [`dividend`](/docs/endpoints/events/dividends), [`split`](/docs/endpoints/events/splits), [`insider`](/docs/endpoints/events/insider), [`analyst`](/docs/endpoints/events/analyst). Two more kinds join the timeline as **explicit opt-ins** (name them in `kind` to include them): [`signal`](/docs/endpoints/events/signal-firings) — boolean-flag firings as enter/exit point-events — and `news` — headline events mirroring [`/v2/news`](/docs/endpoints/news/query). 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` (analyst — see [Analyst actions](/docs/endpoints/events/analyst)), so consumers can switch scope without reshaping.

Those two routes 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.

**`join=state` (paid plans)** widens the grammar to ticker-STATE columns, evaluated against each event's ticker **as of the event's timestamp** — point-in-time replay. "Downgrades on stocks above their 200-day" is one call: `kind=analyst&join=state&q=payload->>'action'='downgrades' AND above_sma_200 = true`. State resolves at daily resolution — the response's `query` echo carries `join: "state"` and `state_resolution: "1d"`; works in row and aggregate mode; gated Hobby and above (`403 plan_required` on Free).

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. `kind=signal` is **filter-mode only**: `q`, aggregates, and `join=state` over the signal log are refused with a 400 — scope with the filter params and filter client-side, or use [signal spans](/docs/endpoints/signals/events) / [`transitions_only`](/docs/endpoints/series/get). 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` too long to ride inside the cursor token sets `q_truncated: true` on the response — resend `q` alongside `cursor` on later pages.

## Plan access

- **Plan access.** Reads available on every plan. The one gate: `join=state` (point-in-time ticker state per event) is paid plans — Hobby and above; Free gets `403 plan_required`.
- **Rate limit.** Free 60/min · Hobby 600/min · Pro 6,000/min · Scale 60,000/min.
- **Per-call cap.** 1000 rows per call on every plan. Corporate kinds reach years back; analyst history to 2012.

## Query / path parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `kind` | query | string | no | Comma list of kinds to include. Omitted → the four corporate kinds; `signal` and `news` join only when named here. Enum: `dividend`, `split`, `insider`, `analyst`, `signal`, `news`. Example: `split,analyst`. |
| `ticker` | query | string | no | Single-ticker filter. When both `ticker` and `tickers` are passed, `ticker` wins. Example: `AAPL`. |
| `tickers` | query | string | no | Comma list of tickers (max 50). Mutually exclusive with `universe`. Example: `AAPL,NVDA,TSLA`. |
| `universe` | query | string | no | Universe slug (`top_10`, `top_100`, or one of yours) to scope the stream. Mutually exclusive with `tickers`. |
| `since` | query | string | no | Events at/after this ISO date or datetime. Example: `2026-07-01`. |
| `until` | query | string | no | Events strictly before this ISO date or datetime. |
| `q` | query | string | no | SQL WHERE over the projection — only `ticker`, `ts`, `kind`, `payload` may appear (plus ticker-state columns when `join=state`). Max 4000 chars. ANDs with the filter params. Example: `kind='analyst' AND payload->>'action'='downgrades'`. |
| `join` | query | string | no | Set to `state` to allow ticker-state columns in `q`/`select`/`group_by`/`having`, evaluated as of each event's timestamp (daily resolution). Paid plans (Hobby and above). Enum: `state`. |
| `select` | query | string | no | Aggregate-mode output columns (requires `group_by`). Default: group keys + `COUNT(*) AS events`. |
| `group_by` | query | string | no | Comma list of rollup keys — switches the response to aggregate rows. Example: `payload->>'firm' AS firm`. |
| `having` | query | string | no | Post-aggregation filter. Requires `group_by`. Example: `COUNT(*) > 5`. |
| `order` | query | string | no | Aggregate-mode sort column or alias. Default: `events`. (Row mode is always newest-first.) |
| `dir` | query | string | no | Aggregate-mode sort direction. Enum: `asc`, `desc`. Default: `desc`. |
| `limit` | query | integer | no | Page size (row modes) / max rollup rows (aggregate mode). Max 1000. Default: `50`. |
| `cursor` | query | string | no | Opaque cursor from the previous response — carries the original filters (and `q` when short), so pass it alone. Not valid with `group_by`. |

## Status codes

- **200** — Envelope with `query`, `count`, `next_cursor` (plus `q_truncated: true` when an oversized `q` could not ride the cursor), and `results` of `{ ticker, ts, kind, payload }` (row modes) or rollup rows plus `truncated: true` when the aggregate exceeds `limit`.
- **400** — Bad `kind`, >50 tickers, `tickers`+`universe` together, no bound at all, `kind=signal` with `q`/`group_by`/`join=state` (filter mode only), invalid timestamps/cursor, or `invalid_query` — an identifier outside the projection (or outside the widened set under `join=state`), a disallowed function, `select`/`having`/`order` without `group_by`, or `cursor` with `group_by`.
- **403** — `plan_required` — `join=state` on the Free plan.
- **404** — Referenced `universe` does not exist.
- **503** — `kind_unavailable` — the `signal` event log is temporarily unavailable; retry later. The other kinds are unaffected.

## Sample response

```json
{
  "as_of": "2026-07-27T15:58:12.000Z",
  "query": { "kind": "split,analyst", "tickers": null, "universe": "top_100", "since": "2026-07-01T00:00:00.000Z", "until": null, "limit": 50 },
  "count": 3,
  "next_cursor": null,
  "results": [
    { "ticker": "AAPL", "ts": "2026-07-26T14:30:00.000Z", "kind": "analyst",
      "payload": { "event_id": "ev_9f2", "firm": "Morgan Stanley", "analyst": "K. Huberty", "action": "downgrades", "rating": "Equal-Weight", "previous_rating": "Overweight", "price_target": 210, "previous_price_target": 250, "price_target_action": "lowers", "importance": 3 } },
    { "ticker": "NVDA", "ts": "2026-07-22T00:00:00.000Z", "kind": "split",
      "payload": { "split_from": 1, "split_to": 10, "ratio": 10 } },
    "(...)"
  ]
}
```

## Examples

### Splits and analyst actions across the top 100, this month

Request:

```shell
curl "https://api.tickerbot.io/v2/events?universe=top_100&kind=split,analyst&since=2026-07-01" \
  -H "Authorization: Bearer YOUR_KEY"
```

Response (`200`):

```json
{
  "as_of": "2026-07-27T15:58:12.000Z",
  "query": { "kind": "split,analyst", "tickers": null, "universe": "top_100", "since": "2026-07-01T00:00:00.000Z", "until": null, "limit": 50 },
  "count": 3,
  "next_cursor": null,
  "results": [
    { "ticker": "AAPL", "ts": "2026-07-26T14:30:00.000Z", "kind": "analyst",
      "payload": { "event_id": "ev_9f2", "firm": "Morgan Stanley", "analyst": "K. Huberty", "action": "downgrades", "rating": "Equal-Weight", "previous_rating": "Overweight", "price_target": 210, "previous_price_target": 250, "price_target_action": "lowers", "importance": 3 } },
    { "ticker": "NVDA", "ts": "2026-07-22T00:00:00.000Z", "kind": "split",
      "payload": { "split_from": 1, "split_to": 10, "ratio": 10 } },
    "(...)"
  ]
}
```

### Downgrade volume by firm, this month (aggregate mode)

Request:

```shell
curl -G "https://api.tickerbot.io/v2/events" \
  -H "Authorization: Bearer YOUR_KEY" \
  --data-urlencode "kind=analyst" \
  --data-urlencode "since=2026-07-01" \
  --data-urlencode "q=payload->>'action'='downgrades'" \
  --data-urlencode "group_by=payload->>'firm' AS firm" \
  --data-urlencode "having=COUNT(*) > 5"
```

Response (`200`):

```json
{
  "as_of": "2026-07-28T13:05:00.000Z",
  "query": { "kind": "analyst", "since": "2026-07-01T00:00:00.000Z", "q": "payload->>'action'='downgrades'", "group_by": ["payload->>'firm' AS firm"], "having": "COUNT(*) > 5", "order": "events", "dir": "desc", "limit": 50 },
  "count": 2,
  "results": [
    { "firm": "Morgan Stanley", "events": 14 },
    { "firm": "Goldman Sachs", "events": 9 }
  ]
}
```

### join=state: downgrades on stocks above their 200-day (point-in-time)

Request:

```shell
curl -G "https://api.tickerbot.io/v2/events" \
  -H "Authorization: Bearer YOUR_KEY" \
  --data-urlencode "kind=analyst" \
  --data-urlencode "join=state" \
  --data-urlencode "since=2026-07-01" \
  --data-urlencode "q=payload->>'action'='downgrades' AND above_sma_200 = true"
```

Response (`200`):

```json
{
  "as_of": "2026-07-29T21:12:40.000Z",
  "query": { "kind": "analyst", "since": "2026-07-01T00:00:00.000Z", "q": "payload->>'action'='downgrades' AND above_sma_200 = true", "join": "state", "state_resolution": "1d", "limit": 50 },
  "count": 50,
  "next_cursor": "eyJmIjp7ImtpbmQiOiJhbmFseXN0In19",
  "results": [
    { "ticker": "CZR", "ts": "2026-07-29T12:04:00.000Z", "kind": "analyst",
      "payload": { "firm": "TD Cowen", "action": "downgrades", "rating": "Hold", "previous_rating": "Buy", "price_target": 32, "previous_price_target": 51 } },
    "(...)"
  ]
}
```

---

Interactive sandbox + parameter editor: https://tickerbot.io/docs/endpoints/events/all
