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

# Ledger

> Double-entry journal entries, postings, and system accounts

Every asset movement in Scrip is recorded as a double-entry journal entry. Credits and debits always balance.

## Double-Entry Accounting

Every transaction creates a journal entry with two or more postings that sum to zero:

```
Journal Entry: "Purchase reward - 10 points"
├── Posting 1: SYSTEM_ISSUANCE   -10  (debit: source)
└── Posting 2: participant/alice +10  (credit: destination)
```

For `PREFUNDED` assets, the source is the program wallet instead of `SYSTEM_ISSUANCE`:

```
Journal Entry: "Purchase reward - 10 points"
├── Posting 1: program/loyalty   -10  (debit: program wallet)
└── Posting 2: participant/alice +10  (credit: participant)
```

## Accounts and Buckets

An account is a balance container in the ledger. Participants, groups, programs, and system entities all have accounts. The ledger tracks funds by writing postings against these accounts.

Each account holds a balance for a single asset in a single bucket. A participant with one asset has up to three accounts: one for `AVAILABLE` funds, one for `HELD` funds, and one for `DEFERRED` funds. Accounts are created lazily, when the first posting touches that bucket. A participant with three assets has up to nine accounts.

A bucket segments the balance into separate pools:

| Bucket      | Description                                                                                                                                                                                                                                                                                              |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AVAILABLE` | The spendable balance. Credits land here by default. Debits, holds, forfeits, and redemptions draw from this bucket.                                                                                                                                                                                     |
| `HELD`      | Reserved and not spendable. A `HOLD` action moves funds from `AVAILABLE` to `HELD`, locking them until the hold is resolved. A `RELEASE` moves them back to `AVAILABLE`. Forfeits can also draw from `HELD`.                                                                                             |
| `DEFERRED`  | Not yet matured. When a credit specifies a future `matures_at` timestamp, funds land here instead of `AVAILABLE`. Deferred funds cannot be spent, held, or debited. When the maturity date passes, a background job automatically moves the funds to `AVAILABLE` and records a `MATURITY` journal entry. |

When you query a participant's balances, the response breaks out each bucket:

```json theme={null}
{
  "balances": [
    {"asset_id": "...", "symbol": "PTS", "available": "850", "held": "150", "deferred": "500"}
  ]
}
```

## Journal Entries

A journal entry is a record of a single ledger operation. The system creates one every time funds move: credits, debits, holds, releases, forfeits, and redemptions.

Each journal entry contains two or more postings. A posting is a single line item that records a change to one account: which account, the signed amount (positive for credits, negative for debits), and which bucket. The postings within an entry always sum to zero.

You can list journal entries through the API:

```bash theme={null}
GET /v1/journal-entries?program_id=...&from=2025-01-01T00:00:00Z
```

Each journal entry includes:

| Field          | Description                                                                                                                               |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `description`  | Human-readable summary of the operation                                                                                                   |
| `postings`     | The individual debit and credit lines, each with an account, amount, and bucket                                                           |
| `event_id`     | The event that triggered this entry, if it came from a rule. Null for direct API operations.                                              |
| `rule_id`      | The rule that triggered this entry, if it was created during rule execution. Null for direct API operations and non-rule worker activity. |
| `action_type`  | The ledger operation that created this entry (`CREDIT`, `HOLD`, `REDEMPTION`, ...)                                                        |
| `reference_id` | Correlation ID linking related entries, such as a hold to its release or settlement                                                       |
| `entry_hash`   | SHA-256 hash sealing this entry into the organization's hash chain                                                                        |

### Filtering

The journal entries list endpoint accepts query parameters to narrow results.

| Filter                      | Description                                                                                                                                                                                 |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `program_id`                | Entries for a specific program                                                                                                                                                              |
| `participant_id`            | Entries involving a participant                                                                                                                                                             |
| `external_id`               | Entries by external ID                                                                                                                                                                      |
| `group_id`                  | Entries involving a group                                                                                                                                                                   |
| `asset_id`                  | Filter by asset                                                                                                                                                                             |
| `bucket`                    | Filter by bucket (`AVAILABLE`, `HELD`, `DEFERRED`)                                                                                                                                          |
| `event_id`                  | Entries from a specific event                                                                                                                                                               |
| `rule_id`                   | Entries created by a specific rule                                                                                                                                                          |
| `action_type`               | Filter by ledger action type: `CREDIT`, `DEBIT`, `TRANSFER`, `HOLD`, `RELEASE`, `FORFEIT`, `EXPIRATION`, `REDEMPTION`, `REVERSAL`, `BURN`, `FUND`, `ADJUSTMENT`, `MATURITY`, or `VOID_HOLD` |
| `reference_id`              | Filter by hold, release, or settle correlation ID                                                                                                                                           |
| `from` / `to`               | Time range                                                                                                                                                                                  |
| `min_amount` / `max_amount` | Posting amount range                                                                                                                                                                        |

Amount filters apply to raw signed posting values. Credits are positive, debits are negative.
Entity filters (`participant_id`, `external_id`, `group_id`) are mutually exclusive.

### Entry Detail

Fetch a single journal entry to see the full record:

```bash theme={null}
GET /v1/journal-entries/{id}
```

The response includes every posting in the entry, with the full account, amount, and bucket detail for each.

## System Accounts

Every fund movement has an origin and a destination. For transfers between participants, both sides are participant accounts. When funds are minted, forfeited, or redeemed, the other side of the transaction is a system account.

| Account             | Role                                                                                                                                                      |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SYSTEM_ISSUANCE`   | Where new points come from. When the system mints funds for an `UNLIMITED` asset, the journal entry debits `SYSTEM_ISSUANCE` and credits the participant. |
| `SYSTEM_BREAKAGE`   | Where lost points go. Forfeited, expired, or otherwise removed funds are credited here.                                                                   |
| `SYSTEM_REDEMPTION` | Where spent points go. When a participant redeems funds for a reward, the entry debits the participant and credits `SYSTEM_REDEMPTION`.                   |

These accounts make it possible to reconcile total points issued against points in circulation, points spent, and points lost.

## Integrity

The ledger is append-only. Journal entries cannot be modified or deleted after creation.

Every journal entry is sealed with a SHA-256 hash that covers its metadata, all postings, and the previous entry's hash. This forms a chain within each organization: if any entry were altered, the hash would no longer match, and every subsequent entry's hash would also break. The `entry_hash` field on each journal entry is this cryptographic seal.

You can verify the chain, along with postings balance and value conservation, at any time with the [ledger integrity report](/api-reference/reporting/get-ledger-integrity). Pin its `chain_head` hash externally to make any later alteration of history detectable.

To reverse a transaction, create a new journal entry with opposite postings. A redemption reversal, for example, credits the participant and debits the redemption account. The original entry and its hash remain intact.
