---
title: "Connect Salesforce to Rig — Rig guide"
description: "Connect Salesforce to Rig with the OAuth 2.0 Client Credentials flow. Create the app, set the Run As user, and sync every business object with all of its fields — plus your org's Apex, validation rules, flows and dependency graph."
canonical: "https://rig.so/guides/connect-salesforce"
format: markdown
---

Search guides, references, playbooks…⌘K

Browse guides

# Connect Salesforce to Rig

Sync your Salesforce org into Rig — every business object the integration user can read, with all of its fields, and optionally the customisation that governs them — so your AI tools can answer pipeline and revenue questions against live CRM data. Salesforce connects server-to-server using the OAuth 2.0 Client Credentials flow, so it keeps working without per-user logins or staff turnover breaking it.

## Before you start

- You need Salesforce **admin** access to create the app.
- Ideally use a dedicated **integration user**, preferably one with the **API Only User** permission, with read access to the objects you want Rig to see. The integration runs as that user, so its permissions are exactly what Rig can read.
- By the end you'll have three values to paste into Rig: an **Instance URL**, a **Consumer Key** and a **Consumer Secret**.

## Step 1: Create an app with the Client Credentials flow

Connected Apps vs External Client Apps
Salesforce restricted creating new **Connected Apps** in Spring '26. New orgs create an **External Client App** instead. The end result is identical: a Consumer Key and Secret you paste into Rig. Use whichever path your org offers.

### External Client App (recommended)

1. In Salesforce, go to `Setup`, type `External` in Quick Find, and open `External Client App Manager`. Click `New External Client App`.
2. Enter a name (e.g. "Rig"), an API name, and a contact email.
3. Under `API (Enable OAuth Settings)`, select `Enable OAuth`.
4. **Callback URL**: the Client Credentials flow never uses a redirect, but the field is required. Enter any valid HTTPS URL, e.g. `https://login.salesforce.com/services/oauth2/callback`.
5. For **OAuth Scopes**, add `Manage user data via APIs (api)`.
6. Under **Flow Enablement**, enable the `Client Credentials Flow` and accept the security warning.
7. Click `Create`.
8. Back in `External Client App Manager`, open the app's actions menu and choose `Edit Policies`. Under **Client Credentials Flow**, set **Run As** to your integration user, then Save. The field wants the user's Salesforce **username**, not their email — they often differ. If you get *"Enter a valid execution user"*, copy the exact value from the Username column in `Setup` → `Users`.
9. From the app's actions menu choose `Edit Settings`, open `OAuth Settings`, and copy the **Consumer Key** and **Consumer Secret**.

### Connected App (legacy / existing apps)

1. `Setup` → `App Manager` → `New Connected App`.
2. Enable OAuth settings, add the `Manage user data via APIs (api)` scope, tick `Enable Client Credentials Flow`, and save.
3. On the app, click `Manage` → `Edit Policies`, and under **Client Credentials Flow** set the `Run As` user.
4. Back on the app, open `Manage Consumer Details` and copy the Consumer Key and Consumer Secret.

## Step 2: Grant the integration user object access

The integration runs **as the Run As user**, so Rig can only read the objects and fields that user is allowed to see. This step is easy to miss and is the most common reason a connection authenticates but returns nothing.

⚠️ Integration users start with no object access
A user on a **Salesforce Integration** license (and most minimal profiles) has **no access to standard objects by default**. If the Run As user can't read an object, Rig shows *"Object not accessible to the integration user"* and Salesforce returns `sObject type 'Account' is not supported` (`INVALID_TYPE`). The fix is always to grant that object via a permission set below.

1. In `Setup`, type `Permission Sets` in Quick Find and open it. Click `New` to create one (e.g. "Rig Read Access"). The **License** dropdown matters and can't be changed after creation:
   
     - Run As user on a regular **Salesforce** license → leave it at `--None--`.
     - Run As user on the free **Salesforce Integration** license (the usual choice for a dedicated integration user) → pick `Salesforce API Integration`. Careful: the dropdown also contains *Salesforce Integration* — a different entry, one word apart. Only the one with **API** in the middle unlocks CRM objects.
2. If the integration user's profile doesn't already include API access (minimal profiles like `Minimum Access - Salesforce` don't), open `System Permissions` in the permission set, click `Edit`, and tick **API Enabled**. Without it, every call fails with `API_CURRENTLY_DISABLED` ("API is disabled for this User") before object permissions are even checked.
   
   ![The System Permissions list of a Salesforce permission set with the API Enabled permission ticked.](https://rig.so/salesforce-api-enabled-permission.png)System Permissions → API Enabled: required for the Run As user to call the REST API at all.
3. Go to `Object Settings` (or type the object name into the `Find Settings...` box at the top of the permission set), and for **each object you want Rig to see** — Rig syncs every business object the Run As user can read, with all of its fields, so this grant is what decides the scope — click `Edit` and enable `Read` (and `View All` if you want every record, not just the user's own). Access is granted **per object**: any object you skip keeps failing with `INVALID_TYPE` even while the others work. Two traps here: if **Accounts, Contacts etc. don't appear in the list at all**, the permission set was created with the wrong license — Salesforce hides objects the license can't grant; recreate it with the right one (previous step). And grant the plain standard objects, not similarly-named custom ones — an API name ending in `__c` (e.g. "Account Products" / `Account_Product__c`) is a custom object. Rig syncs custom objects too, but granting one does not grant the standard Account.
   
   ![Object Settings for Contacts in a Salesforce permission set, showing Read, View All Records and View All Fields enabled plus the Field Permissions table.](https://rig.so/salesforce-permission-set-object-settings.png)Object Settings for one object: Read + View All Records, with field-level Read Access below.
4. While you're in each object's settings, make sure the **fields** you care about have `Read Access` — field-level security can hide individual columns even when the object is granted. A missing field fails the whole query with `INVALID_FIELD` and shows in Rig as *"Field not accessible to the integration user"* (on the User object, `ProfileId` is a common culprit).
5. **Optional — to sync your org's Apex and custom logic.** Object permissions do not cover any of it: the customisation streams read through Salesforce's **Tooling API**, which is gated by system permissions instead. In the same permission set open `System Permissions` → `Edit` and tick:
   
     - `View Setup and Configuration` — required for *every* customisation stream: the Apex, trigger and Visualforce catalogue, validation rules, custom fields, entity definitions, the flow catalogue and the dependency graph. Without it the Tooling API refuses the query outright.
     - `View All Data` *or* `Author Apex` — required **in addition**, and only to read the **source bodies** of Apex classes, triggers and Visualforce pages. With just `View Setup and Configuration` you get the catalogue — names, objects, trigger events, active flags — but the code itself comes back empty.
   
   Granting neither is a perfectly good answer: the CRM sync runs exactly as normal and Rig logs the customisation streams it couldn't read, rather than failing the sync. See the callout below before you decide.
6. Go to `Manage Assignments` → `Add Assignment`, tick your **Run As integration user**, keep `No expiration date`, and click `Assign`. The permission set does nothing until this step.
   
   ![The Manage Assignments screen of a Salesforce permission set with the integration user selected and No expiration date chosen.](https://rig.so/salesforce-permission-set-assignment.png)Assign the permission set to the Run As user — with no expiration date.

Permission changes take effect on the next token, so you can re-run `Test` in Rig immediately — no need to touch the app or rotate credentials.

Salesforce Integration license users: the two-part unlock
On the free **Salesforce Integration** license, CRM object access needs two things, and both must be in place before any grant takes effect: **(1)** the **Salesforce API Integration** permission set license assigned to the user (user's detail page → `Permission Set License Assignments` → `Edit Assignments`), and **(2)** the permission set itself created with `License = Salesforce API Integration`. A permission set on `--None--` or the *Salesforce Integration* user license either refuses assignment ("user license doesn't match") or silently hides the CRM objects from Object Settings. Once both are right, grants apply on the next token — no app changes needed.

⚠️ Syncing your org's customisation is a step past read-only CRM access
Rig can also sync the customisation that governs your CRM — Apex, validation rules, flows, the dependency graph (see [Your org's customisation](#customisation) below). Object permissions don't cover any of it. The Run As user needs the `View Setup and Configuration` system permission to read those streams at all, and `View All Data` or `Author Apex` on top of that to read Apex source bodies. Reading Apex source is **not read-only CRM access**, so decide deliberately whether you want it — if you don't, grant neither and Rig syncs your CRM objects as normal, logging the customisation streams it couldn't read. These are the **documented requirements, not a verified minimum**: we have not tested a narrower permission set against a restricted user.

## Step 3: Find your instance URL

In `Setup`, open `My Domain` and copy your My Domain URL, for example `https://acme.my.salesforce.com`. Sandboxes look like `https://acme--sandbox.sandbox.my.salesforce.com`.

## Step 4: Connect it in Rig

New to Rig? Watch how to find Connections

1. In Rig, open `Connections` in the left sidebar and go to `Sources & actions`.
2. Search for **Salesforce** (it's under CRM, marked `OAuth`) and click its card.
3. **Instance URL**: paste your My Domain URL.
4. **Connected App Consumer Key**: paste the Consumer Key.
5. **Connected App Consumer Secret**: paste the Consumer Secret.
6. Click `Continue`, then `Test` to pull a small sample, then `Sync` to run the full pipeline.

## What Rig pulls in

Salesforce lands in its own `salesforce` schema. There is no fixed object list and no field mapping to maintain: Rig asks your org what it contains at sync time, keeps the **business objects** — every custom object, plus the standard objects Salesforce treats as data rather than plumbing — and syncs **all of their fields**, standard and custom. Add a field or a custom object later and it appears on the next sync.

- **Accounts, contacts, leads, opportunities, cases and users** keep their familiar table names (`salesforce.accounts` and friends) — they just carry every column now, not a hand-picked dozen.
- **Opportunity history** (`salesforce.opportunity_history`): the stage, amount and forecast-category snapshot each time a deal moves — what time-in-stage, pipeline movement and stage-to-stage conversion questions need. This is the one `...History` object Rig keeps, and it is a deliberate exception to the rule below.
- **Custom objects**: every `__c` object your org defines, with its full field set.
- **Currency types**: ISO code and conversion rate, so multi-currency amounts add up the way Salesforce adds them up.

Skipped: objects the Run As user can't read, the system shadow tables (`...Share`, `...Feed`, change events, custom metadata and external objects), the **per-field audit tables** — `AccountHistory`, `OpportunityFieldHistory` and every other `...History` / `...FieldHistory` table that records one row per field edited, with `OpportunityHistory` above as the sole exception — and anything that looks like a credential store — objects and fields whose API name ends in *token*, *secret*, *password*, *api key* or *credential* never reach the warehouse. The first sync backfills your history in resumable batches; after that, syncs pull only records whose `SystemModstamp` moved.

## Your org's customisation, too

The objects above say what is *in* your CRM. None of them say how your org *behaves* — which Apex fires on save, which validation rule rejects a write, which formula really produces the number on a report, what breaks if a field is retired. Rig reads that from Salesforce's Tooling API on the same connection, into the same `salesforce` schema:

- `apex_classes`, `apex_triggers`, `apex_pages` — with their source bodies, plus which object each trigger sits on and which events it handles.
- `validation_rules` — the rule, the object it guards, its error message, whether it's active.
- `custom_fields` and `entity_definitions` — the field and object catalogue behind your schema.
- `flow_definitions` — a catalogue of your flows: name, type, trigger, whether it's active. The logic inside a flow is not synced.
- `component_dependencies` — Salesforce's own dependency graph, every "X references Y" edge, so you can trace what a change would touch.

The Apex, Visualforce and custom-field streams are filtered to `NamespacePrefix = null` — your own customisation, not a managed package's internals. The catalogues (`entity_definitions`, `component_dependencies`) aren't filtered, because your own rules resolve through them.

These streams need permissions beyond object access — `View Setup and Configuration`, plus `View All Data` or `Author Apex` for Apex source bodies. See the callout in [Step 2](#grant-access) before you grant them.

## Good to know

- Rig reads only what the Run As user can see. Give that user least-privilege, read-only access to the objects you want to sync.
- Anyone with the Consumer Key and Secret can mint access tokens. Rotate the secret periodically, and immediately if it leaks.
- Make sure you copy the **production** My Domain URL (or the matching sandbox URL) for the org whose data you want.
- You can disconnect Salesforce at any time from `Connections` → `Sources & actions`.

## What people use this for

- Analyse pipeline velocity and stage conversion
- Forecast more accurately from real opportunity data
- Score account health and expansion potential
- Audit data quality and rep activity

[More ideas for using Salesforce](https://rig.so/integrations/salesforce)

Was this guide helpful?

Yes No

---

- [This page as HTML](https://rig.so/guides/connect-salesforce)
- [Site map for language models](https://rig.so/llms.txt)
- [API and agent documentation](https://rig.so/developers)
