Getting paid
How to follow up on overdue freelance invoices without sending duplicate reminders
Start with list_invoices filtered to unpaid, which returns sent, viewed, partial and overdue invoices with an is_overdue flag. Check the payment history for anything you are about to chase, then send one reminder per invoice with send_invoice and a delivery request id. A draft is not a receivable and a paid invoice needs nothing, so both drop out of the follow-up list.
Written and reviewed by the Billr team. Published , last reviewed .
The short version
A list of invoices that are genuinely owed, a recorded status for each one, and one reminder per invoice at each step of your follow-up cadence.
What you need first
- Invoices already sent, with due dates that reflect your actual terms.
- A key or a person with the sending permission, because a reminder is an email to a client.
- A written cadence, for example a nudge three days after the due date, a second at ten days, and a call at three weeks.
Cautions
- Draft invoices are excluded from any chase. Sending a reminder about something the client never received is the fastest way to lose the thread.
- Read the payment history before you send. A payment recorded today should cancel the reminder rather than arrive alongside it.
- A reminder is a delivery, and deliveries carry their own request id so a retry does not produce a second email.
Who this is for: Freelancers and studio owners who would rather run a short, factual follow-up routine than write increasingly awkward emails from memory.
list_invoicesget_payment_statussend_invoicerecord_paymentrevenue_summary
Read the state before the email exists
Chasing an invoice is a small decision repeated at intervals: is this still owed, and has anything changed since last time? Most awkward follow-ups come from skipping that check. A client who paid on Friday gets a reminder on Monday, or a reminder goes out on a draft nobody has seen.
The routine below keeps the reading first and the writing last. Everything it needs is already in the record: status, due date, balance, and the payment history that explains the balance.
The state you check before every reminder
Due date passes
Status and date decide, not memory
Sent, viewed, partial and overdue invoices past their due date read as overdue.
Read the list
Unpaid invoices, each with its balance
Drafts and paid invoices are not in this list at all.
Read the history
Payments already recorded
A partial payment changes the amount you ask for.
One deliberate send
A reminder with its own delivery id
Retrying the same id does not send a second email.
Close the loop
A recorded payment clears the balance
The invoice leaves the follow-up list on the next read.
Pull one list of what is actually owed
list_invoices with the synthetic status unpaid matches invoices that are sent, viewed, partial or overdue. Each row carries is_overdue, computed from the status and the due date, so you do not have to work out which late invoices are real and which are simply unpaid and not yet due.
The summary line gives you the outstanding total for the page, or a per-currency breakdown when the page mixes currencies. Collect the invoice ids you intend to chase from invoices[].id, and page with next_offset if the list is long.
list_invoices, unpaid only
list_invoices { "status": "unpaid", "limit": 50 }Use client_id to narrow it to one client, or status: "overdue" when you only want invoices already past their due date.
Fictional account, field names as returned by the server
You say
Which invoices are past due, and what is still owed on them?
Your agent calls
list_invoices{ "status": "unpaid", "limit": 50 }
Arithmetic you can check
- $1,450.00 + $890.00 + $320.00$2,660.00 across 3 invoices
What came back
Abridged response from list_invoices. The three fictional invoices are all overdue, which is why the follow-up routine has work to do.
- offset
- 0
- next_offset
- none
- summary
- 3 invoices, $2,660.00 outstanding
- invoices
- 3 entries
Show the raw response
{
"offset": 0,
"next_offset": null,
"summary": "3 invoices, $2,660.00 outstanding",
"invoices": [
{
"id": "2a6f3c81-9d24-4b70-8e15-3c7a1f5d9b62",
"invoice_number": "INV-1141",
"client_name": "Harbor & Lane",
"status": "sent",
"is_overdue": true,
"issue_date": "2026-09-01",
"due_date": "2026-09-15",
"currency": "USD",
"total": 1450,
"balance_due": 1450,
"app_url": "/invoices/2a6f3c81-9d24-4b70-8e15-3c7a1f5d9b62"
},
{
"id": "b8e1d4a7-35c9-4f26-9a03-7d2b6e8c1f54",
"invoice_number": "INV-1136",
"client_name": "Larkspur Audio",
"status": "viewed",
"is_overdue": true,
"issue_date": "2026-08-21",
"due_date": "2026-09-04",
"currency": "USD",
"total": 890,
"balance_due": 890,
"app_url": "/invoices/b8e1d4a7-35c9-4f26-9a03-7d2b6e8c1f54"
},
{
"id": "5d9c2e63-1a78-4b04-8f92-6e3a7c5b1d29",
"invoice_number": "INV-1129",
"client_name": "Harbor & Lane",
"status": "partial",
"is_overdue": true,
"issue_date": "2026-07-30",
"due_date": "2026-08-29",
"currency": "USD",
"total": 500,
"balance_due": 320,
"app_url": "/invoices/5d9c2e63-1a78-4b04-8f92-6e3a7c5b1d29"
}
]
}| Record | Why it is not chased |
|---|---|
| INV-1153 (Larkspur Audio, draft) | Never sent, so it is not a receivable and does not belong in a reminder. |
| INV-1148 (Harbor & Lane, paid) | Already paid in full; record_payment closed the balance. |
Check the payment history on anything with a partial balance
For a partial payment the balance is the part that matters, and the history is the explanation. get_payment_status reports the amount paid, the amount still due, each recorded payment with its date and reference, and whether online card payment is switched on for that client.
This is also where a follow-up becomes easy to word. If a partial payment arrived with reference SEPA-4471, the reminder can thank the client for it by reference and ask only for the remainder, which is a shorter and more agreeable email than a generic chase.
A partial payment does not take the invoice out of the list. Status partial still counts as unpaid, so the row stays until the balance reaches zero and the status becomes paid. What changes is the amount you ask for.
Fictional account, field names as returned by the server
You say
Has INV-1129 been paid, and what is left?
Your agent calls
get_payment_status{ "invoice_id": "5d9c2e63-1a78-4b04-8f92-6e3a7c5b1d29" }
What came back
Abridged response from get_payment_status for the same INV-1129 fixture the list came from. online_payments_enabled is false here, so pay_url is null and the client pays by transfer.
- summary
- INV-1129 is partial and overdue: $180.00 paid, $320.00 still due.
- invoice
- 9 fields
- payments
- 1 entry
- payments_count
- 1
- online_payments_enabled
- no
- pay_url
- none
Show the raw response
{
"summary": "INV-1129 is partial and overdue: $180.00 paid, $320.00 still due.",
"invoice": {
"id": "5d9c2e63-1a78-4b04-8f92-6e3a7c5b1d29",
"invoice_number": "INV-1129",
"status": "partial",
"is_overdue": true,
"currency": "USD",
"total": 500,
"amount_paid": 180,
"balance_due": 320,
"due_date": "2026-08-29"
},
"payments": [
{
"amount": 180,
"payment_date": "2026-09-02",
"payment_method": "bank_transfer",
"reference_number": "SEPA-4471"
}
],
"payments_count": 1,
"online_payments_enabled": false,
"pay_url": null
}Record payments when they land
Outstanding totals come from recorded payments. If money arrived and nobody logged it, the invoice still reads unpaid and your follow-up will be wrong. record_payment is a write: it adds a ledger row and moves the invoice to partial or paid, which is why the reconcile step is worth doing before the next reminder.
Recording that transfer is a one-call job, and the reference you store is what lets the next review match the ledger to a bank statement. The reconcile what has actually been paid guide covers partial payments in more detail.
Send one reminder per step, with a delivery id
send_invoice emails the invoice with its PDF attached and defaults the recipient to the client address on file. It refuses invoices that are already paid or cancelled, which is the guard that stops an over-enthusiastic cadence from chasing money that has arrived.
Give every reminder its own request_id. A retry with the same id and the same recipients and content returns the delivery already recorded, which is what makes a timeout safe to retry. Reusing an id with different content is refused rather than sent.
That idempotency is retry safety, not duplicate prevention in general. Two different request ids send two emails, and so does any other person or key that sends the same invoice. Before each new step, check the invoice in the app: the detail page shows when it was last sent and changes the action to Resend, and the Agents audit panel lists the tool calls that were made.
send_invoice, reminder with context
send_invoice {
"request_id": "e8c2b5a1-4d76-4f39-8a02-1b9e6c3d7f25",
"invoice_id": "2a6f3c81-9d24-4b70-8e15-3c7a1f5d9b62",
"subject": "Invoice INV-1141 from Fieldnote Software, past due",
"message": "Hello. INV-1141 was due on 2026-09-15 and $1,450.00 is still outstanding. If it has already been paid, thank you, and let me know so I can mark it. Otherwise I would appreciate payment this week."
}The id, the number and the balance all come from the same INV-1141 row the list returned. The subject names the invoice and that it is past due; the body states the amount rather than describing the mood.
- Day 3 past due: a short factual reminder with the invoice number, the amount and the original due date.
- Day 10: repeat with the balance, and mention that the invoice link is still valid if the client needs the PDF again.
- Day 21: ask for a payment date, and offer the online payment link when the business has card payments switched on.
- Before each step: re-read the list and the delivery history. If the invoice was paid or already reminded, the step disappears and nothing is sent.
Close the loop when money arrives
A follow-up routine is only as good as the way it ends. When a payment lands outside the card flow, record it with record_payment: the balance drops, the status becomes partial or paid, and the invoice leaves the unpaid list on the next read.
That single step is what keeps the cadence from becoming an embarrassment. It is also how revenue_summary stays useful: invoiced, paid, outstanding and overdue totals all come from invoices and recorded payments, not from anyone remembering what happened. Record a partial payment covers the case where only part of the balance arrives.
record_payment, bank transfer received
record_payment {
"request_id": "8b4d1f6a-2c05-4e97-9a31-5f7c2d8b4e16",
"invoice_id": "5d9c2e63-1a78-4b04-8f92-6e3a7c5b1d29",
"amount": 320,
"payment_date": "2026-09-19",
"method": "bank_transfer",
"reference_number": "SEPA-4471"
}The $320.00 clears what is left of INV-1129, and the reference number is what lets the next review match the ledger row to a bank statement.
Limits and honest expectations
- Billr does not send scheduled reminders on its own. The cadence is yours; the tools make each step safe and recorded.
send_invoicerefuses paid and cancelled invoices. If a reminder is refused as paid, your ledger was right and your reminder list was stale.- Stripe card payments and manual payments are separate paths. Only recorded payments change the balance, so a card payment and a transfer both end up in the same ledger when they are recorded.
- Overdue is derived from the due date and status at read time. Only a draft invoice can be edited, so set the due date correctly before you send; after that the date is part of the record the client received.
Reminders go to a real client
Sending is the step with an external effect, and recording a payment writes to the ledger. The reading steps exist so those two writes are deliberate.
Frequently asked questions
- How do I find which invoices are overdue?
list_invoiceswithstatus: "unpaid"returns sent, viewed, partial and overdue invoices with anis_overdueflag on each row. Usestatus: "overdue"when you only want the ones already past due.- How do I stop the same reminder being sent twice?
- Give each reminder its own
request_idand reuse that id only when retrying the identical message: the retry returns the delivery already recorded, while a new id sends a new email. That guards retries, not duplicate sends in general, so check the invoice delivery history in the app before the next step. - Should I chase a draft invoice that is past its date?
- No. A draft has not been delivered to the client, so it is not a receivable. Only sent, viewed, partial and overdue invoices belong in a follow-up list.
- What if the client made a partial payment?
get_payment_statusshows the amount paid, the balance and each recorded payment with its reference. Record the payment withrecord_paymentwhen it lands, and the status becomes partial until the balance reaches zero.- Can Billr send reminders automatically on a schedule?
- Scheduled automatic reminders are not implemented. The tools let an agent or a person run the routine safely, with each send carrying its own delivery id.
Guides and docs for the individual steps
Each article covers a whole job. These are the narrower references behind it.
Sources
Reviewed 2026-09-20 against Billr's own tool implementations and the pages linked here.
Late invoices are easier to face when the list is short and the balances are current. The month-end routine keeps it that way.
Read the month-end routineEvery example on this page uses a fictional account. Field names come from Billr's own tool implementations, and the arithmetic is recomputed by the same helpers the server uses. All articles.