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

# Settlement items

> Understanding how Rinne tracks actual money movements and settles ledger entries

Settlement items are the bridge between accounting records ([ledger entries](/concepts/ledger-entries)) and actual money movements. While ledger entries record what *should* happen financially, settlement items track what *actually* happened—when money moved, how it moved, and to where.

## What are settlement items?

A settlement item is a clearing link that applies a portion (or all) of a ledger entry to a real settlement operation. Each settlement item represents an actual money movement:

* **PIX payment** to a merchant's bank account
* **Internal transfer** between accounts
* **Invoice payment** for monthly costs
* **Boleto payment** for settlements

### Entity relationships

```mermaid theme={null}
graph LR
    LE[Ledger Entry] -->|settled by| SI[Settlement Items]
    SI -->|references| T[Transaction]
    SI -->|references| IT[Internal Transfer]
    SI -->|references| CO[Cashout]
    SI -->|settles to| BA[Bank Account]
    SI -->|updates| LE
    
    style LE fill:#5B68EB,color:#fff
    style SI fill:#7B89FF,color:#fff
    style T fill:#4A56D9,color:#fff
    style IT fill:#5B68EB,color:#fff
    style CO fill:#7B89FF,color:#fff
    style BA fill:#5B68EB,color:#fff
```

## Core attributes

Each settlement item contains:

* **ledger\_entry\_id**: Which ledger entry is being settled
* **settled\_amount**: How much of the entry is being settled (in cents)
* **settlement\_date**: When the money actually moved (date-only format: YYYY-MM-DD)
* **method**: How the money moved (PIX, internal transfer, etc.)
* **status**: Current state of the settlement
* **operation\_id**: External reference (transaction ID, transfer ID, etc.)
* **affiliation\_bank\_account\_id**: Destination bank account (if applicable)

## Settlement methods

Rinne supports multiple settlement methods:

<CardGroup cols={2}>
  <Card title="PIX" icon="bolt">
    Instant payments to merchant bank accounts (D+0)
  </Card>

  <Card title="Internal transfer" icon="arrow-right-arrow-left">
    Transfers between Rinne accounts (organization fees)
  </Card>

  <Card title="Invoice" icon="file-invoice">
    Monthly invoices for platform/provider costs
  </Card>

  <Card title="Boleto" icon="barcode">
    Bank slip payments for settlements
  </Card>
</CardGroup>

## Settlement status lifecycle

Settlement items follow a state machine with strict transition rules:

```mermaid theme={null}
graph LR
    A[PENDING] --> B[PROCESSING]
    A --> C[PAID]
    A --> D[FAILED]
    B --> C
    B --> D
    C -.terminal.-> C
    D -.terminal.-> D
```

### Valid transitions

* **PENDING → PROCESSING**: Settlement initiated
* **PENDING → PAID**: Instant settlement (PIX)
* **PENDING → FAILED**: Settlement failed immediately
* **PROCESSING → PAID**: Settlement completed
* **PROCESSING → FAILED**: Settlement failed during processing

### Terminal states

* **PAID**: Settlement completed successfully (no further transitions)
* **FAILED**: Settlement failed permanently (no further transitions)

## PIX settlement flow

For PIX transactions, Rinne creates settlement items immediately after the transaction is approved:

```mermaid theme={null}
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#5B68EB','primaryTextColor':'#fff','primaryBorderColor':'#4A56D9','lineColor':'#7B89FF','secondaryColor':'#7B89FF','tertiaryColor':'#4A56D9'}}}%%
sequenceDiagram
    participant T as Transaction
    participant LE as Ledger Entries
    participant SI as Settlement Items
    participant BA as Bank Account
    
    T->>T: Status: APPROVED
    T->>LE: Create posting set<br/>(4 pairs)
    LE->>SI: Create settlement items
    SI->>SI: Status: PENDING
    SI->>BA: Transfer via PIX
    BA->>SI: Transfer complete
    SI->>SI: Status: PAID
    SI->>LE: Update outstanding_amount
    LE->>LE: settled = true
    
    Note over SI,BA: Instant settlement (D+0)
```

### 1. Transaction settlement

The main transaction amount is settled instantly:

```json theme={null}
{
  "ledger_entry_id": "le_merchant_tx_credit",
  "settled_amount": 10000,
  "settlement_date": "2025-01-15",
  "method": "PIX",
  "status": "PAID",
  "operation_id": "trx_456",
  "affiliation_bank_account_id": "ba_merchant_account"
}
```

<Note>
  The `settlement_date` field is returned in date-only format (YYYY-MM-DD) without time information, representing the calendar day when the settlement occurred.
</Note>

The provider's corresponding debit is also settled:

```json theme={null}
{
  "ledger_entry_id": "le_provider_tx_debit",
  "settled_amount": 10000,
  "settlement_date": "2025-01-15",
  "method": "INTERNAL_TRANSFER",
  "status": "PAID",
  "operation_id": "trx_456"
}
```

### 2. Organization fee settlement

Organization fees are settled via internal transfer:

```json theme={null}
{
  "ledger_entry_id": "le_merchant_fee_debit",
  "settled_amount": 250,
  "settlement_date": "2025-01-15",
  "method": "INTERNAL_TRANSFER",
  "status": "PENDING",
  "operation_id": "internal_transfer_789"
}
```

When the internal transfer completes, the status updates to `PAID`.

### 3. Platform and provider costs

Platform and provider costs remain outstanding for monthly invoice settlement:

```json theme={null}
{
  "ledger_entry_id": "le_platform_cost_credit",
  "outstanding_amount": 100,
  "settled": false
}
```

## Ledger entry updates

When settlement items are created or updated, the corresponding ledger entries are automatically updated:

### Outstanding amount calculation

```typescript theme={null}
outstanding_amount = amount - Σ(settled_amount from non-FAILED settlement items)
```

### Settlement status

```typescript theme={null}
settled = (outstanding_amount === 0)
fully_settled_at = settled ? now() : null
last_clearing_at = most_recent_settlement_date
```

### Example progression

**Initial state** (after ledger entry creation):

```json theme={null}
{
  "id": "le_merchant_fee_debit",
  "amount": 250,
  "outstanding_amount": 250,
  "settled": false,
  "fully_settled_at": null,
  "last_clearing_at": null
}
```

**After settlement item creation** (PAID):

```json theme={null}
{
  "id": "le_merchant_fee_debit",
  "amount": 250,
  "outstanding_amount": 0,
  "settled": true,
  "fully_settled_at": "2025-01-15T10:35:00Z",
  "last_clearing_at": "2025-01-15T10:35:00Z"
}
```

## Partial settlements

Settlement items support partial settlements, where a ledger entry is settled in multiple operations:

```json theme={null}
// First settlement: R$50 of R$100
{
  "ledger_entry_id": "le_123",
  "settled_amount": 5000,
  "method": "PIX",
  "status": "PAID"
}

// Second settlement: R$30 of R$100
{
  "ledger_entry_id": "le_123",
  "settled_amount": 3000,
  "method": "PIX",
  "status": "PAID"
}

// Third settlement: R$20 of R$100
{
  "ledger_entry_id": "le_123",
  "settled_amount": 2000,
  "method": "PIX",
  "status": "PAID"
}
```

The ledger entry tracks the total:

```json theme={null}
{
  "id": "le_123",
  "amount": 10000,
  "outstanding_amount": 0,
  "settled": true
}
```

## Refund settlements

Refund settlements follow the same pattern as transaction settlements:

### Transaction refund

```json theme={null}
{
  "ledger_entry_id": "le_merchant_refund_debit",
  "settled_amount": 5000,
  "settlement_date": "2025-01-15",
  "method": "PIX",
  "status": "PAID",
  "operation_id": "refund_456"
}
```

### Organization fee refund

```json theme={null}
{
  "ledger_entry_id": "le_merchant_fee_refund_credit",
  "settled_amount": 125,
  "settlement_date": "2025-01-15",
  "method": "INTERNAL_TRANSFER",
  "status": "PAID",
  "operation_id": "internal_transfer_890"
}
```

## Idempotency

Settlement item creation is idempotent. If settlement items already exist for a ledger entry and operation ID, Rinne skips creation:

```typescript theme={null}
// Check for existing settlement items
const existingItems = await findSettlementItemsByLedgerEntryIdAndOperationId(
  ledgerEntryId,
  operationId
);

// Calculate total settled amount (excluding FAILED)
const totalSettled = existingItems
  .filter(item => item.status !== 'FAILED')
  .reduce((sum, item) => sum + item.settled_amount, 0);

// Skip if already fully settled
if (totalSettled >= ledgerEntry.amount) {
  return; // Already settled
}
```

## Settlement invariants

Rinne enforces strict invariants for settlement items:

### Settlement bounds

```typescript theme={null}
Σ(settled_amount) ≤ ledger_entry.amount
```

You cannot settle more than the original ledger entry amount.

### Outstanding accuracy

```typescript theme={null}
ledger_entry.amount = Σ(settled_amount) + outstanding_amount
```

The sum of settled amounts plus outstanding amount must equal the original amount.

### Non-negative outstanding

```typescript theme={null}
outstanding_amount ≥ 0
```

Outstanding amounts can never be negative.

### Settlement status consistency

```typescript theme={null}
settled = true ⟺ outstanding_amount = 0
```

A ledger entry is settled if and only if the outstanding amount is zero.

## Complete settlement example

Here's a complete example showing how a R\$100 PIX transaction is settled:

### 1. Ledger entries created

```json theme={null}
{
  "merchant_credit": {
    "amount": 10000,
    "outstanding_amount": 10000,
    "settled": false
  },
  "organization_fee_debit": {
    "amount": 250,
    "outstanding_amount": 250,
    "settled": false
  }
}
```

### 2. Settlement items created

```json theme={null}
{
  "merchant_settlement": {
    "ledger_entry_id": "merchant_credit",
    "settled_amount": 10000,
    "method": "PIX",
    "status": "PAID"
  },
  "fee_settlement": {
    "ledger_entry_id": "organization_fee_debit",
    "settled_amount": 250,
    "method": "INTERNAL_TRANSFER",
    "status": "PENDING"
  }
}
```

### 3. Ledger entries updated

```json theme={null}
{
  "merchant_credit": {
    "amount": 10000,
    "outstanding_amount": 0,
    "settled": true,
    "fully_settled_at": "2025-01-15T10:30:00Z"
  },
  "organization_fee_debit": {
    "amount": 250,
    "outstanding_amount": 0,
    "settled": true,
    "fully_settled_at": "2025-01-15T10:35:00Z"
  }
}
```

## Key principles

<CardGroup cols={2}>
  <Card title="Actual movements" icon="money-bill-transfer">
    Track real money movements, not just accounting
  </Card>

  <Card title="State machine" icon="diagram-project">
    Strict status transitions prevent invalid states
  </Card>

  <Card title="Race-safe" icon="shield-check">
    Two-step creation prevents race conditions
  </Card>

  <Card title="Idempotent" icon="repeat">
    Safe to retry settlement operations
  </Card>
</CardGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Ledger entries" icon="book" href="/concepts/ledger-entries">
    Learn about the accounting foundation
  </Card>

  <Card title="Banking" icon="building-columns" href="/concepts/banking">
    Understand banking operations
  </Card>
</CardGroup>
