Bookkeeping

    Journal entries

    Balanced debits and credits for adjustments, accruals, transfers, and anything without its own form.

    Create a journal entry

    Scope: journals:write. Send 2–200 lines. Each line has an account_id and exactly one of debit or credit above zero, and total debits must equal total credits.

    With "post": true the entry goes to the ledger right away. Without it the entry is saved as a draft.

    POST
    curl -X POST "https://api.helloledger.ai/v1/companies/{company_id}/journal-entries" \
      -H "Authorization: Bearer $HL_API_KEY" \
      -H "Idempotency-Key: je_2026_10_owner" \
      -H "Content-Type: application/json" \
      -d '{
      "date": "2026-10-31",
      "memo": "Owner contribution",
      "external_id": "je_2026_10_owner",
      "post": true,
      "lines": [
        {
          "account_id": "66f1a2b3c4d5e6f708091d03",
          "debit": "5000.00",
          "description": "Deposit"
        },
        {
          "account_id": "66f1a2b3c4d5e6f708091d05",
          "credit": "5000.00"
        }
      ]
    }'
    Response (201)
    {
      "journal_id": "48213",
      "external_id": "je_2026_10_owner",
      "date": "2026-10-31",
      "memo": "Owner contribution",
      "status": "posted",
      "posted": true,
      "total": "5000.00",
      "lines": [
        { "account_id": "66f1a2b3c4d5e6f708091d03", "account_name": "Operating Checking", "debit": "5000.00", "credit": "0.00", "description": "Deposit" },
        { "account_id": "66f1a2b3c4d5e6f708091d05", "account_name": "Owner Equity", "debit": "0.00", "credit": "5000.00" }
      ],
      "result": "posted"
    }

    List and read journal entries

    Scope: journals:read. The list pages with next_cursor; pass it back as cursor. Filter by date with from and to (both required together). Voided entries are listed with status voided.

    GET
    curl "https://api.helloledger.ai/v1/companies/{company_id}/journal-entries?from=2026-10-01&to=2026-10-31" \
      -H "Authorization: Bearer $HL_API_KEY"
    One entry · GET
    curl "https://api.helloledger.ai/v1/companies/{company_id}/journal-entries/48213" \
      -H "Authorization: Bearer $HL_API_KEY"

    Edit, post, or delete

    PATCH changes a draft or a posted entry. Sending lines replaces all lines, and they must balance. A posted entry is re-posted with the new lines. DELETE removes drafts only.

    PATCH
    curl -X PATCH "https://api.helloledger.ai/v1/companies/{company_id}/journal-entries/48213" \
      -H "Authorization: Bearer $HL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "memo": "Owner contribution (corrected)",
      "lines": [
        {
          "account_id": "66f1a2b3c4d5e6f708091d03",
          "debit": "5500.00"
        },
        {
          "account_id": "66f1a2b3c4d5e6f708091d05",
          "credit": "5500.00"
        }
      ]
    }'
    Post a draft · POST
    curl -X POST "https://api.helloledger.ai/v1/companies/{company_id}/journal-entries/48213/post" \
      -H "Authorization: Bearer $HL_API_KEY"
    Delete a draft · DELETE
    curl -X DELETE "https://api.helloledger.ai/v1/companies/{company_id}/journal-entries/48213" \
      -H "Authorization: Bearer $HL_API_KEY"

    Void a journal entry

    Voiding removes the entry from the ledger and keeps it with status voided, so the history stays visible. A voided entry can't be edited or posted again.

    POST
    curl -X POST "https://api.helloledger.ai/v1/companies/{company_id}/journal-entries/48213/void" \
      -H "Authorization: Bearer $HL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "reason": "Booked in the wrong month"
    }'

    What you can't change

    • Entries on a date an account has been reconciled through return 409 period_reconciled.
    • Entries created by other integrations, including daily revenue journals, return 409 managed_by_integration. Daily revenue has its own endpoint.
    • Every account must belong to the company and be open on the entry's date.