Skip to content
Ledgerline Help

Transactions and entries

Updated 10 September 20263 min read

On this page

A transaction changes balances. It is a set of entries, each a debit or a credit against one account, and the set has to balance. This is the rule that keeps a ledger trustworthy: money is never created or lost, only moved.

The balancing rule

Within a transaction, the sum of debit amounts must equal the sum of credit amounts in each currency. If it does not, the request fails with HTTP 422 and the code entries_unbalanced.

A transaction must contain at least 2 entries and at most 100.

{
  "ledger_id": "led_01J9QK3ZV8",
  "description": "Invoice INV-2041 settled",
  "status": "posted",
  "effective_at": "2026-09-10T00:00:00Z",
  "entries": [
    { "account_id": "acc_01J9QK5M2A", "direction": "debit", "amount": 480000, "currency": "USD" },
    { "account_id": "acc_01J9QK5N7C", "direction": "credit", "amount": 450000, "currency": "USD" },
    { "account_id": "acc_01J9QK5P1D", "direction": "credit", "amount": 30000, "currency": "USD" }
  ]
}

Amounts are positive integers in minor units. The direction says which way the entry goes.

Pending and posted

Status Meaning
pending The entries are recorded and reserve funds, but are not final.
posted The entries are final and permanent.
archived A pending transaction that was voided. It never affected posted balances.

Create a transaction as pending when you need to hold funds before you know the outcome, for example while a payout is being reviewed. Then:

  • POST /v1/transactions/{id}/post makes it final.
  • POST /v1/transactions/{id}/void releases the hold and archives it.

A pending transaction affects the pending and available balances immediately, but not the posted balance. See Account balances.

Posted entries are immutable

Once a transaction is posted, nothing about it can change, not the amounts, the accounts or the description. There is no update and no delete. This is deliberate: an auditor can trust that history was not rewritten.

To fix a mistake, reverse the transaction:

curl -X POST https://api.ledgerline.dev/v1/transactions/txn_01JA5C9T/reverse \
  -H "Authorization: Bearer $LEDGERLINE_API_KEY" \
  -H "Idempotency-Key: 2c8e6d1a-8f40-47a4-9d6e-0d5f3a1b7c92" \
  -d description="Reversal: duplicate invoice"

A reversal creates a new posted transaction with the opposite entries and links it to the original through reverses. The original keeps its place in history and gains reversed_by. Reversing emits a transaction.reversed event. A transaction can be reversed once.

Effective date and backdating

Each transaction has an effective_at timestamp, which is when the movement counts for reporting. It defaults to now. You may set it up to 90 days in the past. Anything older fails with period_closed, because statements for that period have already been issued. Future dates are allowed for pending transactions only.

Balance protection

Posting is checked against each account's available balance. If a credit-normal account has allow_overdraft set to false, which is the default, and an entry would push its available balance below zero, the whole transaction is rejected with insufficient_funds. No partial transaction is ever written.

Metadata and references

Attach up to 50 key-value pairs of metadata to a transaction, with keys up to 40 characters and values up to 500. Use external_id to store your own identifier. It must be unique per ledger, which gives you a natural idempotency check on top of the Idempotency-Key header described in Idempotency.

Batches

When you import many transactions at once, use POST /v1/transactions/batch. It accepts up to 500 transactions per request and processes them asynchronously. The response is HTTP 202 with a batch id, and each transaction succeeds or fails independently. The endpoint allows 30 requests per minute per key. See Rate limits.

Events

Event Fired when
transaction.posted A transaction becomes posted, including directly at creation.
transaction.reversed A reversal transaction is posted.

Subscribe through webhook endpoints.