Bookkeeping
Bills
Bills from vendors. Posting puts the expense on the books and the amount owed in Accounts Payable.
Create a bill
Scope: bills:write. Each line names an expense (or asset) account from GET /coa and an amount. The vendor is matched by name or created, so you can send bills before setting up vendors.
With "post": true the bill is posted right away (status entered): each line's account is debited and Accounts Payable is credited. Without it the bill is saved as a draft.
curl -X POST "https://api.helloledger.ai/v1/companies/{company_id}/bills" \
-H "Authorization: Bearer $HL_API_KEY" \
-H "Idempotency-Key: bill_5531" \
-H "Content-Type: application/json" \
-d '{
"vendor": {
"name": "Staples"
},
"bill_number": "INV-77",
"date": "2026-10-01",
"due_date": "2026-10-31",
"memo": "October office supplies",
"external_id": "bill_5531",
"post": true,
"lines": [
{
"account_id": "66f1a2b3c4d5e6f708091d01",
"description": "Paper and toner",
"amount": "120.00"
},
{
"account_id": "66f1a2b3c4d5e6f708091d02",
"description": "Storage unit",
"amount": "80.00"
}
]
}'{
"bill_id": "66f1a2b3c4d5e6f708093b01",
"external_id": "bill_5531",
"vendor_id": "66f1a2b3c4d5e6f708092a01",
"vendor_name": "Staples",
"vendor_created": false,
"bill_number": "INV-77",
"date": "2026-10-01",
"due_date": "2026-10-31",
"status": "entered",
"posted": true,
"total_amount": "200.00",
"amount_paid": "0.00",
"amount_credited": "0.00",
"balance_due": "200.00",
"currency": "USD",
"ap_account_id": "66f1a2b3c4d5e6f708091d09",
"lines": [
{ "account_id": "66f1a2b3c4d5e6f708091d01", "account_name": "Office Supplies", "description": "Paper and toner", "amount": "120.00" },
{ "account_id": "66f1a2b3c4d5e6f708091d02", "account_name": "Rent Expense", "description": "Storage unit", "amount": "80.00" }
],
"posted_at": "2026-10-01T15:04:05Z",
"result": "posted"
}Fields
| Field | Notes |
|---|---|
| vendor_id or vendor | Required on create, one or the other. vendor takes the same fields as POST /vendors. |
| date | Date the bill was received (YYYY-MM-DD). Required on create. |
| lines | 1–100 lines of account_id and amount, with optional description, quantity, and unit_price. |
| due_date, bill_number, memo | Optional. |
| ap_account_id | Accounts Payable account. Defaults to the company's A/P account. |
| external_id | Your ID for the bill, stored for reference. |
| post | true posts now. Default false saves a draft. |
List and read bills
Scope: bills:read or bills:write. Filter by status (draft, entered, partial, paid, overdue, voided), vendor_id, external_id, and a from/to date range. Unpaid bills past their due date show as overdue.
curl "https://api.helloledger.ai/v1/companies/{company_id}/bills?status=overdue&limit=50" \
-H "Authorization: Bearer $HL_API_KEY"curl "https://api.helloledger.ai/v1/companies/{company_id}/bills/66f1a2b3c4d5e6f708093b01" \
-H "Authorization: Bearer $HL_API_KEY"Edit, post, or delete
PATCH changes a draft or an unpaid posted bill. Sending lines replaces all lines. A posted bill is re-posted with the new amounts. Bills with payments or vendor credits return 409 bill_has_payments.
curl -X PATCH "https://api.helloledger.ai/v1/companies/{company_id}/bills/66f1a2b3c4d5e6f708093b01" \
-H "Authorization: Bearer $HL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"due_date": "2026-11-15",
"lines": [
{
"account_id": "66f1a2b3c4d5e6f708091d01",
"amount": "135.00"
}
]
}'curl -X POST "https://api.helloledger.ai/v1/companies/{company_id}/bills/66f1a2b3c4d5e6f708093b01/post" \
-H "Authorization: Bearer $HL_API_KEY"curl -X DELETE "https://api.helloledger.ai/v1/companies/{company_id}/bills/66f1a2b3c4d5e6f708093b01" \
-H "Authorization: Bearer $HL_API_KEY"Void a bill
Voiding reverses the bill's ledger entries and sets status voided. Bills with payments or credits can't be voided until those are removed in HelloLedger.
curl -X POST "https://api.helloledger.ai/v1/companies/{company_id}/bills/66f1a2b3c4d5e6f708093b01/void" \
-H "Authorization: Bearer $HL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Duplicate of INV-76"
}'