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

# Events

> List and stream a session's events, resumable by sequence.

Every [session](/docs/api/sessions) emits an ordered stream of **events**, each with a monotonically increasing `seq`. You can list past events or subscribe to a live Server-Sent Events (SSE) stream. Both are **resumable**: pass the last `seq` you handled to continue with no gaps or duplicates.

Event types use a `{domain}.{action}` naming scheme. For the full catalog across all phases, see [Events & streaming](/docs/concepts/events-and-streaming).

## The event object

<ResponseField name="id" type="string">Unique id (e.g. `evt_01H...`).</ResponseField>
<ResponseField name="seq" type="integer">Monotonic sequence number within the session — starts at 1, gap-free. Use it to resume. Mirrored as `last_seq` on the session and as the SSE `id:`.</ResponseField>
<ResponseField name="type" type="string">The `{domain}.{action}` type — see [below](#event-types).</ResponseField>
<ResponseField name="session_id" type="string">The session that emitted the event.</ResponseField>
<ResponseField name="data" type="object">Type-specific payload.</ResponseField>
<ResponseField name="created_at" type="string">Emission timestamp.</ResponseField>

## Event types

| Type                                                   | Data                                                                                                          | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `message.delta`                                        | `text`                                                                                                        | A chunk of assistant text.                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `message.completed`                                    | `text`, `tokens`                                                                                              | An assistant message finished.                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `tool.started`                                         | `name`, `args`                                                                                                | A tool call began.                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `tool.completed`                                       | `name`, `result`, `duration_ms`                                                                               | A tool call finished.                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `tool.confirm`                                         | `tool_call_id`, `name`, `args`                                                                                | A tool requires approval (`ask` [permission](/docs/api/agents)). Answer via [tool confirmations](/docs/api/sessions#respond-to-a-tool-confirmation).                                                                                                                                                                                                                                                                                                            |
| `tool.confirm.resolved`                                | `tool_call_id`, `decision`, `reason`, `scope`, `actor`, `decided_at`, `proposed_args`, `final_args`           | A person answered a `tool.confirm`. `decision` (`allow`/`deny`), `reason` and `scope` are what was sent to [tool confirmations](/docs/api/sessions#respond-to-a-tool-confirmation); `actor` is the user or key that sent it; `proposed_args` are the arguments the card showed (`final_args` is the same — arguments cannot be edited before approving). For a team member's call it is on the member's session. Listed only with `include_accepted=true`. |
| `session.running`                                      | —                                                                                                             | The agent started a turn.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `session.usage`                                        | `token_usage`, `consumed_micro_usd`, `active_seconds`, `tool_calls`                                           | Cumulative usage snapshot, emitted before every idle/terminal transition.                                                                                                                                                                                                                                                                                                                                                                             |
| `session.idle`                                         | `stop_reason`, `pending_actions?`, `structured_output`, `error?`                                              | A turn yielded control. Read `stop_reason` (see [session lifecycle](/docs/api/sessions#lifecycle)). `structured_output` is `null` unless an [output schema](/docs/capabilities/structured-outputs) was satisfied; `error` appears only when a required schema was not.                                                                                                                                                                                          |
| `budget.exceeded`                                      | `estimate_micro_usd`, `remaining_micro_usd`                                                                   | A call was refused because it would breach the cap.                                                                                                                                                                                                                                                                                                                                                                                                   |
| `media.job.queued`                                     | `job_id`, `kind`, `model`                                                                                     | A media job was submitted — by an agent's `generate_video` ([video](/docs/api/video)) or by `POST /v1/media/clips` ([clips](/docs/api/clips)); `kind` says which (`video` or `clip`; `model` is `null` for a clip) and `job_id` is its `med_`. A REST submit has no session, so it reaches [webhooks](/docs/api/webhooks) only.                                                                                                                                      |
| `media.job.completed`                                  | `job_id`, `kind`, `file_ids`, `cost_micro_usd`                                                                | The job's files are in [Files](/docs/api/files); the session has been woken with the first id and told the settled cost.                                                                                                                                                                                                                                                                                                                                   |
| `media.job.failed`                                     | `job_id`, `kind`, `code`                                                                                      | The job produced nothing and billed nothing; `code` is an [error code](/docs/api/errors).                                                                                                                                                                                                                                                                                                                                                                  |
| `file.imported`                                        | `file_id`, `url`                                                                                              | A [URL import](/docs/api/files#import-a-file-from-a-url) landed in [Files](/docs/api/files). A REST import has no session, so this reaches [webhooks](/docs/api/webhooks) only.                                                                                                                                                                                                                                                                                      |
| `app.db.migrated`                                      | `app_id`, `migration_id`, `name`                                                                              | A [migration](/docs/api/database#apply-a-migration) was applied to an app's database for the first time; a replay emits nothing. No session is involved, so this reaches [webhooks](/docs/api/webhooks) only.                                                                                                                                                                                                                                                   |
| `app.storage.bucket.created`                           | `app_id`, `bucket`                                                                                            | A [bucket](/docs/api/storage#buckets) was created on an app's object store. Webhooks only, like `app.db.migrated`; object reads and writes are [audit](/docs/api/audit-logs) rows, not events.                                                                                                                                                                                                                                                                  |
| `app.storage.bucket.deleted`                           | `app_id`, `bucket`                                                                                            | A bucket was deleted (`?force=true` empties it first). Webhooks only.                                                                                                                                                                                                                                                                                                                                                                                 |
| `browser.session.opened`                               | `browser_session_id`, `computer_id`, `region`                                                                 | The agent's `browser` tool opened its [browser](/docs/api/browser) on the session's computer — lazily, on the first action. A REST open has no session and is audit-logged instead.                                                                                                                                                                                                                                                                        |
| `browser.session.closed`                               | `browser_session_id`, `minutes`                                                                               | The browser closed and its minutes were settled on the `browser` line; the tool's browser closes when the session ends or pauses for input.                                                                                                                                                                                                                                                                                                           |
| `browser.context.saved`                                | `context_id`, `identity_id`                                                                                   | The `save_context` action marked a [saved login](/docs/api/browser#save-a-login) saved from the browser opened with it; the close persists the storage.                                                                                                                                                                                                                                                                                                    |
| `browser.context.granted`                              | `grant_id`, `context_id`, `grantee_type`, `grantee_id`                                                        | A saved login was shared with an agent or role over REST. No session, so [webhooks](/docs/api/webhooks) only.                                                                                                                                                                                                                                                                                                                                              |
| `browser.context.revoked`                              | `context_id`                                                                                                  | A saved login was deleted over REST, and every grant on it with it. Webhooks only.                                                                                                                                                                                                                                                                                                                                                                    |
| `wallet.created`                                       | `wallet_id`, `identity_id`, `network`, `address`                                                              | A [wallet](/docs/api/wallet) was provisioned for an identity on that network. Operator action over REST, so [webhooks](/docs/api/webhooks) only.                                                                                                                                                                                                                                                                                                                |
| `wallet.policy.updated`                                | `wallet_id`, `identity_id`, `policy`                                                                          | The per-tx or daily cap changed; the new policy is at the provider already. Webhooks only.                                                                                                                                                                                                                                                                                                                                                            |
| `wallet.transaction.confirmed`                         | `wallet_id`, `identity_id`, `transaction_id`, `kind`, `amount_micro_usd`, `counterparty`, `tx_hash`, `status` | A `fund`, `transfer` or `pay` settled on chain. A `pending` or `failed` transaction emits nothing. Never carries a key, a signature or a payment header.                                                                                                                                                                                                                                                                                              |
| `wallet.swept`                                         | `wallet_id`, `identity_id`, `transaction_id`, `amount_micro_usd`, `counterparty`, `tx_hash`, `status`         | The whole balance was drained and the wallet retired. Webhooks only.                                                                                                                                                                                                                                                                                                                                                                                  |
| `card.issued`                                          | `card_id`, `identity_id`, `status`, `load_micro_usd`, `brand`, `last4`                                        | A prepaid [card](/docs/api/cards) became `active` — on the buy, on a `retry`, or on the reconcile a read does. Never carries a credential.                                                                                                                                                                                                                                                                                                                 |
| `card.failed`                                          | `card_id`, `identity_id`, `status`, `load_micro_usd`, `reason`                                                | The issuer could not complete the order. The debit stays on the row so `retry` re-runs issuance; `refund` returns the credits.                                                                                                                                                                                                                                                                                                                        |
| `card.cancelled`                                       | `card_id`, `identity_id`, `status`, `load_micro_usd`                                                          | A card was marked cancelled. Local status only — a prepaid card cannot be voided at the issuer.                                                                                                                                                                                                                                                                                                                                                       |
| `card.refunded`                                        | `card_id`, `identity_id`, `status`, `load_micro_usd`, `price_micro_usd`                                       | The credits for a `pending_payment` or `failed` card went back to the balance.                                                                                                                                                                                                                                                                                                                                                                        |
| `card.credentials_revealed`                            | `card_id`, `identity_id`, `status`, `load_micro_usd`                                                          | Someone read the card's number/PIN. The event names the card, never the credential; the [audit](/docs/api/audit-logs) row names the caller.                                                                                                                                                                                                                                                                                                                |
| `thread.created` · `thread.idle` · `thread.terminated` | `thread_id`, …                                                                                                | A [team](/docs/team/delegation) coordinator's view of a delegated member session: spawned, result folded back, or failed to start. Payloads are on [Context and budgets](/docs/team/context-and-budgets). `thread.running` is in the enum but nothing emits it today.                                                                                                                                                                                           |

The `session.idle` `stop_reason` is one of `end_turn`, `awaiting_input`, `awaiting_approval`, `awaiting_answer`, `awaiting_delegation`, `budget_paused`, `interrupted`, `max_iterations`, `context_exhausted`, or `error` — the same enum as the [session object](/docs/api/sessions#lifecycle), which is where each one is explained.

Three of them park the turn on something outside the loop, and only two of those park it on a *person*: `awaiting_approval` and `awaiting_answer` both carry `pending_actions` and both wait for a reply, while `awaiting_delegation` waits for the coordinator's own children and no reply will move it.

## List events

`GET /v1/sessions/{id}/events` → `200 OK`. Past events in order (oldest-first). Resume by passing `after_seq`; combine with `limit` for paging. Events are replayable for at least 72 hours.

<ParamField query="after_seq" type="integer">Return events with `seq` **strictly greater** than this. Omit to start from the beginning.</ParamField>
<ParamField query="limit" type="integer">Max events to return. Default `20`, max `100`.</ParamField>
<ParamField query="include_accepted" type="boolean">Include the types this release added — `message.accepted` (a message the session has accepted and not yet answered), `handoff.sent` (a person's fan-out, recorded on the sender's log) and `tool.confirm.resolved` (a person's decision on a held tool call). Off by default, so clients published before those types existed keep reading the page; the live stream sends them either way. It changes only which rows are in `data`: `has_more` and `next_cursor` are the page's own, so nothing is skipped by leaving it off.</ParamField>

```bash theme={"system"}
curl -fsSL "https://api.vetta.sh/v1/sessions/ses_01H9AB.../events?after_seq=140&limit=50" \
  -H "authorization: Bearer sk_live_..."
```

<ResponseExample>
  ```json Response theme={"system"}
  {
    "data": [
      { "id": "evt_01H9II...", "seq": 141, "type": "session.running", "session_id": "ses_01H9AB...", "data": {}, "created_at": "2026-08-20T17:05:01Z" },
      { "id": "evt_01H9IJ...", "seq": 142, "type": "message.delta", "session_id": "ses_01H9AB...", "data": { "text": "Looking up order #4821…" }, "created_at": "2026-08-20T17:05:01Z" },
      { "id": "evt_01H9IK...", "seq": 143, "type": "session.idle", "session_id": "ses_01H9AB...", "data": { "stop_reason": "end_turn" }, "created_at": "2026-08-20T17:05:04Z" }
    ],
    "has_more": false,
    "next_cursor": null
  }
  ```
</ResponseExample>

## Stream events (SSE)

`GET /v1/sessions/{id}/stream?after_seq={seq}` opens a Server-Sent Events stream. Each SSE message carries one event as JSON in its `data:` field, with the event `seq` as the SSE `id:`. On reconnect, pass the last `seq` you saw as `after_seq` to replay everything since.

```bash theme={"system"}
curl -N "https://api.vetta.sh/v1/sessions/ses_01H9AB.../stream?after_seq=140" \
  -H "authorization: Bearer sk_live_..." \
  -H "accept: text/event-stream"
```

```text Stream theme={"system"}
id: 141
data: {"seq":141,"type":"session.running","data":{}}

id: 142
data: {"seq":142,"type":"message.delta","data":{"text":"Looking up order #4821…"}}

id: 143
data: {"seq":143,"type":"session.idle","data":{"stop_reason":"end_turn"}}
```

<Note>
  Track the highest `seq` you have fully processed. After any disconnect, reconnect with `?after_seq=<that seq>` — the stream is gap-free and duplicate-free from that point.
</Note>

<Info>
  `tool.confirm` pauses the turn (`stop_reason: "awaiting_approval"`) until you resolve it via [`POST /v1/sessions/{id}/tool_confirmations`](/docs/api/sessions#respond-to-a-tool-confirmation). `budget.exceeded` accompanies a `session.idle` with `stop_reason` `budget_paused`.

  **A question emits no event of its own.** An agent that calls `ask_operator` parks the same way, and the only signal on the stream is the `session.idle` — `stop_reason: "awaiting_answer"`, with the question in `pending_actions`. Answer it via [`POST /v1/sessions/{id}/answers`](/docs/api/sessions#answer-a-question). A stream reader that branches only on `tool.confirm` will sit on a session that is waiting for it.
</Info>
