---
title: "List run events"
method: GET
path: "/runs/{id}/events"
tags: ["Runs"]
---

# List run events

`GET /runs/{id}/events`

## Request

- Base URL: `https://api.edgaze.ai/v1`
- URL: `https://api.edgaze.ai/v1/runs/{id}/events`
- Auth: HTTP bearer

Return an ordered, bounded page of durable run lifecycle events. Continue from `nextAfterSequence` while `hasMore` is true. Each event carries a `data` object with the content for its type — most importantly `data.text` on `node.output.delta`, which you concatenate in `sequence` order to reconstruct a node's streamed output. Rate limiting: reads are not metered per-key today — only POST /runs is (60/minute). Reads may become metered without a breaking change, so treat 429 with `Retry-After` as possible on any endpoint and back off rather than polling in a tight loop. For run progress prefer GET /runs/{id}/stream, or poll GET /runs/{id} no more than once per second.

## Path parameters

- `id` string, required: UUID returned from POST /runs.

## Query parameters

- `afterSequence` integer
- `limit` integer

## Response `200`

Ordered page of events.

- RunEventsPage: Response body for GET /runs/{id}/events.
  - `id` string, uuid, required
  - `events` RunEvent[], required
    - `type` union, required: Event name. The listed values are every type emitted today; branch on them. The union stays open to plain strings on purpose, because adding an event type is not a breaking change: ignore values you do not recognize instead of failing.
      - 'run.queued' | 'run.queue_position' | 'run.preparing' | 'run.started' | 'run.suspended' | 'run.resumed' | 'run.completed' | 'run.failed' | 'run.cancelled' | 'node.started' | 'node.output.delta' | 'node.completed' | 'node.failed' | 'node.retry_scheduled' | 'node.skipped'
      - string
    - `sequence` integer, required: Monotonic, gap-free position in this run's log. Use as the `afterSequence` cursor and to order events.
    - `ts` string, date-time, required
    - `nodeId` string, nullable, required: Workflow node this event belongs to, or `null` for run-level events.
    - `attempt` integer, nullable, required: 1-based execution attempt for node events; `null` for run-level events.
    - `data` RunEventData, required: Event-specific content, projected to the fields that are safe for the caller.
      - `text` string: Incremental output text. Present on `node.output.delta`; concatenate in `sequence` order to reconstruct a node's streamed output.
      - `status` 'pending' | 'running' | 'suspended' | 'completed' | 'failed' | 'cancelled': Canonical run status exposed by the public API.
      - `reason` string, nullable: Why the run failed, suspended, or a node was skipped. Sanitized to the same buyer-safe text as `Run.reason`.
      - `queue` RunQueue: Edgaze starts runs immediately while it has capacity. At full capacity a run waits in line and starts automatically, in order; nothing is needed from the caller and nothing is charged for waiting. A run that waits past its limit fails with a reason and is not charged.
        - `state` 'waiting' | 'starting', required: `waiting`: in line for capacity. `starting`: it just left the line and is being started.
        - `position` integer, required: Place in line, 1 = next. 0 while starting.
        - `etaSeconds` integer, nullable, required: Estimated seconds until it starts, or null when unknown.
  - `hasMore` boolean, required
  - `nextAfterSequence` integer, nullable, required: Pass as `afterSequence` to fetch the next page. `null` when `hasMore` is false.

## Other responses

- `400`: Invalid pagination cursor.
- `401`: Invalid or missing API key.
- `403`: API key is missing the required scope.
- `404`: Run not found.
- `500`: Unexpected server error.

---

[API](https://skmtc.dev/edgaze/apis/edgaze-api.md) · [All operations](https://skmtc.dev/edgaze/apis/edgaze-api/llms.txt) · [OpenAPI document](https://skmtc.dev/edgaze/apis/edgaze-api/revisions/cfc6436d2f90?raw)
