Tenancy, Isolation, and the Ledger Core

If you're evaluating Paprel as the accounting layer under your product, the architecture question usually comes in two halves: how is my customers' data kept apart? and what actually guarantees the books are right? This article answers both, layer by layer — tenancy, the ledger engine, the workflow layer on top of it, and the reporting layer that reads it all back.

None of this is aspirational. It's the same structure described on the embedded accounting page, running in production today.

Multi-tenancy: a company is the boundary

Everything in Paprel belongs to a company. The company is simultaneously the tenant boundary, the set of books, and the reporting entity. In an embedded setup, you typically create one company per customer of your platform — one API call, and that customer has isolated books of their own.

Two properties matter here:

Company-scoped access. Review tenant-boundary enforcement, token permissions and privileged access with the deployment team. Validate isolation for the supported integration; this architectural overview is not a guarantee that implementation defects are impossible.

A company is born with working books. Provisioning seeds each company with its own ledger, document numbering, and a default chart of accounts based on a standard taxonomy — assets, liabilities, equity, income, expenses. You extend that tree rather than designing one from scratch, and because every later posting lands on an account in this tree, the reports in the last section work with zero reporting configuration on your side.

The ledger engine: append-only, balanced, or rejected

Underneath everything is a double-entry ledger with three load-bearing rules.

Journals are the primitive. Everything in Paprel — an invoice posting revenue, a payment clearing a receivable, a manual adjustment — ultimately compiles down to journal entries: balanced sets of debit and credit lines against accounts in the chart. There is no second bookkeeping mechanism off to the side. If a number appears in a report, there is a journal line behind it.

Balanced or rejected, at the API boundary. Debits must equal credits, and the check happens at write time. There is no code path that lets an unbalanced entry through and no "fix it in a nightly job" reconciliation step — an unbalanced posting is rejected before it exists.

Append-only, with versioning instead of mutation. Posted journal lines are not edited in place; corrections are new entries. Documents (the layer above, covered next) are versioned: every edit creates a new version while a stable anchor_id survives across all of them. The anchor is what you store, link to, and pay against; the version history is what an auditor walks. Combined with the applicable activity history and agreed retention and export features — "what did the books say, and who changed them, and when" is a query, not an investigation.

The write path is idempotent throughout: retried a request because of a timeout? Resubmitting returns the original result instead of double-posting.

The workflow layer: documents that generate journals

Most teams don't want to hand-write journals, and most of the time they shouldn't have to. The workflow layer is where invoices, bills, credit notes, and expenses live — business documents whose state changes generate the journals for you.

Post an invoice and a balanced journal debits receivables and credits the revenue account the line items map to. Record the payment and a second journal moves the money from receivables to cash — the invoice flips to paid, the customer's balance drops, and revenue stays where it was earned. You never wrote either journal; the document did, through account mappings decided once by whoever understood the books.

The lifecycle around those state changes is configurable. Document statuses and approval gates — draft → reviewed → approved → sent, or whatever your operators need — are defined per company via the status settings, and every transition lands in the same audit history as the postings themselves. So the workflow layer is not a convenience wrapper that bypasses the ledger's guarantees; it is a compiler into them.

The reporting layer: derived, never reconciled

Reports in Paprel — P&L, balance sheet, trial balance, GL export — are derived live from the journal rows. They are not a separate datastore that gets synced with the ledger and periodically reconciled against it; they are views over the same rows the engine wrote.

Balanced postings support a consistent trial balance. Customers must still validate mappings, completeness and reporting behavior for their accounting requirements. The same property means there is no end-of-day batch to wait for: post an invoice, and the P&L reflects it on the next read.

The three tiers, end to end

Text
┌─────────────────────────────────────────────────┐
│  YOUR PLATFORM                                  │
│  orders · wallets · billing · custom events     │
└───────────────────────┬─────────────────────────┘
                        │  POST · idempotent
                        ▼
┌─────────────────────────────────────────────────┐
│  PAPREL CORE              (isolated per tenant) │
│                                                 │
│   ingest ──▶ validate ──▶ post (double-entry)   │
│                                                 │
│   ledger (append-only)    audit log (signed,    │
│                           7yr retention)        │
└───────────────────────┬─────────────────────────┘
                        │  GET · webhooks (signed) · export
                        ▼
┌─────────────────────────────────────────────────┐
│  READ SURFACES                                  │
│  P&L · balance sheet · trial balance ·          │
│  GL export · audit trail · signed webhooks      │
└─────────────────────────────────────────────────┘

Your application emits events over idempotent REST (or the SDK, or MCP). The core validates them against the schema and the chart of accounts, posts balanced journals into the append-only ledger, and records everything in the signed audit log. Read surfaces — reports, CSV/JSON exports, signed webhooks carrying content hashes so downstream systems can verify exactly what happened — all pull from that single source of truth. Confirm hosting providers, assurance scope and processing locations in the deployment schedule.

What this buys you

The layering is the point. Tenancy means one API call gives each of your customers their own books, isolated below your code. The engine means those books cannot go out of balance. The workflow layer means your product speaks in invoices and payments, not debits and credits. And the reporting layer means the numbers your customers' accountants see are the ledger — not a copy of it.

Where to go next:

Evaluate Paprel

Build in sandbox, launch with a production trial

Use sandbox for developer testing with no billing. When you are ready for real workflows, start production on a monthly plan with a 14-day free trial.

API-First Delivery
Audit-Ready Controls
Sandbox And Guided Rollout
We use cookies to improve your experience.

We use cookies and local storage for essential settings and, with your choices, analytics and advertising. Online identifiers and activity can be personal data. You can reject optional categories or change your choices.

These cookies are necessary for the basic functionality of the website, ensuring a seamless user experience. They cannot be disabled.