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

# Integrating with Lerian SPB

> Integrating with Lerian SPB: STR operation event families, ledger integration, webhook delivery, and API conventions.

Lerian SPB is event-driven. Event emission is not guaranteed for every operation or lifecycle change: some emitters are optional or best effort, and `EMISSION_REQUIRED` defaults to `false`. Set `EMISSION_REQUIRED=true` in a deployment whose downstream systems depend on these events; bootstrap then fails closed unless event emission is fully wired. Durable control-plane events are delivered to registered webhooks. `settlement.*` and `spb.ldl.*` are delivered on the streaming backbone only. Downstream systems read settlement state from `settlement.*` streaming events and do not poll.

## Event families

***

| Family                  | Emitted on                                                                                                                                                                                                                                                                                   |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `str.operation.*`       | Operation lifecycle — `accepted`, `received`, `returnRequested`, `cancelRequested`                                                                                                                                                                                                           |
| `str.readiness.changed` | The rail's readiness state changes                                                                                                                                                                                                                                                           |
| `str.certificate.*`     | Certificate lifecycle — `rotated`, `expiring`, `counterpartyChanged`, `activationRequested`                                                                                                                                                                                                  |
| `str.approval.*`        | A queued approval emits `signed` or `denied`; when it reaches quorum and changes from `PENDING_APPROVAL` to `SUBMITTED`, it emits `quorumReached` exactly once                                                                                                                               |
| `str.reconciliation.*`  | A reconciliation case is `opened` or `resolved`                                                                                                                                                                                                                                              |
| `str.schedule.changed`  | The operating-window grades change                                                                                                                                                                                                                                                           |
| `str.message.*`         | Message-level `received`, `sent`, `submitted`, `failed`, `rejected`                                                                                                                                                                                                                          |
| `spb.ldl.*`             | SILOC deposit-advisory and deposit-command facts, including `deposit-commanded`, `deposit-confirmed`, and `deposit-failed`. Delivered on the streaming backbone only, not on webhooks                                                                                                        |
| `settlement.*`          | The final settlement position: `settled` once the inbound R-leg confirms an operation, `returned` when a confirmed return reverses a settled original, `failed` on a rejection or on the cancellation of a never-settled original. Delivered on the streaming backbone only, not on webhooks |

## Ledger integration

***

Your ledger consumer must receive both the `str.operation.*` and `settlement.*` families on the streaming backbone. `str.operation.accepted` signals dispatch acceptance, not BACEN settlement, so use it to record a pending posting. Record the final position from the `settlement.*` facts on the streaming backbone: `settlement.settled` fires exactly once when the inbound R-leg moves the operation to `CONFIRMED`; `settlement.failed` fires when BACEN rejects the operation or a cancellation reverses a never-settled original; `settlement.returned` fires when a confirmed return reverses a settled original. A return follows the same pattern: `str.operation.returnRequested` signals the return's dispatch acceptance, and the parent posting reverses on `settlement.returned`. Lerian SPB holds **no** accounting position. The rail carries the message and its settlement state, and your ledger records the money.

## Inbound from BACEN

***

Lerian SPB consumes the inbound STR settlement replies (R-legs) and the GEN-family notices. Both arrive from BACEN over the RSFN. A submitted operation stays open until its R-leg arrives. The R-leg then moves the operation to `CONFIRMED` or `REJECTED`. Lerian SPB projects BACEN's settlement fields verbatim.

## Webhooks

***

Webhook consumers self-register on the canonical event constants. They negotiate payload shapes from a shared event catalog. Delivery is durable. You can retry a failed delivery manually. A dead-letter path handles the deliveries that exhaust their retries.

## API conventions

***

* **Auth** is a bearer token.
* **Writes are idempotent** through an idempotency key. A retried submit does not double-dispatch.
* **Reads never leak raw protocol payloads.** You read a single message by its NUOp. The rail reconstructs an XML view on read. It does not separately retain the literal sent bytes.
* **Unknown ids return a uniform not-found.** The response never reveals whether an operation exists that your institution does not own.
