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.

The reminder is the last step, after the status has been read. A paid invoice is never chased, and a draft is never sent by accident.

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

Example
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"
    }
  ]
}
What stays out of the follow-up list
RecordWhy 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

Example
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.

  1. Day 3 past due: a short factual reminder with the invoice number, the amount and the original due date.
  2. Day 10: repeat with the balance, and mention that the invoice link is still valid if the client needs the PDF again.
  3. Day 21: ask for a payment date, and offer the online payment link when the business has card payments switched on.
  4. 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

Example
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_invoice refuses 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_invoices with status: "unpaid" returns sent, viewed, partial and overdue invoices with an is_overdue flag on each row. Use status: "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_id and 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_status shows the amount paid, the balance and each recorded payment with its reference. Record the payment with record_payment when 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 routine

Every 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.