/
Data Sync API

Data Sync API

Data Sync

Syncing data in Pulsar is a complex process made easy with a few simple methods.

In order to get progress updates and determine when we are finished, we must interact with the Pulsar Platform through the registerHandler method. In FSL contexts we must use methods provided on the pulsar object: addSyncFinishedHandler and addSyncUpdateHandler.

Once we are properly set up to have our callback methods used by the platform we can begin a sync using the syncdata API.

Handling Sync Notifications

Overview

When invoking the syncdata call, it is important to note that the function returns immediately after initiating the sync, not when the sync process finishes. The Pulsar sync process provides a feedback mechanism that allows monitoring sync progress, which can be leveraged in a custom app to track sync completion and intermediate updates.

Context Awareness:

Receiving Sync Progress & Completion Notifications

You can register JavaScript handler functions with the Pulsar bridge to receive updates about sync progress and completion. The two available handlers are:

  • syncDataUpdate – Provides real-time progress updates, including sync pass number and percentage completed.

  • syncDataFinished – Triggers when the sync process is fully complete.

These handlers allow execution of custom logic, such as notifying users when the sync reaches specific progress milestones (e.g., 50% completion).

Only one handler can be assigned per handler name.

Register Handlers Before Sync Starts

  • Since syncdata returns immediately after initiating sync, handlers must be set up before calling syncdata.

  • If the sync process completes quickly, missing handler registration may result in lost sync progress updates.

Avoid issuing a sync request from within a sync handler, as this can create an infinite loop.

Tracking Sync Progress

Syncing can take a long time if there are a lot of changes or data to update. In almost all cases when using the Data Sync API it will be necessary to register the syncDataFinished handler in order to be notified when the sync has finished. It can also be useful to register a syncDataUpdate handler which will receive information about the progress of the sync as it occurs.

syncDataUpdate handler

The syncDataUpdate handler provides periodic updates on sync progress. The handler function receives an object containing:

  • syncpass (string) – The current sync pass number (integer value). Sync may take multiple passes to fully complete.

  • syncpercent (string) – A floating-point value (0 - 100.00) representing completion percentage for the current sync pass. Since sync may require multiple passes, this value may reach 100.00 more than once.

syncDataFinished handler

The syncDataFinished handler triggers when sync completes. The handler function receives an object containing:

  • success (boolean)true if sync completed successfully, false if it failed.

Only one syncDataFinished handler can be added.

A Complete Example

When operating outside the context of FSL:

// Add a handler to respond to sync progress updates bridge.addHandler('syncDataUpdate', function(response) { if (response.hasOwnProperty('syncpercent') && response.hasOwnProperty('syncpass')) { var syncPass = response.syncpass; var syncPercent = response.syncpercent; someScreenUpdate(syncPass, syncPercent); } }); // Add a handler to respond when the sync has completed bridge.addHandler('syncDataFinished', function(response) { console.log('sync data finished'); if (response.hasOwnProperty('success')) { if (response.success) { doSyncSuccess(); // code that should execute after a successful sync } else { doSyncFailure(); // code that should execute after a failed sync } } // clean up the handlers bridge.removeHandler('syncDataFinished'); bridge.removeHandler('syncDataUpdate'); }); // now, start a sync var syncRequest = { 'type' : 'syncdata', 'data' : { } }; bridge.send(syncRequest, function(results) { if (results.type == 'error') { errStr = results.data; alert('A problem occurred:\n' + errStr); } else { console.log('Pulsar is syncing...'); } });

When you are in FSL, use the pulsar object that is present alongside the bridge on the window.

// Add a handler to respond to sync progress updates pulsar.addSyncUpdateHandler('mySyncUpdateHandler', function(response) { if (response.hasOwnProperty('syncpercent') && response.hasOwnProperty('syncpass')) { var syncPass = response.syncpass; var syncPercent = response.syncpercent; someScreenUpdate(syncPass, syncPercent); } }); // Add a handler to respond when the sync has completed pulsar.addSyncFinishedHandler('mySyncFinishedHandler', function(response) { console.log('sync data finished'); if (response.hasOwnProperty('success')) { if (response.success) { doSyncSuccess(); // code that should execute after a successful sync } else { doSyncFailure(); // code that should execute after a failed sync } } // clean up the handlers pulsar.removeSyncUpdateHandler('mySyncUpdateHandler'); pulsar.removeSyncFinishedHandler('mySyncFinishedHandler'); }); // now, start a sync var syncRequest = { 'type' : 'syncdata', 'data' : { } }; bridge.send(syncRequest, function(results) { if (results.type == 'error') { errStr = results.data; alert('A problem occurred:\n' + errStr); } else { console.log('Pulsar is syncing...'); } });

syncinfo

Description

The syncinfo API method returns information about the most recent Pulsar sync operation. This can be useful to determine causes for failures as well as provide data around what may or may not have changed as a result of the sync.

Request Parameters

  • type (string, required) – Must be set to 'syncinfo' for this operation.

  • data (object, required) – An empty object. This value will be ignored, but the field is required.

Example Request

The following returns information regarding the last Pulsar sync operation – whether successful or a failed sync.

var request = { 'type' : 'syncinfo', 'data' : { } // empty object- this is required in the current API }; bridge.send(request, function (results) { console.log('Javascript got its response: ' + results); if (results.type === 'syncinfoResponse') { var previoussynctime = results.data.previoussynctime; var lastsuccessfulsync = results.data.lastsuccessfulsync; } else if (results.type == 'error') { errStr = results.data; alert('A problem occurred:\n' + errStr); } });

Example Response

If the request succeeds, the response data will contain an object with a number of useful data points about the most recent sync.

{ 'type': 'syncinfoResponse', 'object': '', 'data': { 'lastfailedsync': '1970-01-01T00:00:00.000Z', 'lastsuccessfulsync': '2023-06-01T04:10:55.020Z', 'previoussynctime': '1970-01-01T00:00:00.000Z', 'lastsyncduration': '44.9', 'lastsyncsuccess': 'YES', 'localchangespendingcount': '0', 'localcreatedcount': '0', 'localdeletedcount': '0', 'localupdatedcount': '0', 'localupdateduniquecount': '0', 'metadatasyncduration': '9.4', 'metadatasyncperformed': 'YES', 'reachabilitysyncduration': '0.0', 'reachabilitysyncperformed': 'NO', 'refreshduration': '0.0', 'refreshperformed': 'NO', 'schemachanged': 'NO', 'serverintegratedcount': '4304', 'serverprocessedcount': '4485', 'serverprocessedobjectcountmap': 'Account: 4000,Contact: 400,Case: 85', 'syncdomaintype': 'all', 'syncgeneration': '1', 'syncpasscount': '1', 'syncresumed': 'NO', 'syncwindowtype': 'initial' } }

Response Fields Explained

Field

Description

Field

Description

lastsuccessfulsync

A string representation of the DateTime value corresponding to the last successful sync event. It could be the most recent sync. If no successful sync has occurred, this value will be '1970-01-01T00:00:00.000Z'.

lastfailedsync

A string representation of the DateTime value corresponding to the last failed sync event. It could be the most recent sync. If no successful sync has failed, this value will be '1970-01-01T00:00:00.000Z'.

previoussynctime

A string representation of the DateTime value corresponding to the most recent sync event. If no sync has run, this value will be '1970-01-01T00:00:00.000Z'.

lastsyncduration

A string representation of the number of seconds that the last sync took to complete.

lastsyncsuccess

Either 'YES' or 'NO' depending if the last sync finished successfully.

localchangespendingcount

A string representation of the number of local changes that have yet to be synced.

localcreatedcount

A string representation of the number of locally created records sent to the server during the last sync.

localdeletedcount

A string representation of the number of locally deleted records sent to the server during the last sync.

localupdatedcount

A string representation of the number of locally updated records sent to the server during the last sync.

localupdateduniquecount

A string representation of the number of locally updated unique records sent to the server during the last sync.

metadatasyncduration

A string representation of the number of seconds that the metadata portion of the last sync took to complete.

metadatasyncperformed

Either 'YES' or 'NO' depending if the last sync included a metadata sync.

reachabilitysyncduration

A string representation of the number of seconds that the reachability portion of the last sync took to complete.

reachabilitysyncperformed

Either 'YES' or 'NO' depending if the last sync included a reachability sync.

refreshduration

A string representation of the number of seconds that the refresh settings portion of the last sync took to complete.

refreshperformed

Either 'YES' or 'NO' depending if the last sync included a settings refresh.

schemachanged

Either 'YES' or 'NO' depending if the schema was altered as part of the last sync.

serverintegratedcount

A string representation of the number of retrieved records ultimately added or updated on the local device.

serverprocessedcount

A string representation of the number of full or partial records retrieved from the server for any reason (total across all object types).

serverprocessedobjectcountmap

A string containing a list of object types and the number of records retrieved by the server corresponding to that type.

syncdomaintype

One of four possible values: 'all', “mini', 'single', or 'push'.
all is a standard or catch-up sync.
mini is a catch-up sync for a subset of the objects.
single is a catch-up sync for a single object (and possible others via parent/child relationships, though only one level of relationship)
push is a sync that only pushes changes to the server, it does not retrieve any changes.

syncgeneration

A string representation of the number of total sync passes since app was installed.

syncpasscount

A string representation of number of passes that were performed with the last sync.

syncresumed

Either 'YES' or 'NO' depending if the sync was a continuation of an interrupted or incomplete sync.

syncwindowtype

One of three values:

'initial': The first sync performed after installing the app.
'catchup': Any sync that is performed after the initial sync and is not a complete sync.
'complete': A sync that is not an initial sync, but is performing a full sync due to a setting change.

lastfailedsynccurlerrorcode

A string representation of the one or two digit number representing the CURL network communication error that led to a sync failure, or zero if there was no CURL error.

lastfailedsynccurlerrormessage

The error message associated with the CURL error code if one occurred.

lastfailedsyncerrorcode

A string representation of a three or four digit number representing the specific error that caused sync to fail, or zero if sync has never failed (Pulsar Error Codes).

lastfailedsynchttpresponsecode

A string representation of a three digit code plus brief descriptive text corresponding to the code. This is only reported when CURL reports an error or Salesforce’s response contains no body.

lastfailedsyncsferrorcode

A string representation of the error code from Salesforce if applicable.

lastfailedsyncsferrormessage

The error message associated with the Salesforce error code.

syncdata

The syncdata request initiates a Pulsar sync action. This method is functionally equivalent to pressing the Sync Now button on the Pulsar sync status modal. Syncing data can often take a long time and as such, the API method returns immediately after the sync has started. This allows the users application to do other things while the sync is taking place. Users are highly encouraged to register for at least the syncDataFinished handler prior to starting your sync call.

Request Parameters

By default, a standard sync runs unless additional parameters are specified. To initiate a non-standard sync, you can provide parameters within the data node. Note, only the standard sync will affect the sync windows used by standard sync. For example, running a mini sync will not affect the sync windows used by standard sync.

To Perform a Mini Sync

This is similar to a standard catch-up sync but for a subset of the full object list. If there are any offline changes pending, then the object types of those changes are automatically added to the mini sync object list. The sync window used by mini sync is initially informed by the most recent standard sync, but consecutive mini syncs rely on the mini sync window which is set per object.

miniSyncEnabled (boolean, required): Set to true to enable a mini sync.

miniSyncObjectList (array, required): A list of the object types to sync.

To Perform a Single Object Sync

Used to sync a specific object and optionally its related records. This is useful when a single object has been modified and we want to make sure that any server side changes to related objects that may occur a result of the change are synced to the device.

  • singleObjectSyncEnabled (boolean, required): Set to true to enable a single object sync. This syncs a root object and, by default, retrieves:

    • All parent objects (one level above).

    • All child objects (one level below).

  • rootObjectId (string, required): The ID of the specific record to sync.

  • parentIdFieldList (array, optional): A list of reference field names on the root object to sync. If omitted, all referenced objects (of already synced types) will be included. To disable this, specify an invalid field (e.g., ['NONE']).

  • childRelationshipList (array, optional): A list of child relationships on the root object to sync. If omitted, all child relationships (for synced object types) will be included. To disable this, specify an invalid relationship (e.g., ['NONE']).

To Perform a Push Changes Sync

Used to push all local changes directly to Salesforce.

pushChangesSyncEnabled (boolean, required): Set to true to enable a push changes sync. This bypasses standard sync steps and only pushes local changes.

API Mode Selection

You can select a specific Salesforce API to use for the sync with the following optional parameters.

  • useComposite (boolean, optional): Set to true to explicitly use the Salesforce Composite API.

  • useCompositeGraph (boolean, optional): Set to true to explicitly use the Salesforce Composite Graph API.

Important Notes:

  • singleObjectSyncEnabled cannot be used with pushChangesSyncEnabled.

  • useComposite cannot be used with useCompositeGraph.

Example Requests

The following examples do not include the registration steps for syncDataFinished which are needed to know when the sync has finished.

A basic sync request:

var request = { 'type' : 'syncdata', 'data' : { } // empty object- this is required in the current API }; bridge.send(request, function (results) { console.log('Javascript got its response: ' + results); if (results.type === 'syncDataResponse') { // successfully requested sync } else if (results.type == 'error') { errStr = results.data; alert('A problem occurred:\n' + errStr); } });

An example of a mini sync request that syncs just the Account and Contact objects:

var request = { 'type' : 'syncdata', 'data' : { 'miniSyncEnabled' : true, 'miniSyncObjectList' : ['Account', 'Contact'] } };

An example of a Composite Graph API enabled push changes sync:

var request = { 'type' : 'syncdata', 'data' : { 'pushChangesSyncEnabled' : true, 'useCompositeGraph' : true } };

An example of a single object sync that syncs the root object and all parent and child objects:

var request = { 'type' : 'syncdata', 'data' : { 'singleObjectSyncEnabled' : true, 'rootObjectId' : '001234567890123AAA' } };

An example of a single object sync that syncs the root object (Contact) and a subset of parent and child objects:

var request = { 'type' : 'syncdata', 'data' : { 'singleObjectSyncEnabled' : true, 'rootObjectId' : '003d0000032lc1ZAAQ', 'parentIdFieldList' : ['AccountId','ReportsToId'], 'childRelationshipList' : ['Cases','Events','Notes','Tasks'] } };

An example of a single object sync that syncs the root object only:

var request = { 'type' : 'syncdata', 'data' : { 'singleObjectSyncEnabled' : true, 'rootObjectId' : '001234567890123AAA', 'parentIdFieldList' : ['NONE'], 'childRelationshipList' : ['NONE'] } };

Interrupting an Ongoing Sync in Pulsar for Salesforce

Overview

The interruptsync request allows you to stop an ongoing sync process if one is currently running. This is useful when you need to cancel a sync operation due to user action or changing conditions.

  • If no sync is currently running, the request will have no effect.

  • The API returns an immediate response indicating whether the interrupt request was successfully registered.

Request Structure

To send an interrupt sync request, construct the following JavaScript object and send it via the Pulsar bridge:

var request = { 'type': 'interruptsync', 'data': {} // Empty object required by the API }; bridge.send(request, function(responseData) { if (responseData.type === 'interruptSyncResponse') { console.log('Interrupt Sync Response:', responseData.data); var syncSuccess = responseData.data.success; if (syncSuccess) { console.log('Sync was successfully interrupted.'); } else { console.log('No active sync process to interrupt.'); } } else if (responseData.type === 'error') { var errStr = responseData.data; console.error('Error interrupting sync:', errStr); } });

Handling the Response

The response object returned from interruptsync contains the following properties:

  • type (string) – The response type ('interruptSyncResponse' if successful, 'error' otherwise).

  • data.success (boolean)

    • true → Sync was successfully interrupted.

    • false → No active sync process was found to interrupt.

Auto-Sync Status

getAutosyncStatus

The getAutosyncStatus operation will return Pulsar's current auto-sync status. This is the functionality that controls whether a sync starts automatically on login and when you return to the app. This will return the string 'FALSE' if this functionality is off, and 'TRUE' if this functionality is turned on.

var request = { 'type' : 'getAutosyncStatus', 'data' : { } // empty object- this is required in the current API }; bridge.send(request, function (results) { console.log('Javascript got its response: ' + results); if (results.type === 'getAutosyncStatusResponse') { var isAutoSyncOn = results.data; //string value 'TRUE' or 'FALSE' // do something with the information } else if (results.type == 'error') { errStr = results.data; alert('A problem occurred:\n' + errStr); } });

setAutosyncStatus

The setAutosyncStatus operation will attempt to set Pulsar's current auto-sync status. Similar to getAutosyncStatus, this will return the string 'FALSE' if this functionality is off after attempting to set it, and 'TRUE' if this functionality is turned on after the attempt.

var request = { 'type' : 'setAutosyncStatus', 'data' : 'TRUE' // required- this is the value to set 'FALSE' for off, 'TRUE' for on }; bridge.send(request, function (results) { console.log('Javascript got its response: ' + results); if (results.type === 'setAutosyncStatusResponse') { var isAutoSyncOn = results.data; //string value 'TRUE' or 'FALSE' // do something with the information } else if (results.type == 'error') { errStr = results.data; alert('A problem occurred:\n' + errStr); } });

 

Related content