Work overdue invoices
Find invoices your clients haven't paid by their due date, build an aging view, send reminders, charge late fees, and close out invoices you won't collect.
An invoice is overdue when its due date passes and your client hasn't paid it. Wingspan marks the invoice for you. Following up, and deciding when to stop, is up to you.
How an invoice becomes overdue
Once you send an invoice, it's Opened. If it's still unpaid after its dueDate, Wingspan moves it to Overdue and sets events.overdueAt. You don't make a call for this. A draft (Created) invoice never goes overdue, because your client hasn't received it.
An invoice leaves Overdue when:
- Your client pays it, or you collect it. It moves to
PaymentInTransit, thenPaid. - You record a payment made outside Wingspan. See Partial and off-platform payments.
- You void it. It moves to
Cancelled.
If a payment on an overdue invoice fails, the invoice goes back to Overdue and your client can pay again.
Find overdue invoices
Search your invoice rows with Search invoice rows. Filter on the due date as well as the status, so your list includes an invoice whose due date passed today:
curl -s -g "https://api.wingspan.app/v3/search/invoice-rows?filter[status][anyOf][]=Opened&filter[status][anyOf][]=Overdue&filter[dueDate][lt]=2026-11-15&filter[metadata.invoiceType][ne]=approvedInvoicesPayment&sort[dueDate]=asc&page[size]=100" \
-H "Authorization: Bearer $WINGSPAN_TOKEN"// (trimmed)
{
"data": [
{
"id": "Iv7Hn2Qx5Rt8Kw3Lp6Zb9D",
"externalId": "INV-2026-0098",
"invoiceNumber": "NW-0098",
"status": "Overdue",
"amount": 1200.00,
"currency": "USD",
"dueDate": "2026-10-20",
"payerId": "Pq7Lm2Xv9RtK4sWb8NcY3d",
"profile": { "resolvedName": "Northwind Staffing" }
}
],
"summary": { "count": 14, "amountTotal": 18300.00 },
"pagination": { "nextPageToken": "eyJvIjoxMDB9" }
}sort[dueDate]=ascputs the oldest first.summarycovers every matching row, not only the rows in this response, so it's your total past due.- Add
filter[payerId][eq]=<payerId>for one client. It works whether or not the client has a Wingspan login. filter[metadata.invoiceType][ne]=approvedInvoicesPaymentleaves out the internal payment records that payroll creates.
Rows are a summary for lists and filters. To see payments, fees, and reminder history, read the invoice with GET /v3/payments/invoices/{invoiceId}. See Search for paging through large result sets.
Build an aging view
Group past-due invoices by how many days late they are. Run one search for each bucket with a dueDate range, and read summary.count and summary.amountTotal from each. For a report run on November 15, 2026:
| Bucket | Filters |
|---|---|
| Current | filter[status][eq]=Opened&filter[dueDate][gte]=2026-11-15 |
| 1 to 30 days | filter[dueDate][gte]=2026-10-16&filter[dueDate][lte]=2026-11-14 |
| 31 to 60 days | filter[dueDate][gte]=2026-09-16&filter[dueDate][lte]=2026-10-15 |
| 61 to 90 days | filter[dueDate][gte]=2026-08-17&filter[dueDate][lte]=2026-09-15 |
| Over 90 days | filter[dueDate][lte]=2026-08-16 |
For the past-due buckets, add filter[status][anyOf][]=Opened&filter[status][anyOf][]=Overdue and the same approvedInvoicesPayment filter.
summary totals don't split by currency. If you bill in more than one currency, page through the rows instead and add up amount by currency and bucket in your own code. Use page[mode]=materialized so rows don't shift while you read.
Send a reminder
Email your client a reminder with Send payment reminder for an invoice:
curl -X POST "https://api.wingspan.app/v3/payments/invoices/Iv7Hn2Qx5Rt8Kw3Lp6Zb9D/remind" \
-H "Authorization: Bearer $WINGSPAN_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"The call returns the invoice. Wingspan emails the invoice again with the PDF attached and a Pay now button. A client with no Wingspan login can pay from that button through a payment link. The email also goes to the addresses in the Payer's notificationCcEmails, so add your client's AP inbox there with Update a payer. It holds up to 10 addresses.
- You can remind on an
OpenedorOverdueinvoice. Any other status returns409. - If the client's engagement still has payment requirements to complete, you get
409 EligibilityBlockedwithdetailCode: payments.EngagementNotPaymentsEligible. - Every call sends an email, so space your reminders out, for example once a week per invoice.
Automatic reminders
Set notificationPreferences.shouldSendReminders to true when you create the invoice, or on the invoiceTemplate of a recurring invoice. It's off by default. With it on, Wingspan emails your client before the due date, on the due date, and after it, and records each email on the invoice in events.sentDueIn3DaysAt, events.sentDueTodayAt, and events.sentDue3DaysAgoAt.
You can change notificationPreferences with Update an invoice while the invoice is Created or Opened.
Charge late fees
Add lateFeeHandling to the invoice when you create it, or while it's Created or Opened. Use a percentage or a flat amount, not both, and a frequency:
{
"lateFeeHandling": {
"lateFeePercentage": 1.5,
"frequency": { "interval": "LateFeeIntervalMonthly", "every": 1 }
}
}| Field | Notes |
|---|---|
lateFeePercentage | A percentage, such as 1.5 for 1.5% |
lateFeeAmount | A flat amount, such as 25.00 |
frequency.interval | LateFeeIntervalWeekly or LateFeeIntervalMonthly |
frequency.every | How many intervals between fees. 2 with LateFeeIntervalWeekly charges every two weeks. |
Sending both lateFeePercentage and lateFeeAmount returns 422 ConflictingFields. Wingspan charges the first fee once the due date passes, then again each period while the invoice stays unpaid. There's no grace period or cap, so pick a rate and frequency your contract allows.
A late fee doesn't add a line item. It shows in the invoice's fees.items[] with type: Late and chargedTo: Payer, and fees.chargedToPayer includes it. amount stays the amount you billed. The invoice PDF and reminder emails show the late fee. For a recurring invoice, set lateFeeHandling on the template, and each invoice's fees count from its own due date.
Once a fee is charged, you can't remove it from the invoice. To drop it, void the invoice and send a corrected one.
Collect automatically
If your client has a saved payment method and automatic collection is on, Wingspan collects each open or overdue invoice on its due date, so it never needs a reminder. See Save a client's card and turn on autopay and Authorize ACH debits online and collect an invoice.
Close an invoice you won't collect
| Situation | What to do |
|---|---|
| The invoice has the wrong amount or client, or it's a duplicate | Void it, then create a corrected invoice with a new externalId. A voided invoice keeps its externalId. |
| It's still a draft | Delete it. Delete works only on Created invoices. |
| Your client paid you outside Wingspan | Record an off-platform payment. |
| You'll accept less than the full amount | Give your client a credit for the difference. |
| You're writing it off | Void it, and record the write-off amount and reason in your own ledger. |
Only record an off-platform payment when money arrived. Using it to close an invoice you're writing off puts a payment on your books that never happened.
Voiding gives back any credit that applied to the invoice, so your client can use it on another invoice. Void doesn't take a reason, so keep yours in your own system.
What your client sees
When your client signs in to pay you, Wingspan lists their unpaid invoices past the due date under Overdue and the rest under Open. See Client payment experience.
Related pages
Updated 13 days ago