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

# Reporter events

> Subscribe to Reporter's report and deadline events: the streaming manifest operation, the CloudEvents envelope, delivery policies, and what each payload carries.

Reporter publishes a business event whenever a template, a report, or a deadline changes state. Subscribe to those events and you learn that a report finished without polling `GET /v1/reports/{id}` for it.

`GET /v1/streaming/events` describes the contract in machine-readable form. This page covers the consumer side: what the manifest tells you, what arrives on the wire, and what each event carries.

## The manifest operation

***

[Streaming events](/en/reference/products/reporter/get-streaming-events) returns the static event catalog. It requires authentication like every other operation. It answers `Cache-Control: no-store`, and it responds whether or not this deployment publishes events. Read it at startup to check that your consumer and Reporter agree on the contract.

The response exposes the application identity and catalog:

| Field       | What it carries                                                                                                                                                                            |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `version`   | Semantic version of the manifest wire format.                                                                                                                                              |
| `publisher` | Who publishes: `serviceName` and `source` are `reporter`, `routePath` is this operation, and `outboxSupported` is `true`, plus the application and library versions.                       |
| `events`    | One entry per event definition, with its key, `eventKey`, resource type, event type, `class`, schema version, description, and default delivery policy. Reporter emits only `fact` events. |
| `routes`    | Omitted. Reporter does not publish broker topology through the API.                                                                                                                        |

## Broker routing

***

The manifest does not disclose a topic or broker topology. Bind your queue to the exchange named by `RABBITMQ_REPORT_EVENTS_EXCHANGE`. Each message uses the event definition key verbatim as its AMQP routing key: `report.finished`, `deadline.delivery_reverted`, underscores included.

## The event catalog

***

Twelve event definitions exist across the two run modes.

| Event                        | Emitted when                                                      | Delivery profile |
| ---------------------------- | ----------------------------------------------------------------- | ---------------- |
| `template.created`           | A template is uploaded.                                           | Important        |
| `template.updated`           | A template's file or metadata changes.                            | Important        |
| `template.deleted`           | A template is removed, with the count of deadlines that cascaded. | Important        |
| `report.requested`           | A report request is accepted and queued.                          | Important        |
| `report.finished`            | Every data section succeeded and the artifact is stored.          | Critical         |
| `report.partial`             | Some sections failed. An artifact exists.                         | Critical         |
| `report.errored`             | The report ended in error.                                        | Critical         |
| `deadline.created`           | A deadline is created.                                            | Important        |
| `deadline.updated`           | A deadline changes.                                               | Important        |
| `deadline.deleted`           | A deadline is removed.                                            | Important        |
| `deadline.delivered`         | A deadline is marked delivered.                                   | Critical         |
| `deadline.delivery_reverted` | A delivery mark is cleared.                                       | Critical         |

This channel is publish-only. Reporter emits these events and consumes none of them.

## Delivery

***

Every manifest event has class `fact`. The delivery profile in the table above selects its delivery policy.

| Delivery profile | Direct publish | Outbox                                          | Route DLQ      |
| ---------------- | -------------- | ----------------------------------------------- | -------------- |
| Important        | Yes            | Falls back to the outbox when the circuit opens | Not configured |
| Critical         | No             | Always                                          | Not configured |

An event with the `Critical` delivery profile therefore never publishes straight to the broker. Reporter writes it to the durable Mongo streaming outbox after the business-state commit, and a dispatcher replays it after a broker outage.

The state write and outbox insert are separate operations, not one atomic application transaction. That gap is a failure window: a crash or a failed outbox insert after the state commit loses the event. No reconciliation recovers it. The loss leaves only an error log and a metric. Once the row is in the outbox, the dispatcher retries until delivery.

The policy requests dead-letter handling for routable failures, but the current RabbitMQ routes do not provide an explicit DLQ destination. Such a failure is surfaced and logged, with no forensic dead-letter copy.

Emission happens after the commit and never fails the work. A publication problem does not turn a stored report into an errored one.

<Warning>
  Delivery is at-least-once. Deduplicate on `(ce-source, ce-id)`. Only terminal report facts (`report.finished`, `report.partial`, and `report.errored`) and the critical deadline transitions (`deadline.delivered` and `deadline.delivery_reverted`) use deterministic identifiers. Template events, `report.requested`, and deadline create/update/delete events leave the identifier to `lib-streaming`.
</Warning>

## The CloudEvents envelope

***

Messages travel in CloudEvents binary mode, version 1.0. Context attributes ride as message headers.

| Header             | Value                                                                                             |
| ------------------ | ------------------------------------------------------------------------------------------------- |
| `ce-specversion`   | `1.0`                                                                                             |
| `ce-id`            | Opaque producer-defined id; deterministic only for the event classes described above              |
| `ce-source`        | `reporter`                                                                                        |
| `ce-type`          | `studio.lerian.reporter.<resource>.<event>`, for example `studio.lerian.reporter.report.finished` |
| `ce-time`          | RFC 3339 emission timestamp                                                                       |
| `ce-subject`       | The identifier of the report, template, or deadline                                               |
| `ce-resourcetype`  | `report`, `template`, or `deadline`                                                               |
| `ce-eventtype`     | `finished`, `created`, `delivery_reverted`, and so on                                             |
| `ce-schemaversion` | `1.0.0`                                                                                           |
| `ce-tenantid`      | The tenant that owns the change                                                                   |

Reporter marks messages persistent. A single-tenant deployment still stamps a tenant value, so one consumer handles both deployment shapes with the same code.

## What a payload carries

***

Payload keys are `snake_case`, unlike the camelCase REST surface. A `report.finished` body:

```json theme={null}
{
  "report_id": "019826f4-6a9c-7b31-9d40-2f1e8c5a4b77",
  "template_id": "8f2c1a9e-4b30-4c02-9a1b-2d5e6f7a1c33",
  "output_format": "pdf",
  "status": "Finished",
  "artifact_object_key": "org-01abc/reports/8f2c1a9e-4b30-4c02-9a1b-2d5e6f7a1c33/019826f4-6a9c-7b31-9d40-2f1e8c5a4b77.pdf",
  "artifact_content_type": "application/pdf",
  "completed_at": "2026-07-29T14:22:08Z",
  "duration_ms": 8421,
  "section_count": 3
}
```

`artifact_object_key` is the exact object key reported by storage after the write, not a path that consumers should reconstruct. In single-tenant mode it has the form `reports/<templateId>/<reportId>.<format>`. Multi-tenant mode prefixes the same path with the tenant segment. Use the value verbatim.

If you validate its tenant segment, compare it with the tenant bound to your authenticated subscription, not with another field from the same message. An empty key on `report.finished` or `report.partial` is a contract violation. [Download a report](/en/reference/products/reporter/download-report) remains the supported way to fetch a report in the `Finished` state.

`report.partial` adds `section_failures` and `failed_section_count` alongside the same artifact fields. A resolvable key does not mean that the report is complete. Route regulatory delivery only from `report.finished`, and strictly decode the `status` field instead of using key presence as the discriminator.

`report.errored` replaces the artifact fields with `error_code` and `error_summary`. Its lack of an artifact field does not prove that no object was written: storage can succeed before terminal status persistence fails, leaving an object that no event names. Both error fields come from a fixed vocabulary: `report_generation_failed`, `report_generation_timeout`, or `report_generation_canceled`. Each code has a fixed summary. Raw error text never travels on the wire, so a payload cannot leak a query, a connection string, or tenant data. Branch on `error_code`.

## Enabling event publication

***

Event publication is a deployment choice, set with `STREAMING_ENABLED`. Turn it on and Reporter requires three more settings at startup:

| Setting                           | Value                                                                                                |
| --------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `RABBITMQ_REPORT_EVENTS_EXCHANGE` | The exchange that carries the events. Operator-configured; the reference value is `reporter.events`. |
| `STREAMING_BROKERS`               | Must be present and non-empty.                                                                       |
| `STREAMING_CLOUDEVENTS_SOURCE`    | Must be exactly `reporter`; startup rejects any other value.                                         |

When publication is off, `STREAMING_CLOUDEVENTS_SOURCE` may be unset. If it is set, it must still be exactly `reporter`. Reporter rejects another non-empty value at startup even while publication is off. When publication is on, Reporter also refuses to start if any of the three settings is blank, so a misconfigured deployment fails at startup instead of dropping events quietly.

## Next steps

***

<CardGroup cols={2}>
  <Card title="Reporter REST API" icon="code" href="/en/products/reporter/reporter-rest-api">
    The 28 operations, authentication, pagination, and errors.
  </Card>

  <Card title="API Reference" icon="list" href="/en/reference/introduction">
    The streaming manifest operation, with its full response shape.
  </Card>

  <Card title="Environment variables" icon="gear" href="/en/products/reporter/reporter-environment-variables">
    Every setting behind the streaming, exchange, and run-mode surfaces.
  </Card>

  <Card title="What is Reporter?" icon="book" href="/en/products/reporter/what-is-reporter">
    Templates, reports, deadlines, and where they fit.
  </Card>
</CardGroup>
