Salesforce
Connect your workspace to Salesforce CRM to link members with contacts and leads, and give assistants access to your CRM data.
Salesforce
Connect your Gravity Rail workspace to Salesforce CRM. The integration links workspace members to Salesforce Contacts and Leads, and gives your AI assistants the ability to query, create, and update Salesforce records during conversations.
This is useful when your team manages relationships in Salesforce and uses Gravity Rail for automated outreach, inbound scheduling, or AI-assisted conversations. Instead of switching between systems, your assistants can pull up a contact's record, log an interaction, or update a field -- all within the conversation flow.
What the integration does
Once connected, the Salesforce integration provides three capabilities:
-
Member reconciliation -- Match workspace members to Salesforce Contacts or Leads by email or phone number. When a member is linked, their Salesforce record ID is stored so assistants and workflows can reference it.
-
AI assistant tools -- Six tools become available to any AI assistant in the workspace. Assistants can run SOQL queries, search across records, look up a specific Contact or Account, create new records, and update existing ones. All from within a conversation.
-
Schema introspection -- Assistants can describe any Salesforce object type at runtime, so they understand what fields are available before querying or updating records. This means they can work with custom objects and custom fields without hardcoded configuration.
The integration uses OAuth 2.0 with encrypted token storage. One Salesforce org connects to one workspace.
Prerequisites
Before connecting, you need a Salesforce app (either a Connected App or an External Client App) configured for OAuth. If you don't have admin access to Salesforce, you'll need someone on your Salesforce team to set this up.
Salesforce edition
Any Salesforce edition with API access works -- Enterprise, Unlimited, Developer Edition, or a free Developer Edition org. If you're testing, a Developer Edition org is free and never expires.
Create a Salesforce app
You need a Client ID (Consumer Key) and Client Secret (Consumer Secret) from a Salesforce app. There are two ways to create one -- both produce the same credentials.
Option A: External Client App (recommended for newer orgs)
External Client Apps are Salesforce's newer approach, available on orgs running Spring '24 or later. They separate developer settings from admin policies.
- In Salesforce Setup, search for App Manager and click New External Client App
- Fill in the basics:
- Name:
Gravity Rail - Contact Email: your admin email
- Distribution State:
Local
- Name:
- Expand Enable OAuth and check Enable OAuth
- Set the Callback URL to the OAuth callback URL shown in the Setup Details section on the Salesforce Overview page in Gravity Rail (see Connection setup below)
- Add these OAuth Scopes:
api-- Manage user data via APIsrefresh_token, offline_access-- Perform requests at any timeopenid-- Access unique user identifiersid, profile, email, address, phone-- Access the identity URL service
- Select Require Secret for the Web Server Flow and Require Secret for Refresh Token Flow
- Click Save
- Note the Consumer Key (this is your Client ID) and Consumer Secret (this is your Client Secret)
- Under the app's Policies tab, set Permitted Users to
Admin approved users are pre-authorizedand assign the app to the relevant Profiles or Permission Sets
External Client Apps may take a few minutes to become active after creation.
Option B: Connected App (works on all editions)
- In Salesforce Setup, search for App Manager and click New Connected App
- Fill in the basics:
- Connected App Name:
Gravity Rail - Contact Email: your admin email
- Connected App Name:
- Under API (Enable OAuth Settings), check Enable OAuth Settings
- Set the Callback URL to the OAuth callback URL from Gravity Rail
- Add the same four OAuth scopes listed above
- Click Save, then Continue
- Note the Consumer Key and Consumer Secret
Connected Apps are available to all org users by default and may take 2-10 minutes to become active.
Instance URL
You'll need the correct login URL for your Salesforce org:
| Environment | Instance URL |
|---|---|
| Production | https://login.salesforce.com |
| Sandbox | https://test.salesforce.com |
| Developer Edition | Your org's login URL (e.g. https://myorg.my.salesforce.com) |
| Custom domain | Your custom domain login URL |
Using the wrong instance URL is the most common cause of invalid_client_id errors during connection.
Connection setup
Step 1: Open the Salesforce settings page
Navigate to Channels in the sidebar and click Salesforce. If this page isn't visible, the crm_salesforce feature flag may not be enabled on your workspace -- contact your Gravity Rail administrator.
Step 2: Copy the callback URL
Before entering credentials, go to the Setup tab. You'll see an OAuth Callback URL that looks like:
https://api.gravityrail.com/api/v2/w/{your-workspace-uuid}/app-connections/salesforce/oauth/callback
Copy this URL and register it as the Callback URL in your Salesforce app (see Prerequisites above). The URL must match exactly, including the protocol and path.
Step 3: Enter credentials
Click Edit in the page header (or Configure Salesforce if no connection exists yet). In the dialog, enter:
- Client ID -- the Consumer Key from your Salesforce app
- Client Secret -- the Consumer Secret from your Salesforce app
- Instance URL -- the login URL for your Salesforce org (defaults to
https://login.salesforce.com)
Click Create to save the credentials.
Step 4: Authorize with Salesforce
After saving credentials, the connection status shows Awaiting OAuth. Click Connect with Salesforce on the Overview tab. A new browser window opens to the Salesforce login page.
- Log in with a Salesforce user account that has API access
- Review the permissions and click Allow
- The window redirects back to Gravity Rail and closes
The connection status changes to Connected. Your Salesforce instance URL and API version appear on the Overview tab.
Connection states
| State | Badge | Meaning |
|---|---|---|
| Awaiting OAuth | Secondary | Credentials are saved but OAuth authorization hasn't been completed yet |
| Connected | Green | OAuth is complete and the API connection is active |
| Error | Red | Something went wrong (see Troubleshooting) |
| Not Connected | Secondary | No connection has been configured |
Member reconciliation
Member reconciliation links your workspace members to their corresponding Salesforce Contacts or Leads. When a member is linked, their Salesforce record ID is stored as a member field (salesforce:id), which assistants can use to look up the right record during conversations.
How matching works
The system searches Salesforce for records that match each unlinked member by:
- Email (checked first, higher confidence) -- exact match on the member's email address against Contact and Lead records
- Phone (checked second) -- exact match on phone number against Contact and Lead records
Members without an email or phone number won't produce matches. The search checks Contacts first, then Leads, and returns the first match found.
Finding and linking matches
- Go to the Members tab on the Salesforce connection page
- Click Find Matching Records
- In the dialog, click Find Matching Salesforce Records to start the search
- Review the results -- each match card shows the workspace member on the left and the Salesforce record on the right, with the match type (email or phone) and object type (Contact or Lead)
- Click Link on individual matches to link them, or Link All to link every match at once
Managing linked members
The Members tab shows all currently linked members with their Salesforce record IDs. To remove a link, click Unlink next to the member. Unlinking removes the salesforce:id member field but does not delete or modify any Salesforce data.
Member fields
When a member is linked, the Salesforce connection manages these member fields:
| Field Key | Description |
|---|---|
salesforce:id | The 18-character Salesforce record ID for the linked Contact or Lead |
salesforce:account_id | The Salesforce Account ID associated with the record |
salesforce:owner_id | The Salesforce Owner (user) ID assigned to the record |
These fields are available in templates and can be read by AI assistants during conversations.
AI assistant tools
When the Salesforce connection is active, six tools are automatically available to all AI assistants in the workspace. These tools let assistants interact with Salesforce data during conversations without any additional configuration.
Available tools
| Tool | What it does | Example use |
|---|---|---|
| salesforce_query | Run a SOQL query and return matching records | Look up all Contacts associated with an Account |
| salesforce_search | Full-text search across Contacts, Leads, Accounts, and Opportunities | Find a record when you only know a name or partial information |
| salesforce_get_record | Get a specific record by object type and ID | Pull up a Contact's details using their salesforce:id |
| salesforce_create_record | Create a new record in any object type | Log a new Lead after an inbound call |
| salesforce_update_record | Update fields on an existing record | Mark a Contact's status or update a phone number |
| salesforce_describe_object | Get the schema for an object type, including all fields and picklist values | Understand what fields exist on a custom object before querying it |
Query safety
SOQL queries from assistants are capped at 200 rows per query. If an assistant writes a query with a higher limit (or no limit), the system enforces the cap automatically. SOQL is read-only by design -- assistants cannot delete records through queries.
Search terms are escaped to prevent injection. All query results may contain customer data and are never logged.
Using tools effectively
Assistants work best with Salesforce when they have context about your data model. Consider including guidance in your assistant's identity prompt, such as:
- Which object types are relevant (e.g. "Our Salesforce org uses Contacts for patients and custom object
Care_Plan__cfor treatment plans") - Key fields to query or update (e.g. "Always check the
Status__cfield on Contact records") - What the
salesforce:idmember field means and when to use it
The salesforce_describe_object tool helps assistants discover fields at runtime, but providing context up front reduces unnecessary API calls and improves response quality.
Settings reference
Overview tab
| Field | Description |
|---|---|
| Status | Current connection state (Connected, Awaiting OAuth, Error, or Not Connected) |
| Instance URL | Your Salesforce org's instance URL (e.g. https://na1.salesforce.com) |
| API Version | Salesforce REST API version in use (default: v59.0) |
| Error | Error message if the connection is in an error state |
Setup Details (collapsible on Overview)
| Field | Description |
|---|---|
| OAuth Callback URL | The URL to register in your Salesforce app as the Callback URL |
| Required OAuth Scopes | The four scopes your Salesforce app must include |
| Instance URL guidance | Which URL to use for production, sandbox, or developer orgs |
Configuration dialog
| Field | Description |
|---|---|
| Client ID | Consumer Key from your Salesforce Connected App or External Client App |
| Client Secret | Consumer Secret from your Salesforce app |
| Instance URL | Login URL for your Salesforce org |
Disconnecting and reconnecting
To disconnect: click Disconnect on the Overview tab. This clears the OAuth tokens but preserves your client credentials and all member links. The connection returns to the Awaiting OAuth state and you can reconnect by clicking Connect with Salesforce again.
To reconfigure with different credentials: click Edit in the page header and enter new Client ID, Client Secret, and Instance URL values. Then complete the OAuth flow again.
Troubleshooting
Connection stuck on "Awaiting OAuth"
The OAuth flow didn't complete. This can happen if the browser window was closed before Salesforce redirected back, or if the OAuth state expired (it's valid for 10 minutes). Click Connect with Salesforce to start a new OAuth flow.
redirect_uri_mismatch error during OAuth
The callback URL registered in your Salesforce app doesn't match the one Gravity Rail is using. Go to the Setup tab, copy the OAuth Callback URL, and update your Salesforce app to use that exact URL. It must match character-for-character, including the protocol and any trailing characters.
invalid_client_id error
The Instance URL doesn't match your Salesforce org. Double-check which URL to use -- production orgs use
https://login.salesforce.com, sandboxes usehttps://test.salesforce.com, and Developer Edition orgs often use a custom domain likehttps://myorg.my.salesforce.com. Update the Instance URL in the configuration dialog and try again.
Connection shows "Error" state
The access token may have been revoked. This happens when a Salesforce admin ends the user's session, the Connected App is deleted or deactivated, or the authorizing user's account is deactivated. Click Disconnect, then Connect with Salesforce to reauthorize.
Member reconciliation returns no matches
- Verify that workspace members have email or phone data populated
- Verify that matching Contacts or Leads exist in Salesforce with the same email or phone values
- Confirm the Salesforce user who authorized the connection has permission to query Contact and Lead objects
- For External Client Apps: confirm the user's profile has been granted access to the app
AI assistant tools not working
The tools are only available when the connection is in the Connected state with a valid access token. Check the Salesforce connection status on the Overview tab. If it shows an error, disconnect and reconnect.
"Salesforce API request failed" errors
The Salesforce REST API returned an error. Common causes include: the Connected App was deactivated, API rate limits were exceeded (Enterprise edition allows 15,000 API requests per day), or the authorizing user lost permissions. Check the Salesforce app status in Salesforce Setup.
Data Sync
The Salesforce integration supports bidirectional data sync using the same multi-entity sync framework as HubSpot. You can push member data to Salesforce records (outbound) and pull Salesforce record changes back into Gravity Rail (inbound).
Entity Types
Sync is configured per entity type. Each entity type has its own sync direction toggles, field mapping rules, match strategy, and optional filters. Salesforce currently supports the member entity type for syncing workspace members with Salesforce Contacts/Leads.
Configuring Sync
- Go to the Sync tab on the Salesforce connection page
- For each entity type, enable outbound sync, inbound sync, or both
- Configure sync rules that define how fields map between Gravity Rail and Salesforce
- Optionally set outbound filter or inbound filter CEL expressions to limit which entities are synced (e.g.,
source.email != ''to only sync members with an email) - Click Save to apply
Sync rules use CEL expressions for flexible field transforms -- the same system used by HubSpot sync. See the HubSpot Sync guide for detailed documentation on sync rules, expressions, transform presets, and filters, which work identically for Salesforce.
Salesforce-Specific Settings
| Setting | Description |
|---|---|
| Target Object | Which Salesforce object to sync to (default: Contact) |
| Upsert Field | External ID field for matching (default: Email) |
| Record Type | Optional RecordType ID for new records |
These settings are stored in entity_params on the entity's sync config or in the Salesforce-specific SalesforceSyncSettings.
Running a Sync
Click Run Sync on the Sync tab to start a batch sync. Progress streams live to your browser via SSE. The sync uses the same Temporal workflow as HubSpot, with batched member processing and automatic checkpoint tracking per entity type.
Automatic Sync
When outbound sync is enabled for an entity type, member updates automatically trigger a sync for the changed member via managed event rules.
Current limitations
- One Salesforce org per workspace -- Each workspace supports a single Salesforce connection. If you need to connect multiple orgs, use separate workspaces.
- Query row limits -- AI assistant SOQL queries are capped at 200 rows per query. For larger data sets, use more specific WHERE clauses or paginate with OFFSET.
- Inbound polling interval -- Inbound sync polls Salesforce via SOQL queries rather than real-time streaming. Change Data Capture support is planned.