Skip to content

One wallet, one ledger, and a saga that cannot lose a movement.

Every merchant holds one funded wallet. Cards are issued against it, spending draws from it, and withdrawals return from it. Nothing moves without posting balanced legs to a ledger that is only ever appended to.

Wallets

One wallet per merchant, in integer minor units.

A merchant wallet holds a balance in integer minor units — cents, not decimals. No floating-point value exists anywhere in the money path, so no rounding error can accumulate across a million movements. Balances are derived from the ledger rather than trusted as a running total, and an hourly watchdog re-derives them and alerts on any drift.

Unit
integer minor units (BIGINT)
Balance source
derived from ledger entries
Drift watchdog
hourly, alerts on mismatch

Deposits

Funding arrives as crypto, credited on confirmation.

A merchant requests a permanent per-network deposit address. Funds sent to it are credited to the wallet once confirmed, as a balanced movement like any other. Deposit settlement runs in two phases — the provider notifies, then the platform fetches the authoritative record — so a notification that carries no amount can never credit the wrong figure. An hourly reconciliation sweep re-checks anything a webhook missed, idempotently.

Addresses
permanent, per network
Settlement
two-phase: notify, then fetch record
Fallback
hourly reconciliation, idempotent

Issuing

Cards are issued through hold, provider, settle.

Issuing places a hold on the wallet for the initial load plus the product issue fee, calls the licensed issuing partner outside the database transaction, and settles the movement to the ledger on success. The provider call never runs inside a transaction or a lock, so a slow or failed issuer cannot hold a merchant's wallet open. Where the partner provisions asynchronously, the call returns a pending card and the same settlement runs later from the partner's webhook or from reconciliation — either path, once only.

Saga
hold → provider → settle
Provider call
never inside a transaction or lock
Async result
202 pending, settled by webhook or sweep

Cardholders

Identity is stored once, encrypted, and reused.

Cardholder identity lives in a customer registry rather than being re-sent with every request. Records are encrypted at rest and submitted to the issuing partner only inside an issue request. Card numbers and security codes are never exposed through the API and never persisted — a card resource carries a masked number and its last four digits, nothing more.

Storage
encrypted at rest
PAN / CVV
never exposed, never persisted
Card resource
masked number + last four only

Authorizations

Spending resolves to legs that sum to zero.

An authorization does not mutate a balance. It posts a movement whose debit and credit legs are equal and opposite, so the movement nets to zero and the balance is whatever the ledger says it is when you read it back. Corrections are posted as new entries, never as edits. Nothing in the ledger is ever updated or deleted.

Ledger
insert-only
Every movement
minimum two balanced legs
Corrections
posted as new entries

Withdrawals

Money leaves through an approval loop, not an API call.

Withdrawals have no public API. A merchant requests one from the portal, a platform operator approves it, and completion is recorded with its payout proof. Every state change is written to an insert-only audit trail with the actor who made it. This is deliberate: the endpoint that moves money out of the platform is the one endpoint that should not be reachable by a leaked API key.

Public API
none — portal and admin only
Flow
request → approve → complete
Audit
every transition, with actor

Reporting

Figures are read from the ledger, not from a counter.

Nightly aggregates are built from ledger entries rather than from a denormalised revenue column, so a report and the underlying money cannot disagree. Test-mode activity is excluded structurally by a join rather than by a filter someone has to remember to apply.

Source
ledger entries
Schedule
nightly
Test activity
excluded structurally

Where this stands today.

The platform runs against a simulated card provider by default. The first real issuing integration is built and sandbox-certified, and it moves to production once credentials and a webhook secret are confirmed with the partner. Crypto deposit signing is implemented and awaits live certification.

Until those are complete this page describes behaviour that is implemented and tested, not a live issuing service. We would rather say that here than have you find it out during an integration.

Sign in