Why use a Ledger Schema?
By default, the ledger accepts any account address. A schema adds structure:- Catch errors early: Reject typos like
users:alciebefore they create orphaned accounts - Enforce naming conventions: Require user IDs to match a specific format
- Auto-assign metadata: New accounts automatically get default metadata values
- Audit trail: Every transaction records which schema version validated it
Schema structure
A schema consists of two required fields:chart: Defines valid account patternstransactions: Defines reusable transaction templates (can be empty)
Defining your chart
The chart uses a nested JSON structure with special prefixes to distinguish between account segments and properties.Fixed segments
Fixed segments are literal account path components. In the example above,world, banks, users, main, and fees are fixed segments.
banks:main and banks:fees.
Variable segments
Variable segments start with$ and match any value. The text after $ is the variable name (e.g., $userId, $orderId), which helps document what the segment represents.
users:123, users:alice, or users:order-456.
Pattern validation
Add a.pattern property to validate variable segments against a regular expression:
banks:GB82WEST12345698765432. An account like banks:abc123 would be rejected because it doesn’t match the IBAN format.
Leaf vs non-leaf accounts
By default, a segment without children is a valid account (leaf). To define a segment that:- Has children AND
- Is itself a valid account
.self property:
orders:123(the order itself)orders:123:pending(pending state)orders:123:completed(completed state)
.self, only orders:123:pending and orders:123:completed would be valid.
Default metadata
Define default metadata values for accounts matching a pattern:users:alice is created, it automatically receives {"type": "customer", "tier": "standard"}.
Defaults only apply when an account is first created. They never overwrite existing metadata.
Validation rules
When defining your chart, keep these constraints in mind:- Segment names can only contain letters, numbers, underscores, and hyphens
- Root segments must be fixed—you cannot start your chart with a variable (
$userId) or property (.pattern) - One variable per level — each level in your chart can have at most one variable segment
- Patterns only on variables — you cannot add
.patternto a fixed segment
Managing schemas
Create a schema
Insert a schema with a version identifier:List schemas
Retrieve all schema versions for a ledger:Get a specific schema
Retrieve a schema by version:Creating transactions with a schema
Once a schema exists on a ledger, you must pass theschemaVersion query parameter when creating transactions:
Enforcement modes
Control what happens when validation fails:| Mode | Behavior |
|---|---|
audit (default) | Allow the transaction (validation failures are logged for review) |
strict | Reject the transaction with an error |
Behavior summary
| Scenario | Strict | Audit |
|---|---|---|
| Schema specified, validation passes | ✓ Commits | ✓ Commits |
| Schema specified, validation fails | ✗ Rejects | ⚠ Warns, commits |
| Schema specified but doesn’t exist | ✗ Rejects | ✗ Rejects |
| No schema specified, but schemas exist in ledger | ✗ Rejects | ⚠ Warns, commits |
| No schema specified, no schemas exist | ✓ Commits | ✓ Commits |
When a schema is specified but not found, it’s always an error regardless of mode. The enforcement mode only affects validation failures.
Configuration
Set the mode when starting the server:Transaction templates
Transaction templates let you define reusable Numscript programs in your schema. Instead of sending raw Numscript with each request, your application references a template by name and provides variable values.Defining templates
Templates are defined in thetransactions field alongside the chart:
| Property | Required | Description |
|---|---|---|
script | Yes | The Numscript program to execute |
description | No | Human-readable description of what the template does |
runtime | No | Which Numscript interpreter to use: machine (default) or experimental-interpreter |
Executing templates
To execute a template, pass the template name and variables in thescript field:
- Strings:
"user": "users:alice:wallet" - Monetary values:
"amount": "USD/2 5000"or"amount": { "asset": "USD/2", "amount": 5000 }
When a schema exists with templates, transactions must reference a template. In strict mode, transactions without a template are rejected. In audit mode, a warning is logged but the transaction is allowed.
Example: Payment platform
A complete schema for a payment platform:platform:feesmerchants:mch_abc123def456ghij:availablecustomers:cus_xyz789abc123defg:walletorders:ord_123abc456def789g:refunds:ref_abc123def456ghij
merchants:acme— doesn’t matchmch_prefix patterncustomers:cus_abc:savings—savingsnot defined in chartpayments:xyz—paymentsnot in chart