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
queryresource with your query inq). 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
sobjectsresource — re-running it creates the records again; - with
externalIdFieldconfigured, the batch is a keyed upsert (PATCH oncomposite/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/Accountto create; PATCH andsobjects/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 inexternalIdField). 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
| Field | What it means | Notes |
|---|---|---|
| Login URL | The Salesforce login endpoint the token is requested from | Required. Default https://login.salesforce.com. Use https://test.salesforce.com for a sandbox, or your My Domain address. |
| OAuth grant type | How the connector signs in | Required. 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 version | The REST API version in every call's path | Enter 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_id | The Connected App's consumer key | Required. A ${secret:...} reference. |
| Consumer secret / client_secret | The Connected App's consumer secret | Required. A ${secret:...} reference. |
| Refresh token | Shown only for refresh_token | Not used, because that grant is rejected. |
| Scope | OAuth scopes | Pre-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
| Setting | Where | Salesforce behaviour |
|---|---|---|
| External object | Add entity to profile | The sObject API name, standard or custom. |
| External-id field (keyed upsert) | Add entity to profile | The 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 filter | Add entity to profile | A SOQL WHERE fragment without the keyword, for example RecordType.Name = 'Field Sales'. Applied to the delta read and to reconciliation. |
| Delete propagation | Add entity to profile | None — 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 settings | Default 120. How far each read rewinds the SystemModstamp watermark. |
| Nightly reconciliation | Profile settings | A six-field UTC cron. Blank turns it off. Takes effect on the next Compile. |
| Reconcile window (hours) | Profile settings | Default 26, range 1–336. Raise it after an outage so missed days are checked. |
| Auto-repair | Profile settings | Off 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.
- The administrator stores
sf-client-idandsf-client-secretin the "CRM Sync" integration app, creates a connection "Salesforce production" with grantclient_credentials, login URLhttps://login.salesforce.comand API versionv60.0, and the test answers Connection OK. - A trial read step with
q=SELECT Id, Name FROM Account LIMIT 5returns five accounts inbody.records. - In Salesforce, an administrator adds the field
Xmatix_Id__cto Account, marked External ID and Unique. - The administrator creates a sync profile on the connection, adds Account ↔ Account as Bidirectional with External-id field
Xmatix_Id__c, External filterType = 'Customer'and Delete propagation None, compiles, and sets Nightly reconciliation to0 30 20 * * *(02:00 IST). - 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):
- Create the connection and run Test Connection. Expected: Connection OK with the sandbox instance address.
- Change API version to
60.0(no v), save, and run a read step forSELECT Id FROM Account LIMIT 1. Expected: the test still passes, but the read comes back with a non-OK status. Putv60.0back and the read returns one record. - 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) andpassword(Raw JSON).refresh_tokenis rejected. - Test Connection checks sign-in only.
- SOQL read: path
query, keyq, items pathbody.records, first page only. - Batch writes: up to 200 records per call; set
externalIdFieldto 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.
