Fake-AI endpoint bills like the real thing: tokens in + out → atomic credit decrement. Same requestId can hit 5× — you pay once.
Stripe Checkout (test mode) → signed webhook → ledger credit, deduplicated by event.id. Card 4242 4242 4242 4242 works.
Source of truth. No UPDATE, no DELETE — a Postgres trigger raises on both. Balance is derived, never edited by hand.
| # | time | kind | amount | balance after | ref (idempotency key) | meta |
|---|---|---|---|---|---|---|
| loading ledger… | ||||||
Every movement is an immutable ledger row. Mutations blocked at the database layer by trigger.
UNIQUE(ref_id) turns at-least-once delivery — Stripe retries, client storms — into exactly-once billing.
Balance updates in the same transaction as the ledger insert. SUM(ledger) ⇄ balance verified on every poll.
Row-level lock + balance check before charge. Concurrent calls can't spend credits that aren't there.