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

# Transactions

> Understanding how money moves in OLIVE

# Transactions

A transaction is the record of money moving from one place to another in OLIVE. Every payment, transfer, deposit, and withdrawal creates a transaction that tracks what happened, who was involved, and whether it succeeded.

***

## What Happens When You Pay?

Let's say a customer taps their NFC card at a shop to pay 5,000 SLE for groceries. Here's what happens behind the scenes:

### 1. Transaction Created

OLIVE creates a new transaction record with status `PENDING`. This is the starting point - we know someone wants to move money, but nothing has happened yet.

### 2. Validation

Before moving any money, OLIVE checks:

* Does the customer have enough balance?
* Is their card status `assigned` (active)?
* Is the merchant's processor account `active`?
* Does this transaction trigger any compliance rules?
* Is the amount within KYC limits?

If any check fails, the transaction moves to `FAILED` and stops.

### 3. Execution

If validation passes, the transaction moves to `PROCESSING`:

* Customer's wallet is debited 5,000 SLE
* Merchant's account is credited 5,000 SLE
* Any fees are calculated and applied
* Ledger entries are created for both sides

### 4. Completion

Transaction moves to `COMPLETED`. Confirmations are sent to both parties.

This entire flow is **atomic** - if any step fails partway through, everything rolls back. You'll never have money leave one account without arriving in another.

***

## Transaction Lifecycle

```mermaid theme={null}
flowchart TB
    pending["PENDING<br/>Transaction just created"]
    processing["PROCESSING<br/>Money is being moved"]
    completed["COMPLETED"]
    failed["FAILED"]
    
    pending --> processing
    processing --> completed
    processing --> failed
    
    style pending fill:#f59e0b,stroke:#d97706,color:#fff
    style processing fill:#3b82f6,stroke:#2563eb,color:#fff
    style completed fill:#10b981,stroke:#059669,color:#fff
    style failed fill:#ef4444,stroke:#dc2626,color:#fff
```

Most transactions complete in under a second. The `PROCESSING` state exists because some operations (like external bank transfers) may take longer.

***

## Why Compliance States Exist

Sometimes a transaction triggers a compliance rule. Maybe it's unusually large, or the customer has made many transactions today. When this happens, the transaction enters a compliance state instead of completing normally.

### Flagged

The transaction triggered a monitoring rule but was allowed to proceed. An alert is created for the compliance team to review later. Example: A 400,000 SLE transfer is flagged for review but goes through.

### Under Review

The transaction is paused while a compliance officer investigates. The money hasn't moved yet. Example: A new customer suddenly receives 1,000,000 SLE from unknown sources.

### On Hold

The transaction is temporarily frozen pending investigation. This is stronger than Under Review - something suspicious was detected. Example: Multiple rapid-fire transactions from the same account.

### Suspended

The transaction is stopped due to a confirmed compliance concern. It won't proceed until the issue is resolved. Example: The sender's account has been flagged for suspicious activity.

### Approved

After review, a compliance officer manually approved the transaction. It will now proceed to completion.

### Rejected

After review, the transaction was blocked. The sender keeps their money, but the payment won't go through.

***

## Who is Involved in a Transaction?

Every transaction has two sides:

**Sender** (`from_account_id`, `sender_subscriber_id`)
The person or entity whose balance decreases. They're paying, transferring out, or withdrawing.

**Recipient** (`to_account_id`, `recipient_subscriber_id`)
The person or entity whose balance increases. They're receiving payment, getting a transfer, or depositing.

For card transactions, we also track:

* `sender_card_serial` - Which card initiated the payment
* `recipient_card_serial` - Which card received (for card-to-card transfers)

***

## Transaction Types Explained

### Payment Types

| Type             | What It Is                  | Example               |
| ---------------- | --------------------------- | --------------------- |
| `payment`        | General payment to merchant | Buying groceries      |
| `pos_payment`    | POS terminal card payment   | Tapping card at store |
| `online_payment` | E-commerce purchase         | Website checkout      |

### Transfer Types

| Type           | What It Is                      | Example                    |
| -------------- | ------------------------------- | -------------------------- |
| `transfer`     | Person-to-person money movement | Sending money to family    |
| `card_to_card` | Between two OLIVE cards         | Sharing with spouse's card |

### Cash Operations

| Type               | What It Is                        | Example                |
| ------------------ | --------------------------------- | ---------------------- |
| `cashin`           | Converting cash to wallet balance | Giving cash to agent   |
| `cashout`          | Converting wallet to cash         | Withdrawing at agent   |
| `card_topup_agent` | Agent loads card                  | Cash deposit via agent |

### External Operations

| Type                        | What It Is                        | Example                     |
| --------------------------- | --------------------------------- | --------------------------- |
| `topup`                     | Adding funds from external source | VULT funding                |
| `withdrawal`                | Sending to external bank          | Bank transfer out           |
| `card_topup_third_party`    | Partner funding                   | VULT loads card             |
| `card_transfer_third_party` | Partner withdrawal                | Sending to bank via partner |

***

## Transaction Channels

The channel tells you where the transaction originated:

| Channel    | Source                  | Example                             |
| ---------- | ----------------------- | ----------------------------------- |
| `whatsapp` | Conversational AI agent | "Send 10,000 to Ahmed" via WhatsApp |
| `pos`      | Physical NFC terminal   | Tapping card at merchant            |
| `agent`    | Agent shop              | Cash-in at local kiosk              |
| `web`      | Dashboard/web app       | Admin initiating transfer           |
| `api`      | Third-party integration | Partner system calling API          |

***

## Understanding Fees

Transactions can include fees. The `fee` field stores how much was charged on top of the transaction amount.

**Example: POS Payment with 1% fee**

* Customer buys item for 10,000 SLE
* Fee is 1% = 100 SLE
* Customer's wallet debited: 10,100 SLE
* Merchant receives: 10,000 SLE
* OLIVE receives fee: 100 SLE

Fees are configured per transaction type in the Fee Settings. See [Fees](/concepts/fees) for details.

***

## The Ledger: Double-Entry Bookkeeping

OLIVE uses double-entry accounting. For every transaction, we create ledger entries showing exactly what happened:

**Example: 5,000 SLE transfer from Alice to Bob**

| Entry | Account | Type   | Amount | Balance After |
| ----- | ------- | ------ | ------ | ------------- |
| 1     | Alice   | debit  | -5,000 | 45,000        |
| 2     | Bob     | credit | +5,000 | 15,000        |

The ledger provides:

* Complete audit trail
* Balance verification (debits always equal credits)
* Historical record of all balance changes

***

## Idempotency: Preventing Duplicates

Network problems happen. What if you submit a payment and your connection drops before you get a response? Did the payment go through or not?

OLIVE solves this with **idempotency**. Every transaction requires a unique `request_id`. If you submit the same `request_id` twice:

* First time: Transaction is created and processed normally
* Second time: OLIVE returns the result of the first transaction

This means you can safely retry failed requests without worrying about double-charging.

***

## Metadata: Extra Information

The `metadata` field (JSONB) stores additional context:

* Which agent processed a cash-in
* Original transaction channel
* Integration partner details
* Custom notes

This data isn't used for processing but helps with reporting and debugging.

***

## Related Concepts

<CardGroup cols={2}>
  <Card title="Wallets" icon="wallet" href="/concepts/wallets">
    Where balances live
  </Card>

  <Card title="Fees" icon="coins" href="/concepts/fees">
    How fees are calculated
  </Card>

  <Card title="Compliance" icon="scale-balanced" href="/concepts/compliance">
    Transaction monitoring
  </Card>

  <Card title="Agents" icon="users" href="/concepts/agents">
    Cash-in/out operations
  </Card>
</CardGroup>
