xMatix
Sign in Request demo
xMatix
PRODUCTS
SalesField Sales & SFACRMRewardsClaimsInventoryProcurementWarehouse ManagementField ServiceServiceSupportTelephony & MessagingFinance & AccountingPayrollExpense ManagementCommercePortalsAnalytics & ReportingData StudioMobile AppSee all products →
PLATFORM
Platform overviewApp BuilderAutomationIntegrationsSecurity & GovernanceChange ManagementDevelopers
SENSE AI
Sense AI overviewSense AssistSense ControlSense VisionAI StudioTrust & governanceIn Claude & ChatGPTUse cases
SOLUTIONS
Auto DMSConsumer Goods DMSSales Force Automation (SFA) FMCG & DistributionManufacturing & Dealer NetworksAutomotive & DealershipsPharma & HealthcareConsumer DurablesAgri-InputsBuilding MaterialsService NetworksWarehousing & 3PLFinancial AccountingERP SoftwareIndia GST ComplianceUAE VAT & e-InvoicingSaudi ZATCA & VATAll solutions →
RESOURCES
Knowledge CenterDeveloper & CLIBlogGuidesWhat is xMatix?Company facts
COMPANY
AboutCareersPartnersEventsContactAuthorsLegal
Sign in Request demo
Home/Docs/Integrations/Salesforce connector
REFERENCE · Last reviewed

Salesforce connector

The Salesforce connector (connector type Salesforce REST) lets xMatix sign in to a Salesforce org and call its REST API, so you can read records with SOQL and write records from integration flows, or keep xMatix entities and Salesforce objects in step with a sync profile. You set it up once per integration app as a connection; every flow step and sync profile that talks to Salesforce then reuses that connection's sign-in.

Overview

One Salesforce connection carries four things:

  • Sign-in. The connector exchanges your Connected App's consumer key and secret for an access token at the login URL you enter, and learns your org's instance address from the answer. Tokens are kept for 50 minutes and reused by every call on that connection.
  • REST calls from flows. A Connector read step issues one GET (for SOQL, the query resource with your query in q). A Connector write step sends its input as JSON — one record per call, or a whole list as batch calls of up to 200 records.
  • Schema discovery. Sync profiles list your org's objects and fields live, including custom objects and fields.
  • Sync profile traffic. Delta reads, keyed upserts, nightly reconciliation and, for high-volume objects, Bulk API jobs all run through the same connection.

When to use it

  • Use a sync profile when you want standing, scheduled synchronisation of one or more objects, with a ledger that prevents duplicates and a conflict inbox for edits made on both sides.
  • Use flow steps for one-off or event-driven calls: pushing a record to Salesforce when it is saved in xMatix, running a specific SOQL query on a schedule, or calling any other Salesforce REST resource.

How xMatix handles it

Signing in. The connector supports two OAuth grants: client_credentials (a Connected App with a Run As user, no password) and password (a named user's username and password). Each call goes to {instance}/services/data/{API version}/{path}. If Salesforce answers a call with 401 Unauthorized, the connector fetches a fresh token and retries that call once.

Rejected credentials. When the login endpoint rejects the credential itself — OAuth errors invalid_client_id, invalid_client, invalid_grant, unsupported_grant_type or invalid_scope — the run fails with a message saying the credential is wrong and must be fixed on the connection. For the next 10 minutes, runs on that connection fail straight away with the same message instead of asking Salesforce again; after that the connector tries again, so a corrected credential recovers by itself. Any other login failure fails the run with Salesforce's response text.

Reads. A read returns an envelope with status, ok, instanceUrl and the Salesforce response in body; for SOQL the records are in body.records. The connector makes a single call and does not follow Salesforce's next-page link, so a read step returns only the first page of a large result. Keep flow queries small with a WHERE clause and LIMIT, or use a sync profile for whole objects.

Writes. A single-record write sends the step input as the JSON body to the path you name (POST unless the step sets another method, such as PATCH for an update). A list input becomes batch calls of at most 200 records each:

  • with no external-id field configured, the batch is an insert to the composite sobjects resource — re-running it creates the records again;
  • with externalIdField configured, the batch is a keyed upsert (PATCH on composite/sobjects/{object}/{field}), so re-running it updates the matched records. The connector refuses the whole batch if any record has no value in that field, because Salesforce would otherwise insert a duplicate.

Batch results are counted per record: a record Salesforce rejects is counted as failed without failing the others, unless the step sets allOrNone. A batch call that fails outright is skipped and the run continues, unless the step's On error is Fail the whole run.

Sync profiles. On each cycle the engine reads each Salesforce object with a SOQL query for records whose SystemModstamp is later than the stored watermark (rewound by the profile's overlap window), sorted oldest first, with your External filter added. SystemModstamp also moves when Salesforce itself updates a record, so system-calculated changes are picked up. Records are paired by the 18-character Salesforce Id. Your own outbound writes come back on the next read and are dropped as echoes because their content matches what was last synced.

Deletions. The cycle's delta query does not return deleted records, so a deletion in Salesforce is not seen by the regular cycle. The profile's Nightly reconciliation is what makes them visible: it runs a Bulk API queryAll job (Id, SystemModstamp, IsDeleted) over the reconcile window and records, per entity, records that are missing in xMatix or deleted in Salesforce but still live in xMatix. Reconciliation only reports, unless Auto-repair is on — and auto-repair acts only on entities that use the bulk read lane.

The 30-day limit. If an entity's stored watermark is more than 30 days old (for example, a profile paused for over a month), the next cycle reseeds that entity — it reads it in full again — rather than trusting an incremental read across the gap.

Prerequisites

  • A Salesforce Connected App with the OAuth grant you will use enabled, and its consumer key and consumer secret. For client_credentials, the app's Run As user.
  • A dedicated Salesforce integration user that can see exactly the objects and fields you will sync — see Why a dedicated integration user.
  • An integration app in xMatix (Setup → Platform → Integrations) and the Connection Manager role on it.
  • For outbound sync without duplicates: a custom field on each Salesforce object that will hold the xMatix record id, marked External ID and Unique in Salesforce.

Procedure

Step 1 — Store the credentials as secrets

Open your integration app under Setup → Platform → Integrations and add the consumer key and consumer secret on the app's Secrets tab (for the password grant, also the username and the password with the security token appended). See credentials and rotation. Never type a secret value into the connection itself.

Step 2 — Create the connection

In the same app, add a connection. In the New Connection dialog, enter a Name, leave Active on, choose Connector Type Salesforce REST, and fill in the form as described in Connection fields. Choose Create.

For the password grant, switch on Raw JSON and enter the configuration instead, because the form has no username or password fields:

{ "loginUrl": "https://login.salesforce.com", "grantType": "password", "apiVersion": "v60.0", "clientId": "${secret:sf-client-id}", "clientSecret": "${secret:sf-client-secret}", "username": "${secret:sf-user}", "password": "${secret:sf-password}" }

Step 3 — Test the connection

Reopen the connection (the test is available only after it is saved) and choose Test Connection. A pass shows Connection OK with "Authenticated to" and your org's instance address. The test performs only the token exchange — it does not call a data endpoint — so it proves the consumer key, secret and grant, but not object access or the API version. Follow it with a small read (Step 4) before you rely on the connection.

Step 4 — Read with SOQL in a flow

Add a Connector read step: Connector type salesforce.rest, Connection set to your connection, HTTP method GET, Path / resource query, Items path body.records, and under Query string parameters a key q whose value is your SOQL, for example SELECT Id, Name FROM Account WHERE LastModifiedDate = TODAY LIMIT 200. The step hands the records to the next step for mapping.

Step 5 — Write records from a flow

Add a Connector write step with Connector type salesforce.rest and your connection.

  • For one record: HTTP method POST and Path / resource sobjects/Account to create; PATCH and sobjects/Account/{Id} to update.
  • For a list of records: the step's configuration must name the object in sobjectType (and, for an upsert, the field in externalIdField). These keys are not on the step form. Choose On error to decide whether a failed batch is skipped or stops the run.

Step 6 — Use the connection in a sync profile

Create the profile under Setup → Platform → Sync profiles, choosing your integration app, the Salesforce connection and the external system Salesforce. Add entities with Add entity to profile: the External object list comes from your org (only objects Salesforce marks as queryable), and field discovery lists each object's fields. Follow scheduled sync for mapping, compiling and the first cycle, then set Nightly reconciliation on the profile's settings.

Connection fields

FieldWhat it meansNotes
Login URLThe Salesforce login endpoint the token is requested fromRequired. Default https://login.salesforce.com. Use https://test.salesforce.com for a sandbox, or your My Domain address.
OAuth grant typeHow the connector signs inRequired. Default client_credentials. The form also offers refresh_token, but the connector rejects it ("unsupported grantType") — do not choose it. The password grant is available through Raw JSON only.
API versionThe REST API version in every call's pathEnter it with the leading v, for example v60.0. The form pre-fills 60.0, which produces an invalid path; the connection still passes Test Connection but data calls come back with an error status. Left out of the configuration entirely, the connector uses v60.0.
Consumer key / client_idThe Connected App's consumer keyRequired. A ${secret:...} reference.
Consumer secret / client_secretThe Connected App's consumer secretRequired. A ${secret:...} reference.
Refresh tokenShown only for refresh_tokenNot used, because that grant is rejected.
ScopeOAuth scopesPre-filled api. The connector does not send it; the scopes are whatever the Connected App grants.

A flow step's own configuration is merged over the connection's, so a step can override, for example, the API version or add headers (Extra headers) such as Sforce-Auto-Assign.

Sync profile settings that matter for Salesforce

SettingWhereSalesforce behaviour
External objectAdd entity to profileThe sObject API name, standard or custom.
External-id field (keyed upsert)Add entity to profileThe Salesforce field holding the xMatix id; it must be External ID and Unique. Without it, outbound writes insert and the dialog warns that re-runs create duplicates. Leave blank to pick it during field discovery.
External filterAdd entity to profileA SOQL WHERE fragment without the keyword, for example RecordType.Name = 'Field Sales'. Applied to the delta read and to reconciliation.
Delete propagationAdd entity to profileNone — deletes are not propagated (safest) is the default. Soft and hard delete apply only where the engine learns of a deletion — see Deletions.
Overlap window (seconds)Profile settingsDefault 120. How far each read rewinds the SystemModstamp watermark.
Nightly reconciliationProfile settingsA six-field UTC cron. Blank turns it off. Takes effect on the next Compile.
Reconcile window (hours)Profile settingsDefault 26, range 1–336. Raise it after an outage so missed days are checked.
Auto-repairProfile settingsOff by default. Re-reads missing or stale records on the next catch-up — bulk-lane Salesforce entities only.

Example

A distributor keeps its Salesforce accounts and xMatix accounts in step.

  1. The administrator stores sf-client-id and sf-client-secret in the "CRM Sync" integration app, creates a connection "Salesforce production" with grant client_credentials, login URL https://login.salesforce.com and API version v60.0, and the test answers Connection OK.
  2. A trial read step with q = SELECT Id, Name FROM Account LIMIT 5 returns five accounts in body.records.
  3. In Salesforce, an administrator adds the field Xmatix_Id__c to Account, marked External ID and Unique.
  4. The administrator creates a sync profile on the connection, adds Account ↔ Account as Bidirectional with External-id field Xmatix_Id__c, External filter Type = 'Customer' and Delete propagation None, compiles, and sets Nightly reconciliation to 0 30 20 * * * (02:00 IST).
  5. A sales rep renames an account in Salesforce; on the next cycle the change arrives in xMatix. Next morning the Reconciliation tab shows one account deleted in Salesforce but still live in xMatix, and the team decides what to do with it.

Training

Practice exercise

In a sandbox integration app connected to a Salesforce sandbox (https://test.salesforce.com):

  1. Create the connection and run Test Connection. Expected: Connection OK with the sandbox instance address.
  2. Change API version to 60.0 (no v), save, and run a read step for SELECT Id FROM Account LIMIT 1. Expected: the test still passes, but the read comes back with a non-OK status. Put v60.0 back and the read returns one record.
  3. Replace the consumer secret reference with a wrong secret and test again. Expected: Test failed with Salesforce's OAuth error; restore the secret.

Quick reference

  • Connector type Salesforce REST; flow steps use salesforce.rest.
  • API version needs the v: v60.0.
  • Supported grants: client_credentials (form) and password (Raw JSON). refresh_token is rejected.
  • Test Connection checks sign-in only.
  • SOQL read: path query, key q, items path body.records, first page only.
  • Batch writes: up to 200 records per call; set externalIdField to make them upserts.
  • Sync deltas don't see deletions; nightly reconciliation does.
  • A watermark older than 30 days forces a reseed.

Permissions

  • Creating, editing and testing connections needs the Connection Manager role or higher on the integration app. Adding or rotating its secrets needs the Admin role.
  • In Salesforce, the integration user's object and field permissions decide what every read and write can reach. A field it cannot see is missing from discovery and from query results.
  • In xMatix, a sync profile reads and writes as its Sync identity, so it can never sync more than that user can see.

Configuration

Everything an administrator tailors for Salesforce lives in two places:

  • Setup → Platform → Integrations → (app) — secrets and the connection (Connection fields).
  • Setup → Platform → Sync profiles → (profile) — entities, filters, external-id fields, delete propagation, schedule, overlap window and reconciliation (sync profile settings). Watch cycles under Setup → Platform → Monitoring → Sync Monitor.

To move from a Salesforce sandbox to production, change the connection's Login URL and the secrets it references; the flows and profiles that use the connection do not change.

Why a dedicated integration user

Two reasons, both operational. Salesforce's own audit trail then shows exactly what the integration changed. And that user's permissions are the integration's reach — scope it to the objects and fields being synced, nothing more. On the xMatix side, the profile's sync identity plays the same role.

Common problems

"cannot authenticate: Salesforce rejected the configured credential"

The login endpoint rejected the consumer key, secret, grant or user (invalid_client_id, invalid_grant and similar). Check that the secrets hold the current Connected App values, that the Login URL points at the right org (production or sandbox), and that the grant is enabled on the Connected App. After a fix, runs can keep failing with the same message for up to 10 minutes before the connector asks Salesforce again.

"has unsupported grantType 'refresh_token'"

The connection was saved with the refresh_token choice. Change OAuth grant type to client_credentials, or use Raw JSON with password.

The test passes but every read or write fails

Test Connection checks only sign-in. Most often the API version lacks its leading v; otherwise the integration user lacks access to the object, or the path is wrong. Read the status and body in the step output.

"references secret(s) that could not be resolved"

A ${secret:...} name in the connection or step has no stored value in this integration app. Add or re-enter the secret on the Secrets tab.

"upsert on '…': N of M record(s) carry no '…' value"

A keyed upsert batch contains records without the external-id value. Map the xMatix id into that field before the write step.

A flow read returns fewer records than the query matches

The connector returns only the first page of a SOQL result. Narrow the query, or use a sync profile for whole objects.

A record deleted in Salesforce is still live in xMatix

Regular sync cycles do not see deletions. Turn on Nightly reconciliation for the profile and review its findings.

Common questions

Do custom objects and fields work?

Yes. SOQL reads name whatever objects and fields you write, writes accept any sObject path, and sync-profile discovery lists your org's actual schema — custom objects and custom fields included. Discovery lists only objects Salesforce marks as queryable, and it hides the separate latitude and longitude parts of a geolocation field because the compound field carries the value. Field types it cannot classify are not auto-mapped. The one condition throughout is that the integration user can see the object or field.

What happens if someone edits the same record in both systems?

In a bidirectional entity, the conflict engine compares both sides with what was last synced. A field changed on only one side merges through; a field changed on both sides follows the entity's conflict policy. With Field-level merge (recommended) or Manual, those need Store last-synced snapshot on, and contested fields appear as a conflict showing both values for a person to decide. See sync health and conflicts.

Does deleting a record in Salesforce delete it in xMatix?

Not through the regular cycle — its delta query does not return deleted records, and Delete propagation defaults to None. Nightly reconciliation lists Salesforce records that are deleted but still live in xMatix, so you can decide what to do; it changes nothing unless Auto-repair is on, which applies to bulk-lane entities only.

Sandbox or production first?

Sandbox. Point the connection's Login URL at https://test.salesforce.com, run the profile until mappings and the conflict policy behave, then change the Login URL and secrets to production and let the entities reseed. The connection is the only thing that changes.