PAYMENTS

PERSONAL PROJECT · 2026

LedgerLab

LedgerLab is a small payment system backed by double-entry accounting. The demo lets you create two accounts, post a payment, send the same request again, issue a refund, and inspect the journal entries created by each action. Every transaction records an equal debit and credit, so the journal totals remain balanced.

RuntimePython / FastAPI
HostingRender
DatabaseNeon PostgreSQL
AccountingDouble entry
01 — DemoHOW TO USE IT

Try a payment from start to finish

  1. 01

    Start the ledger. This creates a customer account with $250 and a merchant account with $25.

  2. 02

    Post a payment. Choose an amount and watch both balances and the journal update.

  3. 03

    Replay the request. The API returns the original transaction without moving money a second time.

  4. 04

    Refund $20. Open the payment and refund rows to compare their debit and credit entries.

The API may take up to a minute to start after a period of inactivity. All accounts and transactions in this demo are synthetic.

Starting API

Checking the Python API…

Select “Start demo ledger” to create two synthetic accounts and their opening balances. Demo sessions expire automatically and contain no personal information.

02 — ArchitectureREQUEST FLOW
  1. Next.jsBrowser interface
  2. RenderManaged API hosting
  3. FastAPIPayment and refund endpoints
  4. SQLAlchemyTransactional service layer
  5. NeonManaged PostgreSQL storage

The browser calls the FastAPI service hosted on Render, which reads and writes Neon PostgreSQL in a single database transaction. Before saving a payment, it locks the affected accounts, checks the idempotency key and available balance, then inserts matching debit and credit rows.

03 — Implementation detailsPAYMENTS AND REFUNDS
01

Store currency in cents

The API accepts amounts with up to two decimal places and converts them to integer cents before updating balances or journal entries.

02

Use idempotency keys

Each payment request includes an idempotency key. Sending the same request again returns the original transaction instead of creating another payment.

03

Record refunds separately

A refund creates a new transaction linked to the payment. The original payment remains in the journal, and refunds cannot exceed the amount paid.

04

Use temporary demo sessions

Each visitor receives a separate set of synthetic accounts and transactions. Sessions expire automatically so the demo starts clean for future visitors.

04 — TestsBACKEND COVERAGE

What the test suite covers

API tests cover opening balances, payments, repeated requests, conflicting idempotency keys, overdrafts, partial refunds, and refunds that exceed the original payment. Each response also verifies that total debits and credits match.

Money-formatting tests generate values across the supported range and confirm that converting between dollars and cents does not change the amount.