> ## 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.

# BC Correios events

> CloudEvents that Lerian BC Correios publishes to Kafka for mail, sends to BACEN, and AI analysis.

Lerian BC Correios publishes nine JSON business facts as CloudEvents 1.0 in binary content mode over Kafka. The service needs a Kafka broker in every environment: set `STREAMING_BROKERS` and the other [broker variables](https://docs.lerian.studio/en/rails/bc-correios/bc-correios-environment-variables.md#kafka-broker-events). The [event streaming overview](https://docs.lerian.studio/en/reference/events/overview.md) describes the shared envelope.

## Transport contract

| Field | Value |
| - | - |
| `ce-source` | `br-correios` |
| Topic | `lerian.streaming.br-correios` |
| Dead-letter topic | `lerian.streaming.br-correios.dlq` |
| `ce-type` | `studio.lerian.br-correios.<event-key>` |
| `ce-tenantid` | `default` |
| Schema version | `1.0.0` for every event |
| Content type | `application/json` |
| Delivery | Set per event. See [Delivery](#delivery). |
| Runtime manifest | `GET /v1/streaming/manifest` |

The manifest lists the event catalog. It is served at the service root, not under `/api/v1/correios`. The route needs the Access Manager resource `streaming-manifest` with the action `get`, which the editor group holds.

## Delivery

Each event has one of three delivery modes:

* **Outbox**: the service writes the event to its PostgreSQL outbox in the same transaction as the change that caused it, and a relay publishes it to Kafka. If the broker is down, the relay retries for 7 days.
* **Direct, outbox fallback**: the service publishes the event to Kafka. If the broker is unavailable, the service writes the event to the outbox.
* **Best effort**: the service publishes the event to Kafka, with no outbox and no dead letter.

A broker that is down does not stop the service. An event can arrive more than once: deduplicate on `(ce-source, ce-id)` and keep consumers idempotent. Do not rely on arrival order.

## Event catalog

| Event key | Fires when | Delivery |
| - | - | - |
| `mail.received` | Lerian BC Correios stores a new mail from BC Correio. It fires once for each BC Correio message. | Outbox |
| `sync.initial_completed` | The first polling cycle completes. It fires once. | Direct, outbox fallback |
| `mail.read` | A user marks a mail as read. `idempotentNoOp` is `true` when the mail was already read. | Outbox |
| `mail.archived` | A user archives a mail. | Outbox |
| `mail.restored` | A user restores an archived mail to the folder it was archived from. | Outbox |
| `transmission.confirmed` | BC Correio accepts a message that you send, and the send moves to `CONFIRMED`. | Outbox |
| `transmission.failed` | A send does not confirm. The send moves to `FAILED`, or to `AMBIGUOUS` when BC Correio can hold the message. | Outbox |
| `ai.analysis_completed` | The AI analysis of a mail completes. | Best effort |
| `ai.analysis_failed` | The AI analysis of a mail fails. | Best effort |

The service does not start when `STREAMING_EVENT_POLICIES` turns off an event with the `Outbox` delivery.

## Payload fields

| Event key | Fields |
| - | - |
| `mail.received` | `mailId`, `bcbMessageId`, `folder`, `bcbPasta`, `mailType`, `subject`, `sender`, `receivedAt`, `hasAttachments`, `ementa`, `contentType` |
| `sync.initial_completed` | `firstSyncedAt`, `syncStatus` |
| `mail.read` | `mailId`, `userId`, `readAt`, `folder`, `idempotentNoOp` |
| `mail.archived` | `mailId`, `userId`, `archivedAt`, `priorFolder`, `currentFolder` |
| `mail.restored` | `mailId`, `userId`, `restoredAt`, `priorFolder`, `restoredToFolder` |
| `transmission.confirmed` | `mailId`, `userId`, `bcbConfirmationId`, `idempotencyKey`, `sentAt`, `destination`, `subject`, `inReplyToMailId` |
| `transmission.failed` | `mailId`, `idempotencyKey`, `failedAt`, `reason`, `errorClassification`, `originalError` |
| `ai.analysis_completed` | `mailId`, `aiProvider`, `aiModel`, `completedAt`, `insightLengthChars`, `retryCount`, `source` |
| `ai.analysis_failed` | `mailId`, `aiProvider`, `aiModel`, `failedAt`, `aiError`, `failureClass`, `retryCount`, `source` |

`errorClassification` is `BCC-2011` when the send moved to `FAILED`, and `BCC-2010` when it moved to `AMBIGUOUS`. The AI events carry no insight text. Read the insight with `GET /mails/{id}/ai-status`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.