Skip to main content
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 two accounts by default: one for AVAILABLE funds and one for HELD funds. A participant with three assets has six accounts. A bucket segments the balance into separate pools:
BucketDescription
AVAILABLEThe spendable balance. Credits land here by default, and debits draw from here.
HELDReserved and not spendable. Used for authorization holds where funds are locked until a transaction settles or is voided. A HOLD action moves funds from AVAILABLE to HELD; a RELEASE moves them back.
When you query a participant’s balances, the response breaks out each bucket:
{
  "balances": [
    {"asset_id": "...", "symbol": "PTS", "available": "850", "held": "150"}
  ]
}

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:
GET /v1/journal-entries?program_id=...&from=2025-01-01T00:00:00Z
Each journal entry includes:
FieldDescription
descriptionHuman-readable summary of the operation
postingsThe individual debit and credit lines, each with an account, amount, and bucket
event_idThe event that triggered this entry, if it came from a rule. Null for direct API operations.
rule_idThe rule that triggered this entry, if it was created during rule execution. Null for direct API operations and non-rule worker activity.
created_by_api_key_idThe API key that triggered this entry, if it came from a direct API call
entry_hashSHA-256 hash sealing this entry into the organization’s hash chain

Filtering

The journal entries list endpoint accepts query parameters to narrow results.
FilterDescription
program_idEntries for a specific program
participant_idEntries involving a participant
external_idEntries by external ID
group_idEntries involving a group
asset_idFilter by asset
bucketFilter by bucket (AVAILABLE, HELD, DEFERRED)
event_idEntries from a specific event
rule_idEntries created by a specific rule
action_typeFilter by ledger action type (CREDIT, DEBIT, HOLD, RELEASE, FORFEIT, MATURITY)
reference_idFilter by hold, release, or settle correlation ID
from / toTime range
min_amount / max_amountPosting 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:
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.
AccountRole
SYSTEM_ISSUANCEWhere new points come from. When the system mints funds for an UNLIMITED asset, the journal entry debits SYSTEM_ISSUANCE and credits the participant.
SYSTEM_BREAKAGEWhere lost points go. Forfeited, expired, or otherwise removed funds are credited here.
SYSTEM_REDEMPTIONWhere 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, forming a per-organization hash chain. 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. 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.