How Bulk "Mark as Paid" Actually Works
In this article
Selecting a batch of invoices and clicking "mark as paid" feels like it should be a simple status flip applied to every selected row. Under the hood it's doing something more deliberate — and more correct — for a reason that becomes obvious once you know how invoice status actually gets calculated elsewhere in the product.
The Status Field Is Derived, Not Authoritative
An invoice's paid amount and status aren't values you can durably set by editing them directly, because they get recalculated from scratch every time any payment event touches that invoice — a new payment recorded, one deleted, one reconciled. That recalculation always wins: it sums every currently-matched payment against the invoice and derives the status from that sum, overwriting whatever was there before. If bulk "mark as paid" simply wrote status: "paid" onto each selected invoice's data, that edit would hold only until the next payment event of any kind touched the invoice — at which point the recalculation would run, find no payment records backing up the "paid" status, and silently flip it back to unpaid or overdue. The comment in the code that implements this is explicit about the reasoning: hand-setting the field would be "silently reverted... the next time a payment is added, deleted, or reconciled."
What It Actually Does Instead
For each selected invoice, the bulk action calculates the invoice's total, sums whatever matched payments already exist against it, and inserts a new payment record for exactly the difference — the amount still outstanding — tagged with a method of "Bulk mark as paid" and a source of "manual," dated to the invoice's payment date if one's set, or today's date otherwise. That new payment is what actually gets the invoice to a paid status, because the same recalculation logic that could have silently undone a direct status edit now runs in the payment's favor: it sums the payments, finds they now cover the full total, and derives "paid" from real, durable data instead of a field that would drift out of sync the next time anything else touched that invoice.
Partially Paid Invoices Only Get the Remainder
This is where the distinction matters most in practice. If an invoice already has $300 matched against a $1,000 total, bulk mark-as-paid doesn't insert a fresh $1,000 payment — it calculates the $700 still outstanding and records only that. The result is an invoice with two payment records totaling the full amount, an accurate combined history, rather than one payment overstating what was actually received or a second payment that would double-count the $300 already on file. If an invoice already has payments fully covering its total for some other reason, no new payment record gets inserted at all — there's nothing outstanding to record.
It Leaves the Same Trail a Manual Payment Would
Because bulk mark-as-paid goes through the real payment-recording path rather than a shortcut, it triggers everything a normal payment does: the invoice's payment snapshot gets refreshed from the transaction, an audit-trail entry gets written recording a "paid" event tagged with a bulk-action source, and — for the other bulk actions in the same batch operation, like archiving — a corresponding audit entry gets written too. Later, looking at that invoice's history, there's no visual distinction suggesting the payment was somehow less legitimate than one entered one at a time through the regular payment form; it's a normal payment record that happens to have been created through a bulk action, with the method field as the only trace of how it got there.
Why This Matters Beyond Just This One Feature
The underlying lesson generalizes past bulk actions specifically: nowhere in the product is an invoice's paid status something you can durably force into a particular value without backing it with an actual payment record. That's a deliberate constraint, not a missing shortcut — it's what guarantees that "this invoice shows as paid" and "this invoice has payment records covering its total" can never drift apart, which is exactly the property you want from a number that ends up in your financial reports.
Related Articles
How Business Profile Defaults Fill In New Invoices
Your business profile fills in your details, currency, tax rate, payment terms, and design on new blank invoices only. It never changes invoices you've already started, and only workspace admins can edit it.
What Your Client Receives When You Email an Invoice
The email is a short summary with the invoice number, issue date, due date, and total. It doesn't attach the PDF or include a link, and it comes from a no-reply address, so it helps to know what to send with it.
What Happens to Invoices You Create Without an Account
Without an account, saved invoices are kept in your browser's local storage, not on our servers. They aren't copied into an account when you sign up, and signing out of an account on that browser clears them.
Why Editing an Invoice Doesn't Update a Share Link You Already Sent
A share link stores a copy of the invoice as it was when you created the link. Later edits change your saved invoice, but anyone opening the old link still sees the old version, and so does the QR code on a re-downloaded PDF.
Deleting a Client Doesn't Touch Their Invoices
Saved clients are an address book, not a foreign key — invoices store billing details as their own inline copy, so deleting a client record leaves every invoice you've sent them completely intact.
What Happens When You Convert an Estimate to an Invoice
Converting doesn't turn the estimate into an invoice in place — it creates a brand-new invoice with a new ID and marks the original estimate as converted, permanently linking the two in both directions.