Double-entry ledger API | Southpay Ledger Preview<br>Private preview, early access for developers
The double-entry ledger you call, not the one you maintain.
Accounts, transactions, and balances that reconcile by construction, not by a<br>nightly job. Fiat, stablecoins, and crypto from the first call, idempotent by<br>design, append-only by default. The primitives you'd otherwise spend a quarter getting right, live<br>behind an API key today.
already on the waitlist
Request access
We email a confirmation now and your keys when a slot opens. Nothing else.
Free tier for development · Pricing at GA · Self-serve, no sales call
We store your email only to manage preview access. Ask us to delete it anytime:<br>daniel@southpay.io.
POST /transactions 201 response GET /balance
# Post a balanced, multi-currency transaction<br>POST /api/v1/transactions<br>Authorization: Bearer $SOUTHPAY_TOKEN<br>Idempotency-Key: idem_9f1c2a44
"postings": [<br>{ "account": "cash:acme", "direction": "debit",<br>"amount": 42000, "currency": "USD" },<br>{ "account": "revenue:acme", "direction": "credit",<br>"amount": 42000, "currency": "USD" }<br>],<br>"metadata": { "invoice": "inv_8c21f9" }<br>} // 201 Created · debits == credits, per currency<br>"data": {<br>"object": "transaction",<br>"id": "b1f0c2e4-9a77-4e2a-9d51-7c0e2a1b8f44",<br>"status": "posted",<br>"idempotency_key": "idem_9f1c2a44",<br>"postings": [ // 2 balanced postings, debit + credit ],<br>"created_at": "2026-06-08T09:12:04Z"<br>},<br>"livemode": true,<br>"request_id": "req_8a3f2c"<br>} GET /api/v1/accounts/cash:acme/balance
// 200 OK<br>"data": {<br>"object": "balance",<br>"account": "cash:acme",<br>"currency": "USD",<br>"posted": 42000,<br>"pending": 0,<br>"available": 42000<br>},<br>"livemode": true,<br>"request_id": "req_5f3c1b"
In production today. Southpay runs this<br>double-entry ledger in crypto payments, reconciling real customer balances every day.<br>We pulled the invariant-keeping core into its own service, so you build on it instead of<br>rebuilding it.<br>southpay.io
What you get<br>A double-entry ledger API with the hard parts handled.
You could build this on Postgres. Most teams do, then spend a quarter chasing balance<br>races, double-posts, and reconciliation drift. Start one layer up.
Balances that can't drift<br>Every transaction balances per currency, checked server-side before it commits. Corrections are reversals, never edits, so history stays append-only. The books reconcile after every write, not on a nightly job.
Multi-currency is a primitive<br>Fiat, stablecoins, and crypto in one balanced ledger. USD, EUR, USDC, BTC, any token symbol, in integer minor units. No floats, no silent single-currency assumptions.
Built for retries<br>Durable idempotency keys, separate pending and posted balances, and webhooks on every posted transaction. Your integration replays cleanly because ours does.
The model<br>Four primitives. Nothing more to learn.
You write the business logic. We keep the books.
Account<br>A balance in one currency, in a chart of accounts you define. Asset, liability, revenue, expense, or equity.
Transaction<br>A balanced set of postings, made idempotent by a key you supply. Written once, immutable after.
Posting<br>A single debit or credit in integer minor units. Append-only, never updated in place.
Balance<br>Available, pending, and posted views, derived from postings and always reconciled.
Also included<br>Everything around the ledger, too.
Webhooks<br>Fire on every posted transaction, delivered replay-safe.
Reconciliation<br>Match postings against the outside world and flag what is off-book.
Reversals<br>Correct with a reversing transaction. History is never edited.
Period close<br>Lock a period so closed books cannot change.
Export<br>Stream the full journal out, append-only and ordered, for audit or BI.
Account templates<br>Define your own chart of accounts, enforced per template.
Test + live mode<br>Separate keys and data. Every response says which mode it is.
Connectors Soon<br>Pull money movement from external systems into the ledger, no glue code.
SDKs Soon<br>TypeScript, Python, Ruby, Go.
FAQ<br>Common questions from teams evaluating ledgers.
What is a double-entry ledger API?<br>A double-entry ledger API is a service that keeps financial records over HTTP. Every transaction is a set of postings where debits equal credits per currency, so account balances always reconcile. You integrate accounts, transactions, and balances through REST endpoints instead of building ledger tables, invariants, and reconciliation jobs yourself.<br>Why use a ledger API instead of building on Postgres?<br>You can build a ledger on Postgres, and most teams start there. The hard part comes after: balance races under concurrent writes, double-posting on retries, drift between your ledger and the outside world. A ledger API gives you those guarantees from the first call, so the quarter goes into your product instead.<br>How does multi-currency work?<br>Every posting carries an explicit currency and an integer amount in minor units. Transactions balance per currency, and an account holds a...