Integration & Automation

Turning an Unpaid Invoice into a Phone Call, Automatically

Automated collections outreach from Salesforce to Amazon Connect and back

Internal case studySalesforceAmazon ConnectIVRWorkflow Automation

The problem

Collections calls used to mean someone manually pulling a list of overdue accounts and dialing through it. That doesn't scale, and it leaves no consistent record of what was tried or what happened. The fix was to make the call itself part of the pipeline: Salesforce identifies who needs to be called, an automated voice flow makes the call and collects an outcome, and that outcome is written back onto the same record — without anyone dialing a number by hand.

The shape of the flow

The pipeline moves in one direction and closes the loop in a second pass. First, outstanding invoices are pulled out of Salesforce and queued up as call jobs. Each job becomes an outbound call placed through Amazon Connect, which plays the invoice details and gathers a response — payment confirmation, a request to speak to an agent, or no answer. Whatever the outcome, it's tracked through to completion and then reconciled back onto the Salesforce invoice as a status field, so the next person who looks at that account sees exactly what was attempted and how it went.

Call setup

Overdue invoices pulled from Salesforce, queued as outbound call jobs.

In-call

Amazon Connect flow runs, collecting payment status, agent transfer, or no answer.

Reconciliation

A periodic sweep of finished calls writes the final outcome back to the invoice.

Create vs. update, decided once

As with any system feeding an external channel from Salesforce, the direction of truth had to be unambiguous. Salesforce is the only place a call job originates — nothing on the calling side ever invents a new invoice or account. Every status the call flow produces is matched back to the invoice it came from and applied as an update. A call that can't be matched, or that ends in an ambiguous state, is left for the next reconciliation pass rather than guessed at.

What a flow like this actually needs

A queue between "ready to call" and "in progress"

Call jobs move through several states before they're done. A queue keeps each one moving independently instead of one slow call blocking the batch behind it.

A place to hold in-flight state

A call isn't a single request/response — it has a lifecycle. Something needs to track where each call is until it reaches a final outcome, separate from the system of record.

One deterministic matching key

Every call has to trace back to the exact record that triggered it, so the outcome lands on the right invoice and never on the wrong one.

Batching on every write back to the system of record

Writing outcomes one at a time doesn't hold up at volume. Batched writes, with partial-failure handling, keep a few bad records from blocking everything else.

A reconciliation pass, not just live events

Calls fail silently, get dropped, or end in a state nothing anticipated. A periodic sweep that re-checks and closes out anything unresolved is what makes the loop trustworthy.

Internal write-up — kept intentionally high-level. For implementation specifics, see the pipeline source directly.

Facing something similar?
Let’s talk about what this would look like for you.