# List recent events

Source: https://langbot.ai/docs/api/live-events/list-recent-events

`GET /v1/events/recent`

Recent feed events (phrase hits and lifecycle events) newest first, the REST way to backfill a stream gap.

**Auth.** None. Without a token the call is served as Free (the Free delay and request budget, shared per IP); send `Authorization: Bearer lb_…` for your plan's.

**Limits.** Counts against your plan's API requests (60, 600 or 3,000 a minute on Free, Builder and Standard). Served at your plan's delay (+60 s Free, +10 s Builder, +2 s Standard).

## Parameters

### Query parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `event_id` | string | no | One event (`ev_…`). |
| `phrases` | string | no | Comma-separated phrase keys. |
| `types` | string | no | Comma-separated event types; default everything but `transcript_delta`. |
| `source_id` | string | no | One source. |
| `since` | integer | no | ms epoch; default 24 hours ago. |
| `until` | integer | no | ms epoch, exclusive. |
| `cursor` | string | no | `next_cursor` from the previous page; send the same filters. |
| `limit` | integer | no | Page size. 1 to 1000. Default `100`. |
| `subjects` | string | no | Comma-separated typed-fact subjects (`fact_extracted`). |
| `context` | string | no | Comma-separated context kinds to include: `on_air`, `topic`, `near_miss` or `all`. |

## Request

**curl**

```bash
curl "https://api.langbot.ai/v1/events/recent?event_id=ev_kxexamplemention_26nov01&types=phrase_detected&limit=1"
```

**Python**

```python
from langbot import LangbotClient

async with LangbotClient() as lb:
    page = await lb.recent_events_page("ev_kxexamplemention_26nov01", types=["phrase_detected"], limit=1)
    for evt in page.events:
        print(evt.phrase, evt.t_spoken, evt.verdict)
```

**TypeScript**

```ts
import { LangbotClient } from "@langbotai/sdk";

const lb = new LangbotClient();
const page = await lb.recentEventsPage({ eventId: "ev_kxexamplemention_26nov01", types: ["phrase_detected"], limit: 1 });
console.log(page.events, page.nextCursor);
```

## Response

`200 OK`

```json
{
  "ts": 1793566860000,
  "since": 1793566800000,
  "until": null,
  "delay_ms": 60000,
  "rights": "public_domain",
  "next_cursor": "cjoxNzkzNTY2ODA4MDAwOmV2dF8wMU02…",
  "events": [
    {
      "id": "evt_01M6CQ02PR3SVZ3TV7FCXH7E09",
      "type": "phrase_detected",
      "source_id": "src_example_public",
      "event_id": "ev_kxexamplemention_26nov01",
      "market_refs": ["KXEXAMPLEMENTION-26NOV01-TARI"],
      "phrase": "tariff",
      "raw": "we will talk about tariff today",
      "speaker": { "label": "SPK_1", "name": "Example Speaker", "confidence": 0.9 },
      "confidence": 0.93,
      "t_spoken": 1793566809000,
      "t_detected": 1793566809070,
      "t_emitted": 1793566809076,
      "lag_vs_public_ms": null,
      "source_kind": "hls",
      "seq": 9,
      "hash": "aaaa…",
      "prev_hash": "bbbb…",
      "raw_hash": "cccc…",
      "chain_seq": 10,
      "class": "fact",
      "verdict": { "counts": true, "reason": "mention 1 (1 needed)", "role": null }
    }
  ]
}
```

Pages run newest first: pass `next_cursor` back as `cursor` for the next, older page. On a `restricted` source `raw` is the matched phrase only. `verdict` is Langbot's reading of the market's rules, not a settlement. Every field: [Live events](https://langbot.ai/docs/live-events#the-event).

## Errors

| Status | `code` | When |
|---|---|---|
| 401 | `token_invalid` | A token was sent and not recognised. Send a valid one, or none to call anonymously. |
| 422 | `validation_error` | A parameter failed validation; `detail[].loc` names it. |
| 429 | `rate_limited` | Over your request budget; wait `Retry-After` seconds. |

Every error body is `{"detail": …, "code": "…"}`; branch on `code`. All codes: [Errors](https://langbot.ai/docs/api#errors).
