close
Skip to content

Double-entry ledger APIEvery dollar, accounted for twice.

Marketplaces, payouts, rentals: wherever a buyer, a seller and you all have a claim on the same dollar, Ledfra splits it into balanced entries and refuses any write that doesn't add up.

Event · booking.paid
Guest pays $100.00 for a stay
201 posted
The entries Ledfra writes for one booking
AccountDebitCredit
assets:stripe-clearingCash held at the processor100.00—
liabilities:host/9001Owed to the host, not your revenue—85.00
income:platform-feesThe part you keep—15.00
BalancedΔ 0.00100.00100.00

Guarantees the ledger keeps, so your code doesn't have to.

Enforced at write time

01 · BalanceΔ 0.00
Debits equal credits in every currency, or the write is refused. Not flagged, refused.
02 · Idempotence1×
Retries are safe. A reused key with a different body is a 409, never a silent second posting.
03 · Guards≥ 0
Mark an account as unable to go negative and no posting can take it below zero.
04 · History0 edits
Posted entries are never edited. A correction is a new posting, so the audit trail is the ledger itself.

How it works

Three steps from account to audit.

  1. assets
    stripe-clearing
    liabilities
    host/{id}Template
    income
    platform-fees
    01

    Model your money

    Define the chart once. Templates create one account per user the first time a transaction names it.

  2. POST/api/ledgers/{ledgerId}/transactions
    Idempotency-Key: booking-8812
    entries: 3 · Σ debit = Σ credit
    201 Created
    02

    Post transactions

    One call per business event. It lands balanced and atomic, or not at all.

  3. Platform fees · this month
    $48,215.30
    03

    Query anything

    Balances, P&L and balance sheet, live from the same entries. No nightly job.

Account templates

One balance per user. Zero provisioning.

You can't create a million accounts by hand. You don't have to: name one in a transaction and it exists.

Readable
Slugs like liabilities:user/123, not numbered codes like 2100.
On first use
No pre-provisioning step, and no race when two writes name the same new account at once.
Unlimited
One wallet per user, one payable per seller, as many as you have.
How accounts work
A transaction names liabilities:user/9981, which does not exist yet, so Ledfra creates it from the liabilities:user template.
POST"account": "liabilities:user/9981"
liabilities:user/*template
  • user/1231,240.00
  • user/45688.50
  • user/9981just created50.00
Every other user/…, each created by its first transaction
For developers

An API that reads likethe mental model you already have.

Post a balanced transaction and get back the source of truth: real-time balances, P&L, and balance sheet all derive from it. Double-entry is enforced at the API boundary, so an unbalanced write is rejected, not absorbed.

What a rejection looks like - nothing is written in any of these cases:

400
Debits and credits do not net to zero in some currency.
409
An idempotency key was reused with a different body.
422
The posting would leave a guarded account below zero.
Read the API reference
POST
curl 'https://ledfra.com/api/ledgers/{ledgerId}/transactions' \
  -H "Authorization: Bearer $LEDFRA_KEY" \
  -H 'Idempotency-Key: payout-5f72a1' \
  -H 'Content-Type: application/json' \
  -d '{
    "description": "Marketplace payout",
    "metadata": { "seller_id": "42" },
    "entries": [
      {
        "account": "liabilities:seller/42",
        "operation": "DEBIT",
        "amount": "USD:95.00"
      },
      {
        "account": "assets:cash",
        "operation": "CREDIT",
        "amount": "USD:95.00"
      }
    ]
  }'
For finance teams

Reports that don't need a data engineer.

Every statement is read from the ledger itself, so there is no export, no warehouse copy, and no window where the dashboard and the books disagree.

Close
No nightly jobBalances are current the moment a posting lands.
Time zones
Every team, its own dayA team in New York and a team in Tokyo each see the same ledger rolled up by their own calendar day.
See how reporting works
Income statement
1 to 31 October · USD
Income
Platform fees48,215.30
Subscriptions6,400.00
Total income54,615.30
Expenses
Processor fees(8,112.40)
Hosting(2,950.00)
Total expenses(11,062.40)
Net income43,552.90

Δ 0.00 · since your first posting

Ten minutes to set up.Correct for life.

Post your first transaction

Free to try. No credit card. Sandbox included.

Early Access · closes 31 December 2026

Free for six months. Then a fee that never goes up.

Early Access is the period up to 31 December 2026. A workspace created before it closes carries these commitments from the day it is created, and keeps them.

The fee has a ceiling.
Whatever we publish, the monthly fee for an Early Access workspace never rises above $99.
It lasts as long as the workspace does.
The lock attaches to the workspace on the day it is created, and ends only when the workspace is closed.
Sixty days, and your rate up front.
You’ll see the exact number at least 60 days before the first invoice. There’s no card on file to charge.

Every commitment on this page is written into the agreement you sign.

Read what the price lock means (opens in a new tab)

Growth, at the Early Access rate

$99a month, locked

Growth is $399 a month from 1 January 2027. See the published rates

Months 1 to 6 · $0Then $99 while the workspace stays active
Posted transactions included
30,000 / mo
Beyond that
$10 / 1,000
Seven-leg payout vs two-leg transfer
same price
Reports, reads, failed writes, sandbox
free, always

The lock is on the monthly fee. Transactions past the allotment are billed on top.

Create a workspace before 31 December 2026 and this rate is yours for as long as it stays active.

Start building