> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vainona.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Read the events feed

> Every event your organization recorded in the last 30 days, in order, to poll instead of receiving webhooks or to catch up after an outage.

export const productName = "Vainona";

Every event {productName} records, from a [subscription](/concepts/subscriptions) entering or leaving, to a job finishing or judging pausing at a budget, goes into your organization's event log. [Webhooks](/guides/webhooks) push each one to your endpoints. The events feed, `GET /events`, reads the same log, oldest first in the order the events were recorded, for 30 days.

Use the feed when:

* **Your receiver can't accept inbound requests,** such as a batch job or a service behind a firewall. A subscription with no `endpoint` sends its events to the feed only.
* **Your receiver was down.** Read the feed from the last event you handled instead of waiting for retries.
* **You want the events in order.** Webhooks can arrive out of order; the feed can't.

<CodeGroup>
  ```ts TypeScript theme={null}
  for await (const event of db.events.iterate({ cursor: lastSeen, types: ["subscription.*"], namespacePrefix: "acme/prod/" })) {
    await handle(event);
    lastSeen = event.id;
  }
  ```

  ```python Python theme={null}
  for event in db.events.iterate(cursor=last_seen, types=["subscription.*"], namespace_prefix="acme/prod/"):
      handle(event)
      last_seen = event["id"]
  ```
</CodeGroup>

`iterate` follows `next_cursor` until a page comes back empty. Run it again later from the last event you handled to pick up what arrived since.

## Pages and cursors

```text theme={null}
GET /events?cursor=&limit=100&types=subscription.*,job.completed&namespace_prefix=acme/prod/
→ {"events": [...], "next_cursor": "..."}
```

* **Order.** Events come in the order they were recorded for your organization. An event is never visible before one recorded ahead of it, so a poller that resumes from its cursor misses nothing.
* **`next_cursor`** is on every page, even an empty one, so a poller resumes exactly where it stopped. Without a cursor the feed starts at the oldest event it keeps.
* **An event's `id` is a cursor too.** Resume after the last event you handled, however it reached you: a webhook's `webhook-id` works.
* **`limit`** is 1 to 1,000 events a page, 100 by default.
* **Expired cursors.** A cursor or event older than 30 days fails with `invalid_request` and `details.reason: "cursor_expired"`. Re-read the current state, for a subscription with its query, then start again without a cursor.

## Filters

* **`types`** takes event types and patterns, comma-separated: `subscription.*,job.completed`.
* **`namespace_prefix`** keeps the events of namespaces whose name starts with it, such as `acme/prod/`.
* **Your key's scope** always applies: a key scoped to a prefix or a namespace reads only the events of namespaces inside it.
* **Test sends are never in the feed.** They go to the endpoint you tested and its delivery log.

A filter never slows the cursor down: a page reads past the events it leaves out, so a narrow filter still moves `next_cursor` forward on every page.

## One event and its deliveries

`GET /events/{id}` returns an event with its deliveries to the endpoints your key can see: each delivery's status, attempts, and its last attempt's status code, latency and error. `POST /events/{id}/redeliver` with an `endpoint` sends it again, with the same `webhook-id` (see [retries](/guides/webhooks#retries)).

## Event types

| Type | Sent when |
| - | - |
| `subscription.entered` | A document starts matching a subscription's filter. |
| `subscription.exited` | A document stops matching, or is deleted. |
| `subscription.synced` | A subscription's membership changed silently: its first evaluation in a namespace, a backfill, or a threshold or weights change. Re-read its members. |
| `job.awaiting_confirm` | A job waits for your confirmation: a fan-out job, or a shadow report ready to review. |
| `job.completed`, `job.failed` | A job finished, such as a backfill, an export, a namespace delete or a reference index build. |
| `namespace.budget_paused`, `namespace.budget_resumed` | Judging in a namespace paused at its budget, or at quickstart's limit, and resumed. |
| `webhook.test` | A test send, to one endpoint only. Never in the feed. |

New types may be added, so ignore the ones you don't know. Each type's payload is in the API reference, and the SDKs type every event by its `type` (see [SDKs](/sdks#verifying-webhooks)).

In the dashboard, **Events** shows the feed, filtered by type and namespace prefix, and opens each event's JSON and its deliveries.
