Skip to content
Ledgerline Help

Quickstart: record your first transaction

Updated 14 September 20262 min read

On this page

This guide takes you from a new sandbox organization to a posted, balanced transaction in about ten minutes. You will create a ledger, open two accounts, move funds between them and read the balances back. Everything here runs against the sandbox, so no real money moves.

Before you start

You need a Ledgerline organization and a sandbox secret key. Sign in to the dashboard at https://dashboard.ledgerline.dev, open Developers, choose API keys and create a key in the Test tab. Test secret keys start with ll_test_sk_. The key is shown once, so copy it into your secrets manager straight away.

export LEDGERLINE_API_KEY="ll_test_sk_replace_me"

Every request goes to the sandbox base URL and carries the key as a bearer token:

https://sandbox.api.ledgerline.dev/v1
Authorization: Bearer $LEDGERLINE_API_KEY

Note

Live traffic uses https://api.ledgerline.dev/v1 and ll_live_ keys. Sandbox and live share no data. See Going live before you switch.

1. Create a ledger

A ledger is the container for a set of accounts that belong together, such as "Customer funds" for one product line.

curl https://sandbox.api.ledgerline.dev/v1/ledgers \
  -H "Authorization: Bearer $LEDGERLINE_API_KEY" \
  -H "Idempotency-Key: 6f1c0b52-6f0d-4c7e-9a52-1d2f6f1d5c01" \
  -d name="Customer funds" \
  -d description="Funds held on behalf of customers"

The response contains the ledger id, which starts with led_. Keep it for the next step.

2. Open two accounts

Create a customer wallet and an operating account. The wallet is credit-normal because the balance is money you owe the customer. The operating account is debit-normal because it is an asset you hold.

curl https://sandbox.api.ledgerline.dev/v1/accounts \
  -H "Authorization: Bearer $LEDGERLINE_API_KEY" \
  -H "Idempotency-Key: 0d4a7a3c-97d9-4a8d-8f7b-0c14a2a6a102" \
  -d ledger_id=led_01J9QK3ZV8 \
  -d name="Customer wallet" \
  -d currency=USD \
  -d normal_balance=credit

Repeat the call with name="Operating cash" and normal_balance=debit. Each response returns an account id that starts with acc_.

3. Post a transaction

A transaction is a set of entries that must balance. Debits and credits have to add up to the same amount in each currency, otherwise the request fails with entries_unbalanced.

Amounts are integers in minor units, so 250000 means $2,500.00.

{
  "ledger_id": "led_01J9QK3ZV8",
  "description": "Customer deposit",
  "status": "posted",
  "entries": [
    { "account_id": "acc_01J9QK5M2A", "direction": "debit", "amount": 250000, "currency": "USD" },
    { "account_id": "acc_01J9QK5N7C", "direction": "credit", "amount": 250000, "currency": "USD" }
  ]
}

Send it with POST /v1/transactions. Setting status to posted makes the entries final immediately. If you send pending instead, the entries are held until you call POST /v1/transactions/{id}/post, or release them with POST /v1/transactions/{id}/void.

4. Read the balances

curl https://sandbox.api.ledgerline.dev/v1/accounts/acc_01J9QK5N7C/balances \
  -H "Authorization: Bearer $LEDGERLINE_API_KEY"
{
  "account_id": "acc_01J9QK5N7C",
  "currency": "USD",
  "posted": 250000,
  "pending": 0,
  "available": 250000
}

The three balance types are explained in Account balances.

Use an SDK instead

The same flow in Node, using the official client:

import Ledgerline from "@ledgerline/node";

const ll = new Ledgerline(process.env.LEDGERLINE_API_KEY!);

const ledger = await ll.ledgers.create({ name: "Customer funds" });
const wallet = await ll.accounts.create({
  ledgerId: ledger.id,
  name: "Customer wallet",
  currency: "USD",
  normalBalance: "credit",
});

See Node SDK and Python SDK for installation and configuration.

Next steps