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

# Money Lifecycle

> Deterministic execution states, multi-layered verification paths, and idempotency boundaries inside the Zentra Control Plane.

In a high-integrity financial operating system, money movement must never be represented by an implicit, black-box state change. The Zentra Control Plane models every transaction as an immutable, explicit state-machine execution. Whether initiating an outbound transfer, collecting a customer-present payment, or mapping a virtual account settlement, every balance-affecting operation moves through a predictable, inspectable path.

This lifecycle ensures that engineering, risk, operations, and compliance teams can inspect the precise history, retry attempts, and raw evidence behind every ledger mutation.

## The Operational State Path

The following diagram traces the state transitions of a balance-affecting transfer request as it is ingested, verified, dispatched to provider bank networks, and settled.

```mermaid theme={null}
flowchart TD
    Start(["Request Initiated"]) -->|"POST /v1/transfers"| Accepted["1. ACCEPTED"]
    Accepted -->|"Acquire Distributed Lock"| Processing["2. PROCESSING"]
    
    subgraph Core_Engine["Zentra Control Plane Core"]
        Processing -->|"Enforce Tenant Policies & Fees"| Policies{"Tenant Scope"}
        Policies -->|"Allowed"| LedgerWrite["Immutable Ledger Journal Write"]
        Policies -->|"Rejected / Over Limit"| Failed["4. FAILED"]
    end
    
    LedgerWrite -->|"NATS Event Dispatch"| AwaitingProvider["3. AWAITING_PROVIDER"]
    
    subgraph Network_Boundary["Financial Network Boundary"]
        AwaitingProvider -->|"Webhook Callback (success)"| Successful["4. SUCCESSFUL"]
        AwaitingProvider -->|"Webhook Callback (fail)"| Failed
        AwaitingProvider -->|"Sync Provider Status Check"| Successful
        AwaitingProvider -->|"Sync Provider Status Check (fail)"| Failed
    end
    
    Successful -->|"Statement Reconciliation"| Reconciled["5. RECONCILED"]
    Failed -->|"ledger.reversal"| Reversed["5. REVERSED"]
    
    classDef app fill:#14161A,stroke:#2A2E35,stroke-width:1px,color:#F5F4F0
    classDef zentra fill:#2563FF,stroke:#AFC8FF,stroke-width:1px,color:#F5F4F0
    classDef proof fill:#2A2E35,stroke:#5770A0,stroke-width:1px,color:#F5F4F0
    
    class Start app
    class Accepted,Processing zentra
    class AwaitingProvider,Successful,Failed,Reconciled,Reversed proof
```

***

## Lifecycle Stages

Every transaction progresses through the following deterministic states managed by `GenStateMachine` at the core BaaS layer:

<Steps>
  <Step title="ACCEPTED">
    The API Gateway ingests the HTTP request and registers the transaction identifier. At this stage, the payload is validated against JSON schema rules, tenant-scoped credentials are authenticated, and the transaction's unique key is prepared for idempotency verification. No ledger mutations have occurred.
  </Step>

  <Step title="PROCESSING">
    The system attempts to acquire a distributed lock in Redis for the transaction's idempotency key. Once locked, Zentra verifies tenant policy rules (checking daily transfer velocity limits, risk thresholds, and compliance clearance), computes standard fee models, and executes the initial journal entry to reserve funds on the core ledger.
  </Step>

  <Step title="AWAITING_PROVIDER">
    The transaction is handed off to the designated provider gateway or banking rail (e.g., Providus, GTBank, or virtual sandbox networks). Because bank settlements are highly asynchronous, the transfer enters a holding state while the core routing engine waits for a callback hook or polls the partner endpoint.
  </Step>

  <Step title="SUCCESSFUL or FAILED">
    A terminal execution state.

    * **`SUCCESSFUL`**: The partner rail confirms execution and Zentra marks the ledger entry as posted.
    * **`FAILED`**: The partner network rejects the transfer (e.g., due to insufficient counterparty funds, invalid account details, or routing timeouts), recording a precise error signature in the ledger log.
  </Step>

  <Step title="RECONCILED or REVERSED">
    Post-transaction cleanup states.

    * **`RECONCILED`**: End-of-day bank statement parsing matches the ledger entry exactly to settlement reports, verifying absolute matching evidence.
    * **`REVERSED`**: If a transaction halts after a partial debit, an automated `ledger.reversal` event is dispatched to credit the tenant's ledger and restore the balance.
  </Step>
</Steps>

***

## Strict Idempotency Guarantees

Fintech developers must design their applications to handle network timeouts, dropped packets, and temporary server failures. To prevent duplicate fund movement, Zentra enforces strict idempotency at the gateway layer for all mutating endpoints (`POST`, `PUT`, `PATCH`).

### The Idempotency Workflow

1. **Submit Unique Keys**: Attach a unique `x-idempotency-key` (typically a UUIDv4) as an HTTP header or payload parameter to every mutating API call.
2. **Lock Acquisition**: Zentra checks Redis for a cached response using the format `gateway:idempotency:<tenant_id>:<key>`.
3. **Handle Concurrent Calls**: If a second request arrives while the first is still processing, the gateway rejects the duplicate with an `HTTP 409 Conflict`.
4. **Cache & Replay**: Once processing is complete, Zentra caches the payload and HTTP status code in Redis for **24 hours**. Any subsequent calls with the exact same key immediately receive the identical cached response.

```javascript Node.js theme={null}
import { Zentra } from "@zentra/sdk";

const zentra = new Zentra({
  apiKey: process.env.ZENTRA_SECRET_KEY,
  environment: "sandbox"
});

// Use a deterministic, business-event-based idempotency key
const idempotencyKey = "tx_transfer_payout_user_9921_iter1";

try {
  const transfer = await zentra.transfers.create({
    amountMinor: 250000, // 2,500.00 Kobo/cents
    destinationBankCode: "058",
    destinationAccountNumber: "0123456789",
    reference: idempotencyKey,
    narration: "Sandbox payroll transfer"
  }, {
    headers: {
      "X-Idempotency-Key": idempotencyKey
    }
  });

  console.log(`Transfer status: ${transfer.status}`);
} catch (error) {
  if (error.statusCode === 409) {
    console.error("Duplicate request detected. Operation already in progress.");
  } else {
    console.error("Operational failure:", error.message);
  }
}
```

By enforcing explicit transitions, transaction caching, and deterministic ledger writes, Zentra eliminates duplicate transfer risks and ensures every single unit of currency is accounted for across all operational steps.
