Skip to content

List Sync — Salesforce

The QuickFlo Connector is a lightweight Salesforce package that watches records you care about and sends each change to a QuickFlo workflow as a webhook. Use it to keep external systems in sync, enrich leads on the fly, build an audit trail, or kick off automation when records match specific criteria.

This guide walks through installing the package, configuring which objects and events to track, and where to look when something goes wrong. The Salesforce-to-Five9 field and list mappings are defined separately in QuickFlo — see QuickFlo: Configure List and Field Mappings below.

When a Salesforce record is created, updated, or deleted, an Apex trigger on the configured object evaluates your rules and — if they pass — enqueues an asynchronous job that POSTs a JSON payload to your QuickFlo webhook endpoint. You configure what to send in Salesforce; QuickFlo decides where it lands and how it’s shaped.

For the technical detail of how the trigger handles bulk volume, retries, and failures, see Salesforce: Under the Hood below.

  1. Open the install link

    Click this link while logged in as a Salesforce admin:

    Install QuickFlo Connector

    For a sandbox, replace login.salesforce.com with test.salesforce.com in the URL.

  2. Enter the installation password

    Paste the installation key you received from your QuickFlo implementation resource.

  3. Choose “Install for Admins Only”

    Recommended so that regular users can’t modify the connector’s configuration. Triggers still fire on every user’s DML regardless of this setting — it only controls who can see and edit the setup tab. Grant access to specific non-admin integration managers via the QuickFlo Admin permission set.

  4. Assign the permission set

    Once install completes, assign the QuickFlo Admin permission set to yourself (or whichever user will manage the configuration). Setup → Permission Sets → QuickFlo Admin → Manage Assignments.

Salesforce blocks outbound HTTP callouts to any domain not registered as a Remote Site. Before the connector can deliver events, you need to whitelist the QuickFlo endpoint.

Salesforce Remote Site Settings edit page showing the QuickFlo entry with URL https://run.quickflo.app and Active checked
  1. In Salesforce, go to Setup and search for Remote Site Settings in the Quick Find box.

  2. Click New Remote Site.

  3. Fill in the form:

    • Remote Site Name: QuickFlo
    • Remote Site URL: https://run.quickflo.app
    • Active: checked
  4. Click Save.

Open the QuickFlo Setup tab from the App Launcher.

Salesforce App Launcher search with 'QuickFlo Setup' typed in, showing the QuickFlo Setup tab result QuickFlo Setup tab showing the Connection Settings card with Endpoint URL, API Key, Active toggle, Batch Threshold, and Debug Logging fields
  1. Endpoint URL — Paste the webhook URL from your QuickFlo workflow. It will look like https://run.quickflo.app/w/<id>/<workflow-slug>.

  2. API Key — Paste the shared secret from the same workflow. QuickFlo sends this in the Authorization header so your workflow can verify the request is legitimate.

  3. Active — Toggle on to enable outbound syncing. Leave off during initial setup if you want to configure everything before firing any events.

  4. Batch Threshold — Maximum number of records per HTTP request. Default 10. Large DML operations are automatically split into batches of this size. Raise for high-throughput integrations, lower if your receiving endpoint is slow.

  5. Debug Logging — Enables verbose System.debug output for troubleshooting. Leave off in production unless you’re actively debugging, since it generates a lot of log volume.

  6. Click Save Connection, then Test Connection to send a ping and confirm credentials are valid.

Salesforce: Subscribe to Objects and Events

Section titled “Salesforce: Subscribe to Objects and Events”

The Synced Objects section lists every object the connector can track. Standard objects (Lead, Contact, Account, Opportunity, Campaign, CampaignMember) are preconfigured. Click + Add Custom Object to track a custom object.

Synced Objects section showing an expanded object row with Track Creation, Track Updates, and Track Deletes checkboxes and an Active toggle

Each object has three toggles that control which DML events are sent:

ToggleWhen it fires
Track CreationA new record is inserted
Track UpdatesAn existing record is updated
Track DeletesA record is deleted

A record can reach your list three ways, and each fires a different event.

  • Track Creation catches inserts. Every new record fires an insert, whether it came from a bulk load (Data Loader, the Bulk API) or a single hand edit. Bulk loads are the case that matters: a freshly imported record fires an insert and nothing else, so if creation isn’t tracked, the entire import is missed.
  • Track Updates catches edits to existing records. A rep changing a field, or an automation writing one back, fires an update.
  • Track Deletes catches deletions, so a record removed in Salesforce is removed downstream.

Tracking all three means a record lands on your list however it got there.

A single create can fire both a creation event and an update event. This happens when automation re-saves the record in the same transaction: a workflow field update, a Flow, or (for Leads and Cases) an assignment rule that sets the owner. Salesforce runs the insert, runs the automation, then fires the update.

It is not universal. It only happens on objects that have this kind of automation, and the source matters. Workflow field updates and Flows run on both manual and bulk creates. Assignment rules run on a UI create but not on a Data Loader insert, unless the import explicitly sets the assignment header. So the duplicate is most common on hand-created Leads and Cases, and rare on bulk imports.

If an object is only ever edited in place and the extra event is a problem, turn off Track Creation for it. Leave it on for anything that receives bulk loads.

If you only want to fire the webhook on specific changes, expand the Rules panel on any object and add one or more rules.

Expanded trigger rules panel showing a configured rule in the table and the Add Rule form with Field, Operator, Value, and Applies To (C, U, D) checkboxes

A rule consists of:

  • Field — the field to evaluate
  • Operator — one of equals, not equals, changed, contains, is blank, is not blank, etc.
  • Value — the comparison value (disabled for valueless operators like changed or is blank)
  • Applies To — which events the rule gates:
    • C — record matches the rule at creation
    • U — record matches the rule after update (regardless of previous value)
    • D — record matched the rule at the time it was deleted

Multiple rules on the same object are evaluated with AND logic — every rule must pass for the event to fire. If no rules are configured, every change passes through.

We recommend gating every object with at least one filter, so only qualified records reach the dialer. A single boolean usually does it: a field like is_dialable that reliably says whether a record should be synced. With no rules, every change is sent, including records that should never be called.

QuickFlo: Configure List and Field Mappings

Section titled “QuickFlo: Configure List and Field Mappings”

Everything above decides what Salesforce sends. The QuickFlo workflow decides what to do with it — which Five9 list each record lands in, which fields map where, and any transforms on the way through.

Those mappings live in a QuickFlo data store. Your implementation resource wires them with you on a call. Typical contents:

  • Salesforce object → Five9 list (e.g. Leads in Campaign X → Inbound_Q2)
  • Salesforce field → Five9 column (e.g. MobilePhonenumber1)
  • Transforms — phone formatting, timezone, disposition normalization

How the trigger handles volume and failures — useful if you’re evaluating operational risk or debugging unusual behavior.

  • Asynchronous — The trigger never blocks the user’s save. Payloads are sent from a Queueable job after the transaction commits.
  • Per-record batching — Bulk operations (data loader, list views, flows) are chunked into batches so a 10,000-row update doesn’t hit Salesforce’s callout or heap limits.
  • Retry with backoff — Transient failures (5xx, timeouts) are retried up to 3 times with a short escalating delay. Permanent failures (4xx) are recorded once and not retried.
  • Dead-letter queue — Every failed delivery lands in a QF_Sync_Error__c record with the full payload, status code, and reason, so nothing is silently dropped.
Advanced: exactly how retry and the dead-letter queue behave

Everything below is the Salesforce side — the package delivering a payload to QuickFlo. What happens after QuickFlo accepts a payload is covered under QuickFlo: View Sync Results.

Retry timing (Salesforce side). Each delivery is attempted up to 3 times. Transient failures (HTTP 5xx, 408, 429, or a callout timeout) re-enqueue with a short escalating delay — about 1 minute, then 2 — so a brief QuickFlo deploy or restart doesn’t burn every attempt in seconds. After the third failure the payload is dead-lettered. Permanent failures (4xx other than 408/429 — bad auth, validation) are not retried; they go straight to the DLQ on the first attempt.

Where the Salesforce side ends and QuickFlo begins. The Salesforce retry loop and the QF_Sync_Error__c dead-letter queue only cover the Salesforce → QuickFlo hop. The moment QuickFlo returns 200, responsibility moves to QuickFlo — anything that goes wrong afterward (transform, field mapping, the push to Five9) is not in the DLQ. It surfaces in the QuickFlo Sync Dashboard instead. A record missing from Five9 with an empty DLQ always means “look in QuickFlo, not Salesforce.”

DLQ record fields (Salesforce side). Each QF_Sync_Error__c row stores the full payload, the object and operation, the HTTP status code, the error message, the attempt count, and a manual Resolved__c flag.

Duplicate delivery is possible by design. A callout that times out after QuickFlo already processed the payload still counts as a failure on the Salesforce side, so it gets retried — meaning QuickFlo can receive the same payload more than once. Every payload carries a unique eventId so a repeat can be recognized and discarded on the QuickFlo side. This is why delivery is at-least-once, not exactly-once.

When a record isn’t showing up in Five9, the QuickFlo side is usually the first place to look — not the Salesforce dead-letter queue. The DLQ only catches failures where Salesforce couldn’t deliver to QuickFlo. If the payload arrived in QuickFlo but something went wrong transforming or pushing it to Five9, the DLQ is empty but QuickFlo has the full record.

The Sync Dashboard is the primary investigation tool. It logs one row for every attempted CREATE, UPDATE, or DELETE operation against a Five9 list — successful or failed — with the error kind and error message inline.

QuickFlo Sync Dashboard showing a searchable List Syncs table with timestamp, operation type, object name, list name, Salesforce ID, success status, error kind, and error message columns, plus success/failure donut chart and volume-by-list bar chart

Use it to:

  • Find a specific record — search by Salesforce ID, list name, or operation type
  • Triage a batch of failures — filter by date range and error kind (e.g. FIVE9_INVALID_ACCOUNT, FIVE9_RATE_LIMITED)
  • Spot patterns — the donut chart shows overall success/failure mix; the bar chart shows volume per Five9 list

Common error kinds you’ll see in the table, drawn from the Five9 error taxonomy:

  • FIVE9_INVALID_ACCOUNT / FIVE9_AUTH_FAILED — credentials need rotation or the connection needs updating
  • FIVE9_INVALID_ARGUMENT — Five9 rejected the payload shape (usually a field-mapping mismatch)
  • FIVE9_NOT_FOUND — the target list, contact, or campaign doesn’t exist in Five9 with the name expected
  • FIVE9_RATE_LIMITED — Five9 throttled the call. The integration retries transient throttles automatically; sustained throttling shows up here only after retries are exhausted
  • FIVE9_SERVICE_UNAVAILABLE — transient Five9 outage. The integration retries automatically
  • FIVE9_DUPLICATE — record already present in the target list (often expected on re-imports)
  • DRY_RUN — dry-run mode skipped the actual call (a success entry, not a failure)

Most issues can be resolved from the dashboard alone. The error message column usually tells you exactly what went wrong; the error kind tells you what kind of fix it needs (credential, mapping, list config, transient).

When the Sync Dashboard row doesn’t give you enough detail, open the underlying Execution for a full per-step trace: input/output at every step, timing, and stack traces.

QuickFlo Executions view for the List Sync workflow showing recent runs with per-step status, timing, and error details
  1. In QuickFlo, open the List Sync workflow → Executions.
  2. Filter by status or by a searchable attribute (e.g. Salesforce ID if tagged).
  3. Click into a failed execution to see which step failed, the exact payload each step received, and the Five9 API response.

Every failed webhook delivery is recorded as a QF_Sync_Error__c record. To view them:

  1. Open the App Launcher and search for QuickFlo Sync Errors.

  2. Each record shows:

    • Object and Record ID that triggered the event
    • Event Type (Insert / Update / Delete)
    • HTTP Status Code returned by QuickFlo
    • Error Message — the first 32 KB of the response body
    • Request Payload — the first 131 KB of what was sent
  3. After fixing the downstream issue, you can re-send failed records by toggling the source record (any trivial update will re-trigger the webhook), or by running a data fix in Apex.

When a webhook isn’t firing and there’s no dead-letter record, the Apex trigger itself may be the issue. Turn on debug logs to see what’s happening:

  1. Enable Debug Logs

    Setup → Debug Logs → New. Set the Traced Entity to the user who’s making the changes, and use a log level with Apex: FINEST and Callouts: FINEST.

  2. Reproduce the change

    Perform the DML operation (create, update, or delete a record on a tracked object).

  3. Open the log

    Back in Debug Logs, click the most recent entry. Search for QuickFlo — the connector prefixes every debug line so it’s easy to find.

  4. What to look for

    • QuickFlo: Rule eval — shows which rules passed or failed
    • QuickFlo: Enqueueing batch — confirms the async job was scheduled
    • QuickFlo: HTTP 200 / QuickFlo: HTTP 5xx — the response from your webhook
    • QuickFlo: Retry #N — backoff attempts on transient failures

A New Record Fires Both a Create and an Update

Section titled “A New Record Fires Both a Create and an Update”

The record tripped automation that re-saved it in the same transaction: a workflow field update, a Flow, or (on a Lead or Case) an assignment rule. Salesforce fires the insert, runs the automation, then fires the update. This is expected, not a bug. See The create-then-update case above for which automations cause it and why it shows up more on hand-created records than on bulk imports.

If you don’t need to distinguish creates on this object and it is never bulk-loaded, turn off Track Creation. Otherwise dedupe downstream on record Id.

  • Open the QuickFlo Executions view first — if you see the event arrive there, the Salesforce side is fine and the issue is in the workflow itself.
  • If QuickFlo shows nothing, check the Active toggle in Connection Settings.
  • Confirm the object’s Active toggle is on.
  • Confirm at least one of Track Creation / Track Updates / Track Deletes is checked.
  • If you have Trigger Rules, confirm the record actually matches them — add a temporary “always true” rule (e.g. Id is not blank) to isolate whether the rules are the gate.
  • Check QuickFlo Sync Errors in Salesforce for delivery failures.

This means the Remote Site wasn’t added (or was added with a different URL). See Add the Remote Site above.

By default, data loader and similar tools will trigger webhooks for every imported record. If you’re seeding data, temporarily toggle Active off in Connection Settings, perform the import, then toggle it back on.