Receivables
Customer credits
Specials, write-offs, and kept deposits, applied to the charges they cover.
Record a credit
Scope: invoices:write. A credit lowers what a customer owes without money changing hands. HelloLedger debits each line's account, credits A/R, and applies the credit to the invoices you list.
Move-in special · PUT
curl -X PUT "https://api.helloledger.ai/v1/companies/{company_id}/customer-credits/by-external-id/cr_2026_10_special_1001" \
-H "Authorization: Bearer $HL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_external_id": "stu_1001",
"date": "2026-10-01",
"reason": "concession",
"memo": "First month $100 off",
"lines": [
{
"account_id": "66f1a2b3c4d5e6f708091f60",
"description": "Move-in special",
"amount": "100.00"
}
],
"applications": [
{
"invoice_external_id": "chg_2026_10_rent_1001",
"amount": "100.00"
}
]
}'Response
{
"credit_id": "66f6…",
"external_id": "cr_2026_10_special_1001",
"customer_id": "66f2…",
"customer_external_id": "stu_1001",
"date": "2026-10-01",
"reason": "concession",
"credit_number": null,
"memo": "First month $100 off",
"total_amount": "100.00",
"amount_applied": "100.00",
"refunded_amount": "0.00",
"unapplied_amount": "0.00",
"status": "applied",
"lines": [
{ "account_id": "66f1a2b3c4d5e6f708091f60", "description": "Move-in special", "amount": "100.00" }
],
"applications": [
{ "invoice_id": "66f3…", "invoice_external_id": "chg_2026_10_rent_1001", "amount": "100.00" }
],
"result": "created"
}Which account to use
Lines can't point at bank, A/R, asset, or equity accounts. Ask the bookkeeper which accounts to use and keep their IDs in your app's settings.
| Situation | reason | Line account |
|---|---|---|
| Rent special, move-in discount, goodwill credit | concession | An income account such as Rent Concessions |
| Balance you won't collect | write_off | An expense account such as Bad Debt |
| Security deposit kept for damage or unpaid rent | deposit_applied | The deposit liability, such as Tenant Security Deposits (required) |
| Anything else | other | Any income, expense, or liability account |
Keeping a security deposit
Post the damage or unpaid rent as a normal charge, then apply the deposit to it with a deposit_applied credit. The deposit liability goes down and the charge is paid. Return whatever is left with a refund (source deposit).
PUT
curl -X PUT "https://api.helloledger.ai/v1/companies/{company_id}/customer-credits/by-external-id/cr_deposit_kept_1001" \
-H "Authorization: Bearer $HL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_external_id": "stu_1001",
"date": "2027-05-20",
"reason": "deposit_applied",
"memo": "Carpet cleaning kept from deposit",
"lines": [
{
"account_id": "66f1a2b3c4d5e6f708091d4e",
"description": "Deposit applied",
"amount": "150.00"
}
],
"applications": [
{
"invoice_external_id": "chg_2027_05_cleaning_1001",
"amount": "150.00"
}
]
}'Fields
| Field | Type | Notes |
|---|---|---|
| customer_external_id | string, required | Whose balance is credited. |
| date | YYYY-MM-DD, required | Posting date. |
| reason | concession | write_off | deposit_applied | other | Required. |
| lines | array, 1–50, required | account_id, description, amount. The credit total is the sum of the lines. |
| applications | array | Invoices the credit pays down. Can be empty; the amount stays unapplied on the customer's account. |
| credit_number, memo | string | Optional. |
Rules
- Applications must be the same customer's open invoices and can't exceed each invoice's balance or the credit total.
- Credits can't be edited. Void one and send the corrected credit under a new external ID.
- Voiding a credit reverses its ledger entry and reopens the invoices it paid. A credit with a refund can't be voided until the refund is voided.
- An invoice with a credit applied can't be changed (409 invoice_has_payments) until the credit is voided.
POST
curl -X POST "https://api.helloledger.ai/v1/companies/{company_id}/customer-credits/by-external-id/cr_2026_10_special_1001/void" \
-H "Authorization: Bearer $HL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Special entered twice"
}'GET
curl "https://api.helloledger.ai/v1/companies/{company_id}/customer-credits/by-external-id/cr_2026_10_special_1001" \
-H "Authorization: Bearer $HL_API_KEY"