Nordlet

Blog

Double-Entry Ledger APIs for Marketplace Accounting

A technical guide to how immutable double-entry ledger APIs work, why marketplaces need them, and what to look for when embedding accounting into your platform.

Most marketplaces discover they have an accounting problem the same way: a finance hire arrives, opens the payouts spreadsheet, and asks who is actually recording the liability to sellers between the moment a buyer pays and the moment funds leave the platform account. The engineering team points to a transactions table. The finance hire points out that a table of events is not a set of books. That gap, between event data and real accounting, is what a double-entry ledger API is built to close.

This is a technical question with regulatory teeth. Marketplaces hold other people's money, calculate VAT across jurisdictions, and issue invoices on behalf of sellers. Doing that with a homegrown transactions table works until an auditor, a tax authority, or a serious buyer asks for proof.

What a double-entry ledger API actually is

A double-entry ledger API is a programmable accounting engine exposed over HTTP. Every financial event your platform records is written as a balanced journal entry: at least one debit and one credit, equal in total, posted to named accounts in a chart of accounts. The API enforces that balance at write time and stores entries so that they cannot be silently edited later.

The "double-entry" part is the four-hundred-year-old accounting rule that every transaction affects at least two accounts. The "API" part means your product, not a human bookkeeper, is the caller. The "immutable" part means corrections happen through reversing entries, not by editing history. Together, these three properties are what makes the resulting books audit-ready rather than merely tidy.

A useful working definition:

A double-entry ledger API accepts financial events from your application, converts each one into a balanced journal entry against a defined chart of accounts, stores those entries immutably, and exposes the resulting ledger, trial balance, and financial reports through predictable endpoints.

Nordlet is built around exactly this idea: real books as an API, with the ledger, VAT logic, invoicing, and reconciliation all reachable from the same set of endpoints your product already talks to.

Why marketplaces specifically need this

A single-merchant SaaS can often get away with syncing to a general accounting tool once a day. Marketplaces cannot, for three reasons.

First, they sit in the middle of the money. A buyer pays the platform, the platform holds funds, then pays sellers minus fees. Each of those movements is a distinct accounting event affecting different accounts: cash, seller payables, platform revenue, VAT payable, refund reserves. A payments table with a status column does not capture that.

Second, they operate across tax jurisdictions. An EU marketplace with sellers in Lithuania, Germany, and Poland, and buyers across the bloc, has to apply the correct VAT treatment per transaction, validate seller VAT numbers against VIES, and produce filings that satisfy each local authority. Getting this right in application code, then reconciling it against a separate accounting system, is where most marketplaces quietly break.

Third, the volume is wrong for manual bookkeeping. A platform doing ten thousand orders a month is producing tens of thousands of journal entries. That has to be automated end to end, or the finance team becomes a bottleneck on growth.

How the API works, step by step

The mechanics are less exotic than they sound. A typical flow for a marketplace order looks like this.

1. Your platform emits a financial event. A buyer completes checkout. Your backend calls the ledger API with something like: order ID, buyer, seller, gross amount, VAT rate, platform commission, currency, and an idempotency key.

2. The ledger constructs a journal entry. The API translates that event into debits and credits. For a straightforward marketplace sale, that might mean debiting a cash-in-transit account, crediting a seller payable account for the net amount, crediting a platform revenue account for the commission, and crediting a VAT payable account for the tax portion. All balanced. All posted atomically.

3. The entry is written immutably. Once posted, the entry has an identifier and a timestamp and cannot be edited. If something is wrong, you post a reversing entry and a corrected one. The audit trail is the point.

4. Downstream reports update in real time. The trial balance, seller payable balances, VAT summaries, and P&L reflect the new entry immediately. There is no nightly job, no export, no reconciliation window where the numbers are "settling."

5. Webhooks notify your system. Events like sale_invoice.paid or bank_transaction.matched fire to your endpoints, so your product can react without polling. Combined with idempotency keys, this means retries are safe and duplicates do not sneak in when the network hiccups.

The important design point: the ledger is the source of truth for what happened financially. Your application database is the source of truth for product state. The two systems reconcile because the ledger is written from application events, not the other way around.

The chart of accounts is where the design work happens

Most of the intellectual effort in setting up a ledger for a marketplace is in the chart of accounts. This is the list of named buckets that debits and credits land in: cash accounts per bank, seller payable accounts (often one per seller or one aggregate with sub-ledgers), platform revenue by category, VAT payable per country, refund reserves, chargeback reserves, and so on.

A few patterns that repeat across marketplaces:

  • Seller funds are a liability, not revenue. Money you hold on behalf of sellers is a payable. Treating it as revenue and "expensing" the payout later is the classic mistake that shows up in due diligence.
  • VAT is a separate liability per country. If you operate across EU jurisdictions, you want distinct VAT payable accounts per country so filings map cleanly.
  • Fees have to be modeled at the moment they are earned, not when they are paid out. Accrual accounting is not optional here.
  • Refunds, chargebacks, and disputes each need their own accounts so the P&L reflects reality rather than a churn of positive and negative sales.

A good ledger API lets you define this structure once and then post to it with confidence, rather than reinventing the accounting logic inside your checkout code.

Immutability, period locking, and why auditors care

Immutability sounds like a database detail. It is actually the difference between books an auditor will sign off on and books they will not.

If a marketplace can silently edit last quarter's entries, then last quarter's numbers are, in an accounting sense, unknowable. An immutable ledger enforces the rule that history is history. Corrections are visible as corrections. Period locking extends this: once a month is closed, no new entries or edits can land in that period without an explicit reopen action, which is itself logged.

For platforms that will eventually raise funding, sell, or face a tax audit, this is not a "nice to have." It is the thing that makes the books defensible. Nordlet's ledger is designed around this by default, with the immutable double-entry structure and period locking built in rather than bolted on.

EU VAT: the part that eats engineering time

VAT is where most marketplace accounting projects overrun. The rules are not simply "apply a percentage." They depend on where the buyer is, where the seller is, what is being sold, whether the seller is VAT-registered, whether the marketplace is deemed supplier under the 2021 e-commerce rules, and which reporting regime applies locally.

A serious ledger API for the EU handles at least:

  • VIES validation for seller and buyer VAT numbers, ideally with results cached and stamped on the transaction
  • Per-country VAT rate logic including reduced rates and exemptions
  • i.SAF register generation for Lithuanian filings, and equivalent structured outputs where other member states require them
  • Peppol BIS 3.0 e-invoicing for jurisdictions moving to mandatory electronic invoicing
  • OSS/IOSS handling for cross-border B2C sales

Doing this in application code, per country, is a full engineering team's worth of work that never really finishes because the rules keep changing. Pushing it into the ledger layer is the pragmatic call.

Reconciliation is where the time savings show up

Once the ledger is the source of truth, bank reconciliation stops being a monthly ordeal. Bank statements come in, the ledger already knows what should be there, and matching is largely automatic.

The realistic version of this is not "zero manual work." It is "the exceptions surface themselves." A one-click reconciliation flow for the ninety percent of transactions that match cleanly, plus a queue of the ten percent that need a human decision, is roughly what a well-designed reconciliation API delivers. Smart payment matching handles partial payments, overpayments, and payments that cover multiple invoices without a human writing rules for each case.

SEPA export (pain.001 format) for supplier and seller payouts closes the loop on the outgoing side. You approve payouts in your product, the ledger generates the SEPA file, your bank processes it, and the resulting movement is reconciled back automatically.

Build vs. buy vs. embed

Marketplace teams tend to consider three paths. Here is how they compare on the axes that matter.

Approach Time to production Audit-readiness EU VAT handling Fits inside your product
Build your own ledger 12 to 24+ months Depends entirely on your team You build it, per country Yes
Sync to Xero/QuickBooks Weeks Good for the accounting side, weak for marketplace-specific flows Partial, add-ons required No, lives in a separate tool
Embed a ledger API (e.g., Nordlet) Weeks Built in via immutable ledger and period locking Built in for EU, including VIES and i.SAF Yes, via API and SDKs

Building your own is defensible if accounting is your product. For everyone else, the math rarely works. Syncing to a traditional accounting tool works for single-entity businesses but strains under marketplace flows: split payments, seller sub-ledgers, per-country VAT, and platform-as-deemed-supplier scenarios do not map cleanly to tools designed for one company's books.

Embedding an API-first ledger is what most modern platforms are converging on. The books live inside your product's experience, sellers see their own financials in your UI, and the compliance heavy lifting is handled at the infrastructure layer.

What to look for when evaluating a ledger API

A short checklist worth keeping open during vendor calls:

  • Immutable double-entry storage with reversing-entry corrections, not editable rows
  • Period locking with logged reopen actions
  • Idempotency keys on every write endpoint
  • Webhooks for the events your product needs to react to, not just a polling API
  • Typed SDKs in the languages your team actually uses
  • Per-country VAT logic including VIES, i.SAF or equivalents, and OSS/IOSS
  • Multi-company support if you operate multiple entities or plan to
  • Role-based access granular enough to separate developers, accountants, and viewers
  • Report exports in XLSX, PDF, and JSON, with webhook notifications when large reports are ready
  • A sandbox that mirrors production behavior, not a stripped-down demo

If a vendor cannot demonstrate the first three in a technical call, the rest does not matter.

What I would do first

If a marketplace is starting this work from scratch, the sequence that saves the most pain:

  1. Map the actual money flows on a whiteboard before writing any code. Who owes whom, at what moment, in what currency, with what VAT treatment.
  2. Draft the chart of accounts from that map. Seller payables, platform revenue, VAT payable per country, reserves. Get an accountant to review it before it goes into production.
  3. Pick the ledger layer. Build, sync, or embed. Be honest about which one your team can actually deliver and maintain.
  4. Implement one flow end to end: order to invoice to payout to reconciliation. Prove it balances. Then scale.
  5. Turn on period locking as soon as the first month closes cleanly. The discipline compounds.

The teams that get this right treat the ledger as core infrastructure, not a reporting afterthought. That is the shift, and it is what makes the finance conversation with an auditor, an investor, or a tax authority a short one instead of a long one.

FAQ

Is a double-entry ledger API the same as an accounting integration?

No. An integration syncs data from your product into an external accounting tool, usually on a delay. A ledger API is the accounting system, written to directly, in real time. The distinction matters because integrations lose fidelity at the edges: partial payments, multi-currency, marketplace splits. A ledger API records these natively.

Can we not just use Stripe's or Adyen's reporting?

Payment processor reports tell you what moved through the processor. They are not double-entry books. They do not know about your seller payables that have not been paid out yet, your VAT liabilities across countries, or your non-payment-processor expenses. They are one input into the ledger, not a replacement for it.

How immutable is immutable in practice?

Entries cannot be edited. Corrections are new entries that reference the original. This is a design decision, not a technology one. Any competent ledger will enforce it. The reason to care is that "we edited it to match the bank" is exactly the pattern that makes books untrustworthy.

What about non-EU marketplaces?

The double-entry mechanics are universal. The tax logic is not. A ledger API tuned for EU VAT will handle EU-heavy operations well and can support non-EU transactions, but if your primary market is US sales tax or Latin American e-invoicing regimes, verify the specific compliance coverage before committing.

How long does implementation actually take?

For a marketplace with a clean event model, embedding a ledger API to the point of running one flow end to end is typically a few weeks of engineering. Full migration from a legacy setup, including historical data, takes longer. The variable is almost always the state of the existing data, not the API itself.