Receivables
Customer payments
Record each payment on its own and apply it to the invoices it paid. No lumped deposits.
Record a payment
Scope: payments:write. HelloLedger debits the deposit account, credits A/R, and applies the payment to the invoices you list. Each invoice's balance and status (partial or paid) update immediately.
PUT
curl -X PUT "https://api.helloledger.ai/v1/companies/{company_id}/customer-payments/by-external-id/pay_pi_3Q8x" \
-H "Authorization: Bearer $HL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_external_id": "stu_1001",
"date": "2026-10-03",
"amount": "875.00",
"deposit_account_id": "66f1a2b3c4d5e6f708091c3d",
"method": "card",
"reference": "pi_3Q8x",
"memo": "Stripe payment",
"applications": [
{
"invoice_external_id": "chg_2026_10_rent_1001",
"amount": "850.00"
},
{
"invoice_external_id": "chg_2026_10_late_1001",
"amount": "25.00"
}
]
}'Response
{
"payment_id": "66f4…",
"external_id": "pay_pi_3Q8x",
"customer_id": "66f2…",
"customer_external_id": "stu_1001",
"date": "2026-10-03",
"amount": "875.00",
"amount_applied": "875.00",
"unapplied_amount": "0.00",
"refunded_amount": "0.00",
"deposit_account_id": "66f1a2b3c4d5e6f708091c3d",
"method": "card",
"reference": "pi_3Q8x",
"status": "applied",
"applications": [
{ "invoice_id": "66f3…", "invoice_external_id": "chg_2026_10_rent_1001", "amount": "850.00" },
{ "invoice_id": "66f5…", "invoice_external_id": "chg_2026_10_late_1001", "amount": "25.00" }
],
"result": "created"
}Fields
| Field | Type | Notes |
|---|---|---|
| customer_external_id | string, required | Who paid. |
| date | YYYY-MM-DD, required | Payment date. |
| amount | decimal string, required | Total received. |
| deposit_account_id | string, required | Bank account, or a clearing account (e.g. Undeposited Funds) when a processor pays out in batches. |
| method | ach | card | check | cash | bank | other | Defaults to bank. |
| reference | string | Processor or check reference. |
| memo | string | Optional. |
| applications | array | Invoices this payment paid. Can be empty for a prepayment; the amount stays unapplied. |
Rules
- Applications must belong to the same customer, can't exceed each invoice's open balance, and can't add up to more than amount.
- Payments can't be edited. To correct one, void it and send the corrected payment under a new external ID.
- Voiding a payment (for example, an ACH return) reverses its ledger entry and reopens the invoices it paid.
- An overpayment stays on the payment as unapplied_amount. The bookkeeper can apply it to a later charge in HelloLedger, or you can send it back with a refund (source payment). A payment with a refund can't be voided until the refund is voided.
POST
curl -X POST "https://api.helloledger.ai/v1/companies/{company_id}/customer-payments/by-external-id/pay_pi_3Q8x/void" \
-H "Authorization: Bearer $HL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "ACH return R01"
}'Read a payment
GET
curl "https://api.helloledger.ai/v1/companies/{company_id}/customer-payments/by-external-id/pay_pi_3Q8x" \
-H "Authorization: Bearer $HL_API_KEY"