Nordlet

Blog

What Is a Double-Entry Ledger API for Marketplaces?

A double-entry ledger API records marketplace money movement as balanced, immutable journal entries so you always know who is owed what and why.

Nordlet Team · · 11 min read

A marketplace can look healthy in its orders table and still be wrong about its money. The order says "paid." The seller dashboard shows a balance. But nothing in that table proves how much cash the platform holds, how much it owes each seller, how much of the payment is commission revenue, or how much VAT is now payable. A double-entry ledger API exists to record those financial consequences correctly, one balanced transaction at a time.

Put plainly: a double-entry ledger API is a programmable accounting system. Your application sends it a financial event, such as a captured payment or an approved payout, and the ledger writes that event as a journal with equal debits and credits across named accounts. It does not move money. It records the truth about money that moved elsewhere.

What "double-entry ledger" means here

A ledger is the record of changes to accounts, not a table holding the latest balance. A working ledger has three connected ideas:

  • Account: a named financial position, such as payment processor receivable, seller payable, commission revenue, or VAT payable.
  • Transaction (journal): one atomic financial event containing multiple balanced lines.
  • Entry (posting): a single debit or credit line inside that transaction.

The invariant that holds every design together is simple: total debits equal total credits, for every transaction and every currency. Ledger APIs typically reject an unbalanced write before it reaches storage. Modern Treasury's documentation defines a ledger transaction as involving two or more accounts with at least one debit and one credit of equal totals, and treats a posted transaction as immutable.

Double-entry does not mean exactly two rows. A single marketplace sale often needs one debit and several credits. That is the part people misread most often.

Why marketplaces need a ledger, not just a payments table

A marketplace holds several financial relationships at the same moment. A buyer pays. A processor settles. The platform may temporarily control the funds. The seller earns a portion. The platform keeps a commission. Tax becomes payable. A reserve may be held back. Later, a payout moves money out, and refunds or chargebacks reverse parts of it.

A payments table can tell you the commercial status of an order. It cannot reliably tell you:

  • how much processor receivable or cash exists
  • how much is owed to each seller
  • how much revenue belongs to the platform
  • how much VAT is payable, and in which country
  • what is reserved against refunds or disputes
  • whether a payout reduced the correct seller liability
  • whether processor settlements match what the platform expected

Nordlet's guide to double-entry ledger APIs for marketplace accounting draws the line clearly: application tables describe product state, while the ledger records the financial consequences of that state. It also makes a point worth repeating, that payment-processor reports are inputs for reconciliation, not complete double-entry books.

A worked marketplace sale

Assume a buyer pays €100, the seller is entitled to €85, and the platform commission is €15. Ignore VAT and processor fees for clarity.

Account Debit Credit Reason
Payment processor receivable €100 Processor owes the platform the captured payment
Seller payable €85 Platform owes the seller
Commission revenue €15 Platform earned its commission
Total €100 €100 Balances

The important classification here is that the €85 owed to the seller is a liability, not platform revenue. Under the IFRS conceptual framework, a liability is a present obligation to transfer an economic resource. A marketplace should not report the seller's full sale proceeds as its own income merely because the buyer paid through it. Whether you sit as agent, principal, or deemed supplier changes the treatment, but the ledger mechanism stays the same.

When the seller becomes eligible for payout, no new revenue is recognized. You settle the liability:

Account Debit Credit
Seller payable €85
Bank or payout clearing €85
Total €85 €85

If the processor takes a €3 fee before settling, the cash movement becomes a three-line journal: €97 to bank cash, €3 to processing expense, €100 out of processor receivable. Every change in position has a source and a destination.

How the API works, step by step

1. Your application detects a business event. A payment is captured, an order is fulfilled, a payout is approved, a refund is issued, a chargeback opens, a settlement lands. Your database still owns operational state. The ledger records the monetary effect.

2. You send a structured request. It usually carries event type, amount and currency, order or payment ID, buyer and seller identifiers, commission, tax data, the accounts involved, effective and posting dates, an idempotency key, and metadata linking back to processor and product records. Nordlet's public API example shows a conceptual sale request with a seller ID, sale type, amount, currency, and VAT country and rate.

3. The API validates. It checks that debits and credits balance, the accounts exist and are postable, the currency is supported, the amount uses precise minor-unit handling, the idempotency key is not reused for a different result, the period is open, and required metadata is present. A failed check leaves no partial journal behind.

4. It posts atomically. The full transaction writes as one unit. You should never be able to record the debit while the matching credit fails. For a marketplace, a partial split could create an apparent seller balance with no corresponding cash, or book commission without the seller obligation.

5. Balances and reports derive from the ledger. After posting, you can read account balances, seller pending and available balances, a trial balance, general-ledger activity, VAT summaries, and history as of a past date. The seller balance should be rebuildable from postings, not trusted from a mutable field.

6. Webhooks notify your product. Events like sale_invoice.paid, a posted journal, an available payout, or a reconciliation exception get pushed to you. Process them idempotently. A webhook is a notification, not permission to apply the financial event a second time. The API conventions cover scopes, idempotency keys, error shapes, and webhook signing in detail.

Seller balances are not a single number

Most marketplaces get into trouble by treating a seller balance as one figure. Money should sit in states:

State Meaning
Pending Seller may be entitled, but release conditions are not met
Available Eligible for payout
Reserved Withheld against refunds, returns, or disputes
Paid out Obligation settled by a transfer
Negative Refunds, chargebacks, or fees exceed available funds

Processor models mirror this. Stripe's separate charges and transfers flow lets a platform charge its own account, then transfer portions to connected accounts, with fees, refunds, and chargebacks landing on the platform balance. Adyen's marketplace model distinguishes user balance accounts, which hold funds until payout, from a liable balance account that can absorb negative balances from refunds or chargebacks. These are useful inputs to your ledger. They are not your complete accounting model.

Payouts and seller earnings happen at different times

A seller can earn on Monday and get paid on the following Monday. Between those points, an order gets fulfilled, a reserve is held, a payout batch is built, a processor settles it net of fees, and a bank deposit arrives. A ledger has to preserve each stage instead of overwriting the order with a final "paid." That is what lets you explain timing differences between order activity, seller entitlement, settlement, payout initiation, and bank receipt.

Refunds and chargebacks: reverse, do not rewrite

Refunds and chargebacks are new events linked to the original payment. In an immutable ledger, you correct with a reversing entry followed by a corrected one, so the original stays visible for audit. Modern Treasury treats posted transactions as immutable and supports idempotency keys to prevent duplicate objects on retry.

A refund typically reduces cash or buyer receivable, reverses seller payable, may reverse part of commission depending on policy, adjusts tax, and can consume a refund reserve. A chargeback reduces cash or processor receivable, may reopen an amount owed by the seller or platform, records a dispute expense and processor fee, and moves funds through a reserve account.

Reconciliation: connecting the ledger to real money

A ledger can be internally balanced and still be wrong about the outside world. Reconciliation compares internal records against external evidence: processor settlement reports, bank statements, payout files, refund and dispute records.

A workable loop looks like this:

  1. Import the settlement or bank batch.
  2. Match each line to an order, payment, refund, fee, payout, or dispute.
  3. Compare expected gross, deductions, reserves, and net.
  4. Post confirmed movements to the ledger.
  5. Send unmatched items to a named suspense account.
  6. Investigate exceptions.
  7. Lock the period.

Nordlet's reconciliation material describes exactly this, importing settlement batches, matching charge and refund lines, and routing unmatched receipts to suspense rather than guessing an invoice. Two checks matter and neither replaces the other: double-entry validation asks whether each journal balances, and reconciliation asks whether it agrees with the processor, bank, and business event.

Design details that decide whether you get this right

Idempotency. Tie the key to a stable event, such as payment_captured:pi_123. A retry returns the original result, not a second journal.

Atomicity. All lines of one event post together or none do.

Immutability and reversals. Posted history is not editable through ordinary updates. Corrections create linked entries that preserve the original amount, date, classification, reason, and author.

Precise money. No binary floating point. Use integer minor units or exact decimals, explicit currency, and a deterministic rounding rule for splits. Split €100 across sellers and fees without one, and a stray cent will break your balance.

Effective vs posting dates. When the buyer paid, when the seller earned, when the bank settled, and when the entry posted are different dates. Conflating them makes period reporting and tax timing unreliable.

Multi-currency. Debit and credit should balance within a currency. Conversion needs an explicit rate event with accounts for the fee, rounding, and any FX gain or loss. Accepting a currency field does not make a ledger an FX engine.

What a ledger API will not do for you

It will not decide your chart of accounts. You still have to determine whether you are principal or agent, when commission is earned, which party bears processor fees, how refunds affect commission, and how VAT is calculated and reported. Nordlet's own guidance is to map the money flows first, draft the chart of accounts, get an accountant to review it, then implement one full flow from order through payout and reconciliation before scaling.

It will not settle tax questions. VAT depends on buyer and seller location, product type, registration status, and deemed-supplier rules; the EU VAT guide sets out what the engine derives and what it flags for a human. Nordlet's VAT coverage is EU and EEA focused, so it does not extend to US sales tax or Latin American e-invoicing. And it will not resolve operational ambiguity, whether a return window closed, whether a payout should be blocked, whether a payment is fraudulent. Those are your decisions. The ledger records their financial result.

Where Nordlet fits

Nordlet is an accounting API built for platforms and marketplaces, with an immutable double-entry ledger, payouts, EU VAT handling, REST endpoints, typed SDKs, and webhooks reachable through one surface. Its distinguishing choice is embedded accounting inside your own product rather than a third-party checkout. As of this writing the product is in early access with a sandbox for design partners, so treat it as a strong example of the category and evaluate production maturity, uptime, and jurisdictional coverage for your own case before committing.

For marketplace and platform developers, the useful mental model is the split between payment movement and financial truth. Your processor moves the money. A double-entry ledger API records who is owed what, what you earned, what tax and reserves you carry, and whether the outside world reconciles to your books.

FAQ

Is a double-entry ledger API the same as a payment processor?

No. A processor authorizes, captures, settles, and sometimes pays out funds. A ledger API records the accounting consequences of those events. Most marketplaces use both, a processor like Stripe or Adyen for movement and a ledger for the books.

Can I just use my processor's dashboard as the general ledger?

You can try, and it will fail an audit eventually. Processor reporting shows charges, fees, transfers, and settlements, but it usually does not represent your full seller obligations, tax liabilities, non-processor expenses, or accounting adjustments. Treat it as a reconciliation input.

Does a balanced ledger mean my books are correct?

Only that your entries satisfy the debit-credit rule. A perfectly balanced transaction can still be posted to the wrong account, to the wrong seller, or with the wrong tax treatment. Balance is necessary, not sufficient. Reconciliation is what catches the rest.

If the ledger is immutable, how do I fix mistakes?

You post a reversing entry and then a corrected one. The original stays visible, which is the whole point. Immutability protects the audit trail, it does not trap your errors.

Does an accounting API make me compliant automatically?

No. It enforces accounting structure and produces usable records. Legal compliance still depends on your jurisdiction, contractual role, tax treatment, payment regulations, KYC and AML processes, and reporting obligations.

Further reading