Skip to main content
Midaz emits its public JSON business facts as CloudEvents 1.0 in binary content mode over Kafka through lib-streaming.

Public JSON ledger catalog

The public ledger manifest contains the following verified definitions. Every cataloged definition has a non-test production emission path.

CloudEvents envelope

Every public JSON fact uses the shared envelope below. The headers carry routing and schema information; the Kafka value carries the JSON data object.

Topics, manifest, and routing

The application topic identifies the producing application, not an individual event. Route a record by ce-resourcetype and ce-eventtype, and validate ce-schemaversion before decoding its data value.
  • Facts: lerian.streaming.ledger
  • Route DLQ: lerian.streaming.ledger.dlq
  • Manifest: GET /v1/streaming/manifest exposes the public JSON catalog and topic mapping, including while publication is disabled.

Delivery and failure semantics

Publication is disabled until STREAMING_ENABLED=true and broker configuration succeeds. When enabled, Midaz emits after the business-state change. It does not wire a lib-streaming outbox writer, outbox repository, transactional outbox, or outbox relay.
  • Policy: every public JSON definition is a fact with direct delivery, on_routable_failure DLQ handling, and fallback_on_circuit_open configured by lib-streaming v3.
  • Actual Midaz boundary: because no outbox writer is wired, the circuit-open fallback cannot persist an event. Emit paths log and swallow publication errors instead of returning them to the business command.
  • Consumer requirement: broker delivery is at least once for published records. Make handlers idempotent and deduplicate with (ce-source, ce-id).

Separate legacy RabbitMQ plane

Midaz also has compatibility exchanges for selected transaction, overdraft, and audit notifications. They are a separate legacy RabbitMQ plane, not a lib-streaming contract and not a complete representation of this 49-event public JSON catalog. New integrations should use the Kafka contract on this page.

Complete data contracts

These TypeScript-style declarations mirror the producer wire shape. Every field name is its JSON name. ? means the field has omitempty; | null means the field is nullable without omitting it. A source-type comment preserves the inventory type exactly. Decimal values are JSON strings, never binary floating-point numbers.

Shared source-type mappings

Event: studio.lerian.ledger.account.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An account is opened in a ledger.Subject: account ID (p.ID)
Event: studio.lerian.ledger.account.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An account is deleted.Subject: account ID (p.ID)
Event: studio.lerian.ledger.account.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An account’s mutable fields change.Subject: account ID (p.ID)
Event: studio.lerian.ledger.asset.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An asset is registered in a ledger.Subject: asset ID (p.ID)
Event: studio.lerian.ledger.asset.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An asset is deleted.Subject: asset ID (p.ID)
Event: studio.lerian.ledger.asset.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An asset’s mutable fields change.Subject: asset ID (p.ID)
Event: studio.lerian.ledger.balance.changedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A committed transaction moves a balance — one event per balance-affecting operation; values reflect the state after the operation.Subject: transaction ID and operation ID (p.TransactionID + ":" + p.OperationID)
Event: studio.lerian.ledger.balance.config_changedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A balance’s settings change, or overdraft is enabled (companion balance materialized). changeType discriminates settings_updated from overdraft_enabled.Subject: balance ID (p.ID)
Event: studio.lerian.ledger.balance.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A balance is created during account setup.Subject: balance ID (p.ID)
Event: studio.lerian.ledger.balance.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A balance is deleted.Subject: balance ID (p.ID)
Event: studio.lerian.ledger.balance.overdraft_clearedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: Overdraft is fully repaid — terminal signal (action = cleared).Subject: transaction ID and operation ID (p.TransactionID + ":" + p.OperationID)
Event: studio.lerian.ledger.balance.overdraft_drawnTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A debit consumes overdraft beyond available funds (action = drawn).Subject: transaction ID and operation ID (p.TransactionID + ":" + p.OperationID)
Event: studio.lerian.ledger.balance.overdraft_repaidTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: Overdraft usage decreases but is not fully cleared (action = repaid).Subject: transaction ID and operation ID (p.TransactionID + ":" + p.OperationID)
Event: studio.lerian.ledger.fee_billing_packages.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A billing package is created.Subject: billing package ID (p.ID)
Event: studio.lerian.ledger.fee_billing_packages.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A billing package is deleted.Subject: billing package ID (p.ID)
Event: studio.lerian.ledger.fee_billing_packages.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A billing package’s mutable fields change.Subject: billing package ID (p.ID)
Event: studio.lerian.ledger.fee_charge.appliedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A fee package is applied to a committed transaction.Subject: transaction ID (p.TransactionID)
Event: studio.lerian.ledger.fee_packages.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A fee package is created.Subject: fee package ID (p.ID)
Event: studio.lerian.ledger.fee_packages.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A fee package is deleted.Subject: fee package ID (p.ID)
Event: studio.lerian.ledger.fee_packages.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A fee package’s mutable fields change.Subject: fee package ID (p.ID)
Event: studio.lerian.ledger.holder.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A holder is created.Subject: holder ID (p.ID)
Event: studio.lerian.ledger.holder.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A holder is deleted.Subject: holder ID (p.ID)
Event: studio.lerian.ledger.holder.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A holder’s mutable fields change.Subject: holder ID (p.ID)
Event: studio.lerian.ledger.instrument.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An instrument is created for a holder and account.Subject: instrument ID (p.ID)
Event: studio.lerian.ledger.instrument.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An instrument is deleted.Subject: instrument ID (p.ID)
Event: studio.lerian.ledger.instrument.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An instrument’s mutable fields change.Subject: instrument ID (p.ID)
Event: studio.lerian.ledger.ledger.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A ledger is created within an organization.Subject: ledger ID (p.ID)
Event: studio.lerian.ledger.ledger.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A ledger is deleted.Subject: ledger ID (p.ID)
Event: studio.lerian.ledger.ledger.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A ledger’s name or status changes.Subject: ledger ID (p.ID)
Event: studio.lerian.ledger.operation_route.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An operation route is created.Subject: operation-route ID (p.ID)
Event: studio.lerian.ledger.operation_route.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An operation route is deleted.Subject: operation-route ID (p.ID)
Event: studio.lerian.ledger.operation_route.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An operation route’s mutable fields change.Subject: operation-route ID (p.ID)
Event: studio.lerian.ledger.organization.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An organization is created.Subject: organization ID (p.ID)
Event: studio.lerian.ledger.organization.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An organization is deleted.Subject: organization ID (p.ID)
Event: studio.lerian.ledger.organization.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: An organization’s mutable fields change.Subject: organization ID (p.ID)
Event: studio.lerian.ledger.portfolio.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A portfolio is created.Subject: portfolio ID (p.ID)
Event: studio.lerian.ledger.portfolio.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A portfolio is deleted.Subject: portfolio ID (p.ID)
Event: studio.lerian.ledger.portfolio.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A portfolio’s mutable fields change.Subject: portfolio ID (p.ID)
Event: studio.lerian.ledger.segment.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A segment is created.Subject: segment ID (p.ID)
Event: studio.lerian.ledger.segment.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A segment is deleted.Subject: segment ID (p.ID)
Event: studio.lerian.ledger.segment.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A segment’s mutable fields change.Subject: segment ID (p.ID)
Event: studio.lerian.ledger.transaction.canceledTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A pending transaction transitions from PENDING to CANCELED.Subject: transaction ID (p.ID)
Event: studio.lerian.ledger.transaction.committedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A pending transaction transitions from PENDING to APPROVED.Subject: transaction ID (p.ID)
Event: studio.lerian.ledger.transaction.postedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A newly created transaction is committed to storage with all its operations persisted (no parent).Subject: transaction ID (p.ID)
Event: studio.lerian.ledger.transaction.revertedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A revert flow creates a child transaction; parentTransactionId correlates it to the original.Subject: transaction ID (p.ID)
Event: studio.lerian.ledger.transaction_route.createdTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A transaction route is created.Subject: transaction-route ID (p.ID)
Event: studio.lerian.ledger.transaction_route.deletedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A transaction route is deleted.Subject: transaction-route ID (p.ID)
Event: studio.lerian.ledger.transaction_route.updatedTopic: lerian.streaming.ledgerRoute DLQ: lerian.streaming.ledger.dlqSchema: 1.0.0Fires when: A transaction route’s mutable fields change.Subject: transaction-route ID (p.ID)

Internal billing event (outside the public catalog)

billing_recorded is emitted separately from the 49 public JSON facts. It uses Confluent-framed Protobuf, not the public JSON manifest, and its fixed topic is lerian.streaming.billing.recorded. Do not count it as a manifest event or decode it as the JSON data contracts above. It keeps the CloudEvents 1.0 headers with ce-source=ledger, ce-resourcetype=billing, ce-eventtype=recorded, and ce-time set to the transaction creation time. CloudEvents type: studio.lerian.ledger.billing.recorded Topic: lerian.streaming.billing.recorded Content type: application/vnd.confluent.protobuf Schema: 1.0.0 Route DLQ: lerian.streaming.ledger.dlq Tenant: ce-tenantid follows the same resolved-tenant or literal default rule as the public facts. Subject: account ID Fires when: A non-noop transaction lifecycle write leaves the transaction in APPROVED status; Midaz emits one record for each unique non-external account referenced by its operations.
Midaz populates metric as active_account; properties.account_id and properties.transaction_id as strings; and subscription_id as the tenant ID in multi-tenant mode or the transaction organization ID otherwise.