---
title: "stream_job_events"
method: GET
path: "/v1/jobs/{job_id}/events"
tags: ["operations"]
---

# stream_job_events

`GET /v1/jobs/{job_id}/events`

## Request

- Base URL: `https://ndi-api.nace.ai`
- URL: `https://ndi-api.nace.ai/v1/jobs/{job_id}/events`
- Auth: API key in header `X-API-Key`
- TypeScript: <https://skmtc.dev/nace/apis/ndi-platform-api/docs/v1/jobs/:job_id/events/get.ts> (a function with typed inputs; its response is checked against the schema)

Stream job progress as Server-Sent Events. Cost class: fast.

Each frame is a :class:`~ndi_service.app.platform_api.results.JobEvent`
serialised as ``data: <json>\n\n`` with a monotonic ``id: <sequence>``.
Frames are emitted by polling the job row — the row is the event source,
so a frame appears whenever ``status`` or ``progress`` changes and the
stream closes once the job is terminal (or after the same ceiling as the
inline wait, for a job nothing is advancing).

**REST and CLI only.** MCP has no streaming shape; an MCP agent polls
``get_job`` instead.

``Last-Event-ID`` offsets the sequence numbering so a reconnecting client
keeps a monotonic ``id``; the current state is always re-emitted as the
first frame, because there is no event log to replay from.

## Path parameters

- `job_id` string, uuid, required: Job identifier.

## Headers

- `Last-Event-ID` string, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `504`: Gateway Timeout
- `default`: Typed error envelope used by every 4xx and 5xx. ``error.code`` distinguishes the failure; HTTP status is a consequence of the code.

---

[API](https://skmtc.dev/nace/apis/ndi-platform-api.md) - [All operations](https://skmtc.dev/nace/apis/ndi-platform-api/llms.txt) - [OpenAPI document](https://skmtc.dev/nace/apis/ndi-platform-api/revisions/d002a3589a67?raw)
