# GET /v2/events?kind=analyst

**Analyst actions**

Upgrades, downgrades, initiations, and price-target changes — the freshest kind on the stream.

## Query / path parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `kind` | query | string | yes | Fix to `analyst` for this view (comma-combine kinds to merge timelines). Example: `analyst`. |
| `ticker` | query | string | no | Single symbol. Beats `tickers` when both are passed. Example: `AAPL`. |
| `tickers` | query | string[] | no | Comma-separated symbols, up to 50. Not combinable with `universe`; `ticker` wins when both are passed. Example: `AAPL,MSFT`. |
| `universe` | query | string | no | System or caller-owned universe slug. Example: `top_100`. |
| `firm` | query | string | no | Structured filter: exact firm-name match on the ratings feed. ANDs with `q`. Example: `Morgan Stanley`. |
| `action` | query | string | no | Structured filter over the action vocabulary (`upgrades`, `downgrades`, `initiates_coverage_on`, `maintains`, `reiterates`, `assumes`, `reinstates`, `suspends`, `terminates_coverage_on`). Enum: `upgrades`, `downgrades`, `initiates_coverage_on`, `maintains`, `reiterates`, `assumes`, `reinstates`, `suspends`, `terminates_coverage_on`. Example: `downgrades`. |
| `from` | query | string | no | `YYYY-MM-DD` or ISO timestamp (inclusive). `since` is accepted as an alias. Example: `2026-09-14`. |
| `to` | query | string | no | `YYYY-MM-DD` or ISO timestamp — a bare `YYYY-MM-DD` means through the end of that day; timestamps are exclusive. `until` is accepted as an alias. Example: `2026-06-28`. |
| `q` | query | string | no | SQL filter. This kind's payload fields are first-class typed columns here: `firm`, `analyst`, `action`, `rating`, `previous_rating`, `price_target_action` (text), `price_target`, `previous_price_target`, `importance` (numeric) — e.g. `firm = 'Goldman Sachs' AND price_target > previous_price_target`. `payload->>'…'` works too. Base columns: `ticker`, `ts`, `kind`, `payload`. Example: `action = 'downgrades'`. |
| `join` | query | string | no | `state` widens `q` to ticker-state signals evaluated as of each event's timestamp. Never gated. Enum: `state`. |
| `interval` | query | string | no | 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`. Enum: `1m`, `1h`, `1d`, `auto`. Default: `auto`. |
| `limit` | query | integer | no | Rows per page. Max 1000. Default: `50`. Example: `5`. |
| `cursor` | query | string | no | Opaque cursor from the previous response. |

## Returns

- `as_of` (string) — Server time this response was assembled (ISO 8601).
- `query` (object) — Your filters, echoed.
- `count` (number) — Rows in this page.
- `next_cursor` (string) — Opaque token for the next page; `null` on the last page. Pass it back as `cursor`.
- `results` (array) — One row per event, newest first.
  - `ticker` (string) — Symbol the action targets.
  - `ts` (string) — When the action landed (timestamp-grained).
  - `kind` (string) — Always `analyst` on this view.
  - `payload` (object) — The action.
    - `event_id` (string) — Stable id for the action.
    - `firm` (string) — Research firm.
    - `analyst` (string, optional) — Analyst name, where attributed.
    - `action` (string) — `upgrades`, `downgrades`, `maintains`, `reiterates`, `initiates_coverage_on`, `assumes`, `reinstates`, `terminates_coverage_on`, `suspends`.
    - `rating` (string, optional) — New rating label; `previous_rating` carries the prior one.
    - `price_target` (number, optional) — New target (USD); `previous_price_target` carries the prior one.
    - `price_target_action` (string, optional) — How the target moved (`raises`, `lowers`, …).
    - `importance` (number, optional) — Vendor-assigned salience, 0–5.

## Sample response

```json
{
  "as_of": "2026-07-30T18:20:11.000Z",
  "query": { "kind": "analyst", "since": "2026-07-01T00:00:00.000Z", "limit": 50 },
  "count": 1,
  "next_cursor": null,
  "results": [
    { "ticker": "CZR", "ts": "2026-07-29T13:41:02.000Z", "kind": "analyst",
      "payload": { "event_id": "bz-8841207", "firm": "Goldman Sachs", "action": "downgrades",
                   "rating": "Neutral", "previous_rating": "Buy",
                   "price_target": 38, "previous_price_target": 51,
                   "price_target_action": "lowers", "importance": 4 } }
  ]
}
```

## More examples

### Downgrades on stocks above their 200-day (join=state)

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 "from=2026-08-17" \
  --data-urlencode "q=payload->>'action'='downgrades' AND above_sma_200 = true"
```

Response (`200`):

```json
// Same envelope; query echo carries join: "state" and state_resolution: "1d".
```

## Notes

- This is [`GET /v2/events`](/docs/endpoints/events/query) with `kind=analyst`; it has its own page because the payload is its own contract. The full query grammar lives there and applies here unchanged, including `join=state`, which evaluates ticker-state signals as of each event's timestamp.
- A rating change lands within the hour, 24/7, with history back to 2012.
- The legacy specialized route `GET /v2/analyst/events` returns the same payloads with firm/action as plain params. It is deprecated with a 2026-10-31 sunset and this view is its successor; it is no longer listed in the OpenAPI spec or the endpoint index; responses are unchanged and carry `Deprecation`/`Sunset` headers until then.
- The [ticker object](/docs/schema) carries live analyst signals (`last_rating_date` / `last_rating_firm` / `last_rating_action`) and `recent_*` booleans for scans.
- To be pushed instead of polling, create an event-trigger webhook: [`POST /v2/webhooks`](/docs/endpoints/webhooks/create) with `trigger.kinds=analyst`.

---

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