Skip to main content

How do I reconcile Stripe invoice payment status against my open AR balance?

Compare each Stripe invoice's status field — draft, open, paid, uncollectible, or void — against what your AR aging report shows for the same invoice. A mismatch almost always means a status-change event (paid, voided, marked uncollectible) fired on Stripe's side but the workflow that updates AR aging never processed it, not that the two systems actually disagree about the invoice.

Zuny FesterBy Zuny Fester, Head of Operations and Marketing
Reviewed by Zuny Fester
Published Last reviewed Editorial policy

Part of the finance integrations guide.

Stripe's 5 invoice statusesdraft, open, paid, uncollectible, void
SymptomAR aging shows an invoice as open that Stripe already marked paid, void, or uncollectible
Root causeThe specific status-transition event wasn't processed by the workflow that updates AR aging
Where to checkStripe's own invoice list, filtered by status, compared line by line against AR aging for the same period

The five states an invoice can be in

Stripe's Invoice object carries a single status field, documented as one of draft, open, paid, uncollectible, or void, with a status_transitions object recording when each change happened (finalized_at, marked_uncollectible_at, paid_at, voided_at). That timestamp data is exactly what makes a reconciliation possible — you're not just checking current status, you're checking when it changed relative to when AR aging last updated.

Why AR aging drifts from Stripe's own record

AR aging is populated when an invoice is created, but every status change after that — paid, voided, marked uncollectible — is a separate event. If the workflow that maintains AR aging only listens for invoice creation and not the later transition events, Stripe's own record moves forward while AR aging stays frozen at whatever status it captured first. The two systems aren't actually in conflict about the invoice; one of them just never heard about the update.

How to run the comparison

Pull Stripe's invoice list for the period, and for each invoice compare its status and status_transitions timestamps against the corresponding row in AR aging. Any invoice where Stripe shows a later status than AR aging reflects is a candidate for a stale poll, not a genuine disagreement — Loopfour's Stripe integration has no webhook handler, so the fix is scheduling listInvoices or getInvoice to run periodically against open invoices, not re-deriving the status by hand for every invoice.

Next step

Map the finance workflow with the most exposure and prove the automation path.

Bring the invoice, contract, payment reconciliation, or customer finance workflow you have to defend at audit. Loopfour can map the trigger, controls, integrations, and approval loop.

Book a workflow review

Worked example

A $1,850 invoice marked paid in Stripe, still open in AR aging

A customer pays a $1,850 invoice through Stripe's hosted invoice page. Stripe's own record updates immediately: status moves to paid, and status_transitions.paid_at records the exact timestamp. But AR aging was populated by a single getInvoice call when the invoice was first created and finalized, and nothing has re-checked it since, so it keeps showing $1,850 as an open, aging balance for that customer. Pulling Stripe's invoice list and comparing paid_at against the AR aging snapshot date immediately shows the gap — the fix is a scheduled re-poll of open invoices, not investigating the customer for a payment problem that doesn't exist.

Frequently Asked Questions

No — uncollectible means Stripe attempted collection and it failed or was abandoned; the invoice can still theoretically be paid later. Void is terminal and permanent, and only reachable from open or uncollectible status.

In practice no — finalizing a draft invoice moves it to open (or immediately attempts payment if collection_method is charge_automatically), and only a successful payment moves it to paid from there.

No — that's a separate problem about cash actually landing in the bank. This is about whether AR's own record of who owes what matches what Stripe's invoice object says, independent of when the money settles.

Sources

Related