Skip to main content

What is double-entry accounting?

Double-entry accounting is a bookkeeping system where every financial transaction affects at least two accounts. For every transaction, the total debits must equal the total credits. This fundamental principle ensures that your ledger always balances and provides a complete audit trail of all financial movements. In double-entry accounting:
  • Every transaction has two sides: a debit and a credit
  • Debits must equal credits: the accounting equation always balances
  • Each account tracks separately: credits and debits are maintained independently
  • Complete audit trail: you can trace every movement of funds

The accounting equation

At the heart of double-entry accounting is the fundamental equation:
Assets = Liabilities + Equity
Every transaction maintains this balance. In Blnk’s context:
  • Assets: Customer balances, operational accounts
  • Liabilities: Money you owe (merchant settlements, withdrawals)
  • Equity: Platform revenue, fees collected

How Blnk implements double-entry

Blnk implements double-entry accounting at the transaction level. Every transaction in Blnk:
  1. Has a source (where money comes from) - this is a debit
  2. Has a destination (where money goes to) - this is a credit
  3. Records both sides separately in each balance
  4. Maintains the equation: total debits = total credits

Transaction structure

When you create a transaction:
{
  "source": "bal_alice_wallet",
  "destination": "bal_bob_wallet",
  "amount": 100,
  "precision": 100,
  "currency": "USD"
}
Blnk performs two operations:
  1. Debit the source: Add 10000 (in minor units) to bal_alice_wallet.debit_balance
  2. Credit the destination: Add 10000 to bal_bob_wallet.credit_balance

Balance calculation

Each balance in Blnk maintains:
  • credit_balance: Total amount credited (added) to the balance
  • debit_balance: Total amount debited (removed) from the balance
  • balance: The current balance (credit - debit)
current_balance = credit_balance - debit_balance

Understanding debits and credits

In traditional accounting, debits and credits have specific meanings depending on the account type. In Blnk’s simplified model:

Credits (money in)

A credit increases the balance. Credits represent:
  • Money deposited into an account
  • Payments received
  • Refunds received
  • Any incoming funds

Debits (money out)

A debit decreases the balance. Debits represent:
  • Money withdrawn from an account
  • Payments sent
  • Fees charged
  • Any outgoing funds
Blnk uses a simplified approach where credits increase balances and debits decrease them. This differs from traditional accounting where the meaning depends on account type (asset, liability, etc.). For fintech applications, this simplified model is more intuitive.

Examples

Example 1: Simple payment

Alice pays Bob $50.00:
curl -X POST http://localhost:5001/transactions \
  -H "Content-Type: application/json" \
  -d '{
    "source": "bal_alice",
    "destination": "bal_bob",
    "amount": 50,
    "precision": 100,
    "currency": "USD",
    "reference": "payment_alice_to_bob_001"
  }'
What happens: Alice’s balance (bal_alice):
  • debit_balance: +5000 (in minor units)
  • balance: decreases by 5000
  • Interpretation: Alice sent $50.00
Bob’s balance (bal_bob):
  • credit_balance: +5000
  • balance: increases by 5000
  • Interpretation: Bob received $50.00
The equation balances:
Debit (Alice -$50) = Credit (Bob +$50)

Example 2: Deposit from external source

Alice deposits $100 from her bank account:
curl -X POST http://localhost:5001/transactions \
  -H "Content-Type: application/json" \
  -d '{
    "source": "bal_external_bank",
    "destination": "bal_alice",
    "amount": 100,
    "precision": 100,
    "currency": "USD",
    "reference": "deposit_alice_001"
  }'
What happens: External bank balance (bal_external_bank):
  • debit_balance: +10000
  • Represents money leaving the external system
Alice’s balance (bal_alice):
  • credit_balance: +10000
  • balance: increases by 10000
  • Alice now has $100 more

Example 3: Payment with platform fee

Alice pays Bob $100, and the platform takes a 2% fee:
curl -X POST http://localhost:5001/transactions \
  -H "Content-Type: application/json" \
  -d '{
    "source": "bal_alice",
    "destinations": [
      {
        "identifier": "bal_bob",
        "distribution": "98%"
      },
      {
        "identifier": "bal_platform_fees",
        "distribution": "2%"
      }
    ],
    "amount": 100,
    "precision": 100,
    "currency": "USD",
    "reference": "payment_with_fee_001"
  }'
What happens: Alice’s balance (bal_alice):
  • debit_balance: +10000
  • balance: decreases by 10000 ($100)
Bob’s balance (bal_bob):
  • credit_balance: +9800
  • balance: increases by 9800 ($98)
Platform fee balance (bal_platform_fees):
  • credit_balance: +200
  • balance: increases by 200 ($2)
The equation still balances:
Debit (Alice -$100) = Credits (Bob +$98 + Platform +$2)

Example 4: Refund

Bob refunds Alice $50:
curl -X POST http://localhost:5001/transactions \
  -H "Content-Type: application/json" \
  -d '{
    "source": "bal_bob",
    "destination": "bal_alice",
    "amount": 50,
    "precision": 100,
    "currency": "USD",
    "reference": "refund_to_alice_001",
    "parent_transaction": "txn_original_payment"
  }'
What happens: Bob’s balance (bal_bob):
  • debit_balance: +5000
  • balance: decreases by 5000
Alice’s balance (bal_alice):
  • credit_balance: +5000
  • balance: increases by 5000
This creates a complete audit trail showing:
  1. Original payment from Alice to Bob
  2. Refund from Bob back to Alice

Verifying your ledger

With double-entry accounting, you can verify that your ledger is balanced at any time.

Sum of all balances

In a closed system (where money doesn’t enter or leave), the sum of all balances should equal zero:
Σ(all balances) = 0
This is because every debit has a matching credit.

Total debits = Total credits

Across all balances:
Σ(debit_balance) = Σ(credit_balance)
You can verify this by summing all debits and credits:
# Get all balances and sum the values
curl "http://localhost:5001/balances?limit=1000"
If you have external sources/destinations (bank accounts, payment providers), track them as special balances to maintain the equation.

Benefits of double-entry in Blnk

Error detection

If debits don’t equal credits, you know there’s an error. This makes debugging much easier.

Complete audit trail

Every transaction shows where money came from and where it went, making audits straightforward.

Balance integrity

Balances can’t be manipulated without leaving a trace. All changes are through transactions.

Financial reporting

Generate accurate reports showing total credits, debits, and current balances for any time period.

Best practices

Create balances for external systems (banks, payment providers) to keep your ledger balanced:
# Create a balance for your bank account
curl -X POST http://localhost:5001/balances \
  -d '{
    "ledger_id": "ldg_external",
    "currency": "USD",
    "meta_data": {"type": "bank_account"}
  }'
Now all deposits and withdrawals go through this balance, maintaining the equation.
Always update balances through transactions. Direct modifications break double-entry principles:Wrong:
{"balance": 10000}
Right:
{
  "source": "bal_external",
  "destination": "bal_user",
  "amount": 100
}
Separate different types of balances into different ledgers:
  • Customer wallets → Customer Ledger
  • Merchant accounts → Merchant Ledger
  • Platform revenue → Revenue Ledger
  • External accounts → External Ledger
This makes reporting and reconciliation easier.
Periodically verify that your ledger balances:
  1. Sum all debit_balance values
  2. Sum all credit_balance values
  3. Verify they’re equal
  4. Check external accounts match real-world balances
Use Blnk’s reconciliation features to automate this.
Use transaction metadata to understand money movement:
{
  "meta_data": {
    "category": "revenue",
    "subcategory": "platform_fee",
    "original_transaction": "txn_payment_123"
  }
}
This helps with financial reporting and tax compliance.

Common scenarios

Multi-currency transactions

When dealing with multiple currencies, each currency maintains its own double-entry balance:
# Alice sends USD to Bob's EUR account (with conversion)
# This requires two transactions:

# 1. Debit Alice's USD balance
curl -X POST http://localhost:5001/transactions \
  -d '{
    "source": "bal_alice_usd",
    "destination": "bal_platform_usd",
    "amount": 100,
    "precision": 100,
    "currency": "USD"
  }'

# 2. Credit Bob's EUR balance (at exchange rate)
curl -X POST http://localhost:5001/transactions \
  -d '{
    "source": "bal_platform_eur",
    "destination": "bal_bob_eur",
    "amount": 92,
    "precision": 100,
    "currency": "EUR"
  }'

Fee collection

Platform fees should be tracked as separate credit entries:
curl -X POST http://localhost:5001/transactions \
  -d '{
    "source": "bal_customer",
    "destinations": [
      {"identifier": "bal_merchant", "distribution": "97%"},
      {"identifier": "bal_platform_revenue", "distribution": "3%"}
    ],
    "amount": 1000,
    "precision": 100
  }'
The platform revenue balance accumulates all fees, making revenue reporting straightforward.

Next steps

Transactions

Learn more about creating and managing transactions

Balances

Understand balance structure and tracking

Reconciliation

Match your ledger with external records

Financial Reporting

Generate reports from your double-entry ledger

Build docs developers (and LLMs) love