LedgerUp Resources
How to Get Stripe Payment Status Back into Salesforce: Paid, Failed, and Aging on the Account and Opportunity
Sales asks finance whether the customer paid. Finance opens Stripe. The answer should already be on the Salesforce account. This guide covers which Stripe events matter, which fields to write on the account, opportunity, and contact, how aging gets computed, the four ways to build the write-back, and the failure modes that make status wrong.
In This Article
Payment status write-back is the half of a Salesforce to Stripe integration that most teams build last and need first. The first half creates the subscription. The second half tells the account owner that the invoice is paid, that the card failed, or that the customer is 45 days past due, in the record they already have open. Without it, every renewal conversation starts with a Slack message to finance.
This guide covers the write-back for B2B billing on Stripe: invoices on net terms paid by ACH, wire, or card, with subscriptions and one-off invoices on the same account. It pairs with the Stripe reconciliation page, which covers the payout side (fees, refunds, disputes, and matching to the ledger). Updated September 2026.
Quick answer
Subscribe to Stripe's invoice, subscription, charge, and dispute events; on each event, resolve the Stripe customer to the Salesforce account by the stored ID; write invoice status, paid date, amount due, and subscription state to the account and the originating opportunity; run a daily job that computes aging buckets and past-due totals per account from open invoices; create a task for the account owner and a Slack alert on a failed charge; and keep one field that says when the status was last updated so nobody trusts a stale one. Stripe's Salesforce app, an automation tool, a webhook endpoint, or LedgerUp can each do part of this; the table below shows which parts.
What to write, and where
| Salesforce record | Fields worth having | Why |
|---|---|---|
| Account | Stripe customer ID, open AR balance, past-due amount, oldest open invoice date, last payment date, collections status, status last updated | The account is where sales and CS look. Balance and past-due amount answer "can we upsell them" and "should we pause work." |
| Opportunity | Stripe subscription ID, Stripe invoice ID, invoice status, invoice paid date, amount paid | Ties commission, bookings, and cash together. Closed-won with an unpaid invoice is a different report from closed-won and paid. |
| Contact | Billing contact flag, Stripe customer email | Collections emails go to the right person, and the AE knows who that is. |
| Task (on failed charge or past-due threshold) | Subject, due date, invoice link, amount, owner = account owner | A field nobody watches is not an alert. A task is. |
| Optional: Invoice custom object | One record per Stripe invoice with number, status, due date, amount, PDF link | Needed if you want invoice-level reporting in Salesforce rather than account-level summaries. Stripe's Salesforce app creates these as synced objects. |
Book a LedgerUp Demo
See how Ari connects contracts, billing, collections, approvals, and accounting records while finance stays in control of exceptions.
Book a LedgerUp DemoThe Stripe events that matter
- invoice.finalized and invoice.sent: the invoice exists and is out. Write the invoice ID, amount, due date, and status open.
- invoice.paid: write paid, the paid date, and reduce the account's open balance. This fires for card, ACH, wire (when Stripe records the transfer), and out-of-band payments marked paid.
- invoice.payment_failed: the card or bank debit failed. Create the task, alert the owner, and set collections status. Stripe will retry per its dunning settings; the task should say so.
- invoice.marked_uncollectible and invoice.voided: remove from open AR; write the reason.
- customer.subscription.updated and customer.subscription.deleted: seat count, price, cancellation state. The account's subscription state should match Stripe within minutes.
- charge.refunded and charge.dispute.created: a paid invoice is no longer simply paid. Write the refund or dispute amount and alert finance; disputes have deadlines.
Events can arrive out of order and more than once. Every handler should read the current object from Stripe rather than trusting the event payload, and should be safe to run twice.
LedgerUp Insight: The workflow described above is one that LedgerUp automates end-to-end. Ari handles the repeatable steps, keeps the source records connected, and routes exceptions to finance for review.
Aging is a calculation, not an event
No Stripe event says "this invoice is now 31 days past due." Aging buckets (current, 1 to 30, 31 to 60, 61 to 90, over 90) and the past-due total per account come from a daily job that lists open invoices per customer, compares due dates with today, and writes the sums to the account. The same job is the natural place to flip collections status, decide which accounts get a follow-up, and create tasks when a threshold is crossed. If the write-back only listens to events, aging never updates, and the account looks fine until the invoice is paid or written off.
Four ways to build the write-back
| Method | Event handling | Account summary fields | Aging | Failed-charge task and alert | Collections |
|---|---|---|---|---|---|
| Stripe for Salesforce Platform | Syncs Stripe invoices, subscriptions, and customers into Salesforce as objects, event-driven and bidirectional | Roll-ups and flows an admin builds on the synced objects | A scheduled flow or report an admin builds | A flow on the synced invoice status | No |
| Zapier or Make | One Zap per Stripe event updating the opportunity or account | Field updates per event; totals are hard | No practical way | Yes, Create Task step | Templated emails at best |
| Webhook endpoint (Apex REST, Workato, MuleSoft) | Your code or recipe handles each event with retries | Whatever you compute | A scheduled job you write | Yes, as code | Build it or use another tool |
| LedgerUp | Ari consumes Stripe events and reconciles them with the contract and the invoice | Open balance, past due, oldest open, last payment, collections status written to the account; invoice status and paid date to the opportunity | Computed daily and written back | Task for the owner plus a Slack message with the invoice and contract context | Contextual follow-ups on overdue ACH, wire, and card invoices, with escalation to the owner |
Failure modes that make status wrong
- Name matching. Two accounts named the same, or one account renamed, and the status lands on the wrong record. Store the Stripe customer ID on the account and match on it only.
- Invoice paid outside Stripe. A wire arrives at the bank; nobody marks the Stripe invoice paid out of band; Salesforce shows past due for a customer who paid two weeks ago. The reconciliation process has to close this loop, which is why the write-back and payout reconciliation belong together.
- Refunds and disputes after paid. Status stays paid while the money went back. Handle charge.refunded and charge.dispute.created.
- Multiple subscriptions or one-off invoices per account. Opportunity-level status is fine; account-level status has to sum across all of them.
- Sandbox IDs in production. Test-mode customer IDs written to the account during setup never match live invoices.
- Field-level security. The integration user can write the field; the account owner cannot see it. Check profiles before declaring the write-back live.
- Stale status with no timestamp. A status field with no last-updated field is trusted long after the integration silently stopped. Write the timestamp every time.
Frequently asked questions
Book a LedgerUp Demo
See how LedgerUp connects your CRM, billing, and ERP systems to eliminate manual work and accelerate revenue.
Get Started with LedgerUp