Package Library
Installable package

Activity Sync

Sync call, chat, email, or sms interactions from any source to your CRM as activity records, and enrich with any data you want.

@quickflo/activity-syncby @quickflov1.4.1
See how Activity Sync works

Package overview

Overview

Activity Sync saves Five9 activity as Salesforce Tasks.

  • The first event for a call creates a Task.
  • Later events for the same call update that Task.
  • Five9 can send the event and move on. QuickFlo finishes the Salesforce work in the background.

Keep the main activity-sync workflow set to Async and its sub-workflows set to Auto. All built-in sub-workflow calls, including the failure handler, run inline inside the parent's worker.

Set up

  1. Install Activity Sync.
  2. Connect Salesforce and name the connection salesforce.
  3. Review the salesforce record in the activity_sync_settings data store. Use a Salesforce Task text field marked Unique for session_id_field if events for the same call can arrive at the same time.
  4. Send a test event to the installed activity-sync webhook.
  5. Check the Activity Sync dashboard for the result.

Settings

The package installs this record:

  • Data store: activity_sync_settings
  • Record key: salesforce
{
  "saveTaskWithoutInvalidWhoIdOrWhatId": true
}

The setting has two choices:

Value What Activity Sync does
true If Salesforce rejects WhoId or WhatId because the related record is invalid or deleted, remove the rejected relationship and save the Task anyway.
false Do not remove either relationship. The Salesforce create or update fails, and Activity Sync records the error.

true is installed by default. This is usually the best choice because the call activity is still saved even when its contact, lead, account, opportunity, or other related record is no longer available.

This setting only applies after Salesforce rejects a valid WhoId or WhatId field with ENTITY_IS_DELETED or INVALID_CROSS_REFERENCE_KEY. It does not remove unrelated fields.

If Salesforce cannot identify which relationship is bad and both fields are present, Activity Sync first tries again without WhatId. If Salesforce still rejects the relationship, it tries once more without both WhoId and WhatId.

Send an activity

{
  "session_id": "abcd-efgh-aaaa-bbbb-cccc",
  "session_id_field": "Five9__Five9SessionId__c",
  "field": {
    "Description": "Call notes",
    "RecordingLink__c": "https://example.com/recording",
    "WhoId": "003000000000001AAA",
    "WhatId": "001000000000001AAA"
  }
}
Field Required What it does
session_id yes Identifies the call. The same value updates the same Salesforce Task.
session_id_field no Salesforce Task field that stores the ID. Defaults to Five9__Five9SessionId__c.
field yes Salesforce Task fields to save.
field.Subject no Sets the Task subject. If omitted, Activity Sync creates one and keeps it on later updates.

Send a non-empty session_id without curly braces ({ or }). The session field must exist in the cached Task field list. Activity Sync rejects an invalid session field before querying or writing Salesforce. A value in field cannot override the session ID used to match the Task.

Check the result

Five9 does not wait for the completed Salesforce response. The webhook acknowledgement means QuickFlo accepted the event and queued it.

Use the Activity Sync dashboard to see the final result:

  • success: Salesforce saved the Task on the first attempt.
  • recovered: Salesforce rejected the first attempt, but Activity Sync fixed the problem and saved the Task.
  • error: Salesforce did not save the requested change.

For more detail, open the workflow execution or the matching record in activity_sync_history.

The history table shows Time → Status → Action → Explanation → Session ID → Fields → Salesforce ID → Salesforce Task, with the newest activity first. Session ID identifies the activity; Fields shows the final Task fields sent, and Salesforce ID is shown when available. The explanation tells you whether the Task was saved, saved after recovery, or failed. A recovered result can include an omitted invalid WhoId (Name) or WhatId (Related To) value; it is not the same as a first-attempt success.

Raw error, recovery, and Salesforce response objects stay in drill-down. Click a status slice in the counts chart to drill into the full records, or open activity_sync_history for the session ID, fields sent, execution ID, and raw error, recovery, and Salesforce response details. Nothing is removed from the history record.

The explanation is calculated from the existing history when the dashboard is queried. It does not run another workflow or call Salesforce.

Handle failed activities

When a Salesforce write still fails after Activity Sync finishes its built-in recovery, Activity Sync first records the final result in activity_sync_history. It then starts the optional Handle Failed Activity workflow inline, as part of the same run. This does not add a separately metered workflow execution.

The installed handler only writes a warning to the QuickFlo logs. Customize or replace it when you want to take an action. For example, add a Switch step that checks {{ initial.errorCode }}, then send selected failures to Slack, email, a ticketing system, or a review data store.

The handler receives the session ID, attempted create or update action, Task fields, error code and message, HTTP status, recovery details, Salesforce record details when available, and a unique failure ID.

Use those inputs directly; you do not need to fetch the history record again. When history uses analytics-backed storage, new records can take a few seconds to appear in reads and dashboards even though the write has completed.

The handler runs only when the final status is error. It does not run for success or recovered. The call uses Continue on error, so a handler error does not replace the recorded Salesforce result.

Keep inline actions short: the parent waits for them, and they share its worker and overall timeout. For long-running or independent work, add a sub-workflow call inside your handler and enable Run in background on that call. That dispatched work is a separate, metered execution. The parent itself remains async, so Five9 does not wait for either approach.

Use {{ initial.failureId }} as the unique key for your ticket or review record. Replaying the handler can repeat an action, so check that key before sending another notification or creating another ticket. A new Activity Sync execution has a new failure ID, even for the same session.

The handler also receives INVALID_ACTIVITY_INPUT when the writer rejects an empty session ID or invalid session field; its action is validate. For Salesforce write failures, action is create or update.

This handler does not catch failures that stop the workflow before the writer returns a result, such as a failed schema refresh, enrichment, connection, or Salesforce lookup. Check failed Activity Sync executions for those problems. If saving history or calling the handler fails, check the parent execution and its inline child trace. After fixing the problem, replay only the handler with the same failure payload when appropriate. Routing is best effort, not a guaranteed review queue.

How fields are handled

Activity Sync automatically removes field names that do not exist on the Salesforce Task object.

The valid Task field names are stored here:

  • Data store: activity_sync_schema_cache
  • Record key: salesforce-task-fields

The first activity refreshes this record if it does not exist. A daily schedule refreshes it again at 03:17 UTC. Normal activity runs read the cached list and do not request the full Task schema from Salesforce.

With a warm cache, a normal activity uses two Salesforce API calls: one lookup to decide whether to create or update, followed by the create or update.

WhoId and WhatId are different: the field names are valid, but the IDs inside them can point to deleted or invalid records. The saveTaskWithoutInvalidWhoIdOrWhatId setting controls what happens in that case.

How retries work

  • Salesforce reads and the first write retry up to three times when a request fails temporarily.
  • Retries start one second apart and wait longer after each failure.
  • If a create may have reached Salesforce but its response was lost, Activity Sync checks for the Task before trying another create. This reduces duplicate creates; it does not make simultaneous requests atomic.
  • Activity Sync makes only a small, fixed number of recovery attempts. It does not retry forever.

To prevent duplicate Tasks when two events for the same call arrive together, the Salesforce field named by session_id_field must be marked Unique. An External ID field alone does not guarantee uniqueness. Without a Unique field, both requests can find no existing Task and create one. With a Unique field, Salesforce rejects the second create; that request is recorded as an error and can be retried after the first create finishes.

Activity history

activity_sync_history keeps the latest result for each session_id. A new event for the same call replaces that history record.

The record includes the action, final status, Salesforce Task ID and URL, fields sent, execution ID, Salesforce response, error details, and recovery details.

Customize fields

Use the optional Enrich Task Fields sub-workflow to add or override Salesforce Task fields. Activity Sync checks the combined fields against the cached Task field list before saving them.

Salesforce is currently the supported CRM. For help, contact support@quickflo.app.

What’s inside

One install, the complete system.

Workflows

5 included

  • Activity Sync
  • Activity Sync Refresh Salesforce Task Schema
  • Activity Sync Enrich Fields
  • Activity Sync Write Salesforce Task
  • Activity Sync Handle Failed Activity

Triggers

2 included

  • Activity Sync
  • Activity Sync Refresh Salesforce Task Schema Daily

Dashboards

1 included

  • Activity Sync

Data stores

3 included

  • Activity Sync History
  • Activity Sync Settings
  • Activity Sync Schema Cache

Configure during install

Set up what it needs. QuickFlo handles the wiring.

You’ll connect or provide these requirements during guided setup, before anything changes.

1 environment valueProvide the values this package needs to run.

Extension points

Designed for your team to make their own.

This package includes clearly defined areas your team can customize without forking or rebuilding the rest of the solution.

Enrich Task Fields

Customize when needed

Customer extension point. Return any additional or override fields from this sub-workflow's Return step to include them in the Salesforce Task create/update. Returned keys are merged with the base fields (right-hand wins, so returned values override) and then filtered against Salesforce Task's valid fields, so invalid keys are dropped automatically.

Handle Failed Activity

Customize when needed

Customer extension point. Runs inline after Activity Sync records a terminal failure, without a separate execution charge. Use errorCode to route failures. Dispatch a background sub-workflow inside this handler only when needed.