# Digital Twin — AVRO Kafka

AVRO / Kafka

# Asynchronous messages
Not every Digital Twin "API" is REST. Many integrations are AVRO messages that partners publish to or consume from Kafka topics — the same operations as the REST page, asynchronously.

← REST APIs
Mainframe shadowing →

> Schemas are owned by dtw-events (Confluent schema registry). amount is an UNSCALED decimal in minor units ($14.85 → 1485). Force-post = a ledger entry with balanceUpdateStrategy = UNCONDITIONAL, allow-listed per history code — Kafka path only. <prefix> is the per-environment topic prefix.

## PRODUCE `<prefix>.dtw.transaction.operations.*.command`
- **Key**: AccountKey (branch + account)
- **Producers**: channels · processors · adapters
- **Reply**: Entry<Op>CommandSuccessResult / …FailureResult

**AVRO schema · EntryRequestCommand**

```
// namespace: com.matera.dtw.command.transaction.entry
{ "type": "record", "name": "EntryRequestCommand", "fields": [
  { "name": "baseCommand", "type": "BaseCommand" },   // idempotencyId, traceId, correlationId, timestamp
  { "name": "account",     "type": "AccountKey" },    // { branch: int, account: long }
  { "name": "entry", "type": [                         // one of:
      "LedgerEntryRequestData", "BlockingEntryRequestData", "UnblockingEntryRequestData",
      "ReversalEntryRequestData", "RemovalEntryRequestData",
      "ExclusionEntryRequestData", "ReleaseEntryRequestData" ] }
]}

// LedgerEntryRequestData — the common "post an entry" case
{ "type": "record", "name": "LedgerEntryRequestData", "fields": [
  { "name": "historyCode",          "type": "int" },              // the transaction code
  { "name": "amount",               "type": "FinancialAmount" },  // { currency, amount } — amount UNSCALED
  { "name": "status",               "type": "EntryStatus" },      // POSTED | PENDING
  { "name": "balanceUpdateStrategy","type": "EntryBalanceUpdateStrategy" }, // CONDITIONAL | UNCONDITIONAL (force-post)
  { "name": "asOfDate",             "type": "date" },
  { "name": "correlationId",        "type": "string" },
  { "name": "description",          "type": ["null","string"] },
  { "name": "metaData",             "type": ["null","json"] }
]}
```

## CONSUME `<prefix>.dtw.transaction.event.transaction`

Channels consume entry events (posted transactions) to reflect balances in real time, without polling. A balance is the deterministic sum of these entries.

**AVRO schema · EntryCreationEvent**

```
// namespace: com.matera.dtw.event.transaction.entry
{ "type": "record", "name": "EntryCreationEvent", "fields": [
  { "name": "baseEvent", "type": "BaseEvent" },   // timestamp, traceId, correlationId, source
  { "name": "entry",     "type": "LedgerEntry" }  // account, historyCode, amount, status, balanceChanges, ...
]}

// Related events on the same topic:
//   PendingEntryCreationEvent · EntryReversalEvent · EntryExclusionEvent
//   EntryRemovalEvent · BlockingEntryEvent · UnblockingEntryEvent
```

## PRODUCE `multi-account: BundleRequestCommand`

Move value across several accounts atomically via the Composite Transaction service (REST: POST /v1/transaction-bundles; or the Avro BundleRequestCommand). Owned by dtw-events (dtw-bundle-events).

**AVRO schema · BundleRequestCommand**

```
// namespace: com.matera.dtw.command.transaction.command
{ "type": "record", "name": "BundleRequestCommand", "fields": [
  { "name": "baseCommand", "type": "BaseCommand" },
  { "name": "request", "type": [                  // one of:
      "RegularBundleRequestData",                  // multi-account entries in one atomic bundle
      "BundleExclusionRequestData" ] }
]}
```
