Demo
using demo key

Overview

A double-entry ledger for . Every transaction sums to zero.

New here? Read this first.

go-ledger has no user interface of its own. It is an API. The actual product is a set of HTTP endpoints your app calls to create accounts, move money, and read reports. There is no shipped dashboard, no login form, no admin panel. The API is the product.

This page is a demo. I built this small UI on top of those same APIs so you can click around and see what the ledger does, without writing any code. Every button and form here fires a real API call against the live server. Nothing is faked or hardcoded.

Want to see the API itself? Open the API Playground. Every endpoint used on this page is documented there, with example requests and responses you can send straight from your browser.

go-ledger is an open-source, multi-tenant, double-entry payment ledger written in Go. Money moves as balanced transactions: every set of postings sums to zero, so funds are never created or lost, only shifted between accounts. This demo is a thin client over the live API.

  • Double-entry core zero-sum postings, balances derived from history, never edited in place
  • Multi-tenant isolated ledgers, each with its own accounts, keys and policy
  • Multi-currency the zero-sum invariant holds per currency, with FX conversion
  • Operator surface tenants, API keys, webhook subscriptions and guardrail policy
  • Reporting trial balance proof, transaction search and disputes
  • Tamper-evident append-only audit chain and idempotent posting

Accounts

The buckets money moves between. Balances are derived from postings, never edited directly.

All accounts

Double-entry sign convention: debits are positive, credits are negative, and every currency nets to zero across all accounts. Credit-normal accounts (income, liability, equity) therefore carry negative balances, so a growing income shows as a larger negative number. That is the balance working, not a mistake.

Post a transaction

Move money as a set of postings. Positive amounts debit an account, negative amounts credit it. The set must sum to zero, so every posting here is in one currency. To move between currencies, use Convert currency.

Pick an account below to set the currency.
Balance: 0.00 Balanced, ready to post
Advanced
Every post sends a fresh Idempotency-Key automatically, so a double click never posts twice.

Convert currency

Move money between two accounts in different currencies. The server applies the exchange rate and markup and posts the balanced legs for you.

How it works. Pick the account to take money from and the account to move it into. They must be in different currencies, and a rate for that pair must exist (set them in Settings). Enter the amount in the from account's currency, and the amount the other account receives is calculated for you.

Plain transactions stay single-currency. Post a transaction requires every posting in one currency (they must sum to zero). Crossing currencies is this page, because it needs a rate.

Recipient gets: - Pick two accounts and an amount

Statement

A running-balance view of a single account.

Tenants

Isolated ledgers. Each tenant has its own accounts, keys and policy.

All tenants

API keys

Keys for . Secrets are hashed at rest and shown only once.

Keys

Webhooks

POST notifications when things happen in the ledger for .

Endpoints

Policy

Approval workflow (ADR-025)

Server-wide and read only here. A transaction that crosses a threshold is held; see it under Approvals.

Loading…

Guardrails for . Everything here is optional. Saving writes the full policy: an empty field clears that guardrail.

Largest absolute posting amount allowed in one transaction (major units).
Total posted volume per calendar day (major units).

Trial balance

The core invariant: every currency nets to zero across all accounts.

Per-account balances

Transactions

Everything posted to this tenant.

Audit log

Every change to the ledger, append-only and tamper-evident. Each row is hash-chained to the one before it, so a silent edit is detectable.

Recompute every row's hash from genesis and confirm nothing was altered.

Disputes

Transactions under review. Funds stay reserved until resolution.

Approvals

Transactions held because they crossed the tenant's approval threshold (ADR-025). Nothing posts until a decision is made.

Settings

Local to this browser. Nothing here is sent anywhere except with your API calls.

API key

Stored in this browser's localStorage under goledger_admin_key. Sent only to this server as an Authorization: Bearer header. Never sent to any other origin and never logged by this page.

Workspace

Scopes the whole demo to this tenant: the ledger and reporting views as well as the admin panels. With an admin key the server isolates each view to the selected tenant; a non-admin key stays on its own tenant.
Demo Public demo server, resets every hour.

About

go-ledger is an open-source, multi-tenant, double-entry payment ledger written in Go. Every transaction is a set of postings that sums to zero, so money is never created or lost, only moved. Source and docs at go.sohag.pro.