# Salesforce

- URL: https://betteranalyst.com/docs/connectors/salesforce
- Updated: 2026-10-28
- Author: Better Analyst

Connect a Salesforce org to Better Analyst with OAuth, choose the objects it may query, pin saved reports, and analyze CRM data in chat, dashboards, alerts, and Data Flows.

Connect Salesforce to Better Analyst to analyze accounts, opportunities, leads, cases, campaigns, activities, and custom objects. Better Analyst runs read-only SOQL queries against the objects you select, runs the saved reports you pin, and never asks you to paste a password or security token.

## Requirements

- A Salesforce user with **API Enabled** and read access to the objects you want to analyze
- An org edition with API access (Enterprise, Unlimited, Performance, Developer, or Professional with API access)
- Permission to approve the `api`, `refresh_token`/`offline_access`, and `id` OAuth scopes

### Choose which Salesforce app connects

The connector page offers two ways to connect:

- **Connect with Better Analyst's app**: one click, once your Salesforce org can use Better Analyst's app (see below).
- **Use your organization's own Salesforce app**: your Salesforce admin creates an app in your own org and gives Better Analyst its consumer key and secret. Use this if your org can't use Better Analyst's app yet, or if your security policy requires apps your org owns. See [Use your organization's own Salesforce app](#use-your-organizations-own-salesforce-app).

### First connection: your Salesforce admin installs the app

Since September 2025, Salesforce blocks users from authorizing apps their org has not installed. Before the first person in your org connects, a Salesforce admin should open **Setup → Connected Apps OAuth Usage**, find Better Analyst, and select **Install**. After that, anyone in the org with the requirements above can connect. Alternatively, the admin can grant the connecting user the **Approve Uninstalled Connected Apps** permission.

### Use a read-only integration user

Salesforce has no read-only OAuth scope. The `api` scope grants the connecting user's full API rights, so what Better Analyst *could* do is limited by that user's profile and permission sets, not by the scope. Better Analyst itself only sends SOQL `SELECT` queries and Bulk API 2.0 query jobs, and rejects DML, `FOR UPDATE`, and `ALL ROWS` before a request leaves the app.

For defense in depth, connect with a dedicated integration user whose permission set grants **Read** on the objects you need and nothing else. Field-level security on that user also decides which fields Better Analyst can see.

## Connect an org

1. Go to **Connectors**, then **Salesforce**.

2. Choose where you sign in:

   - **Production** for `login.salesforce.com`
   - **Sandbox** for `test.salesforce.com`
   - **My Domain** for a host such as `acme.my.salesforce.com` or `acme--uat.sandbox.my.salesforce.com`

3. Select **Continue with Salesforce** and approve access.

4. Choose the objects Better Analyst may query. Common objects (Account, Contact, Lead, Opportunity, Case, Campaign, User, Task, Event, and Opportunity History) are preselected when your org has them. Search to add custom `__c` objects. You can select up to 40 objects.

5. Name the connector and save it.

Each Salesforce org can be connected once per workspace. Connectors created in a team workspace are available to the team.

Use **Manage** to change which objects are selected, and **Refresh selected schema** after fields or picklist values change in Salesforce.

## Use your organization's own Salesforce app

A Salesforce admin sets this up once. After that, anyone in the workspace can connect with it.

1. In Salesforce, open **Setup → External Client App Manager** and choose **New External Client App**. Keep the distribution state **Local**.

2. Turn on **Enable OAuth** and set the **Callback URL** to exactly the URL shown on the Better Analyst connector page, for example `https://app.betteranalyst.com/api/salesforce/callback`.

3. Add these OAuth scopes:

   - **Manage user data via APIs (api)**
   - **Perform requests at any time (refresh\_token, offline\_access)**
   - **Access the identity URL service (id, profile, email, address, phone)**

4. Under security settings, turn on **Require secret for Web Server Flow**, **Require secret for Refresh Token Flow**, and **Require Proof Key for Code Exchange (PKCE)**. Leave the other flows off.

5. Save the app. In its **Policies**, choose who may use it: all users may self-authorize, or admin-approved users assigned through profiles or permission sets. We recommend refresh token rotation.

6. Under **Settings → OAuth Settings**, choose **Consumer Key and Secret** and copy both. A new app can take a few minutes to start working.

7. In Better Analyst, open **Connectors → Salesforce**, choose **Use your organization's own Salesforce app**, and enter your **My Domain URL** (from **Setup → My Domain**, for example `https://acme.my.salesforce.com`), the **Consumer Key**, and the **Consumer Secret**. Select **Connect** and approve access.

Better Analyst stores the consumer secret encrypted and never shows it again. In a team workspace, the app belongs to the team: its creator or a team owner or admin can update the key or secret, or remove it. An app can't be removed while a Salesforce data source uses it. Reconnecting, and teammates connecting their own Salesforce login to a shared data source, use the same app automatically.

## Saved reports

Pin saved Salesforce reports when you want answers that match a report your team already trusts, with its filters, groupings, and formula columns.

1. On the Salesforce connector page, choose **Manage** on a connected org.
2. Open the **Reports** tab, search by report name, and select up to 50 reports.
3. Choose **Save pinned reports**.

Chat can run only pinned reports. Ask for one by name, for example "Use the Pipeline by Stage report to show this quarter's closed-won deals by owner."

- **Formats:** tabular, summary, and matrix reports are supported. Joined reports cannot be pinned. Query their objects directly instead.
- **Rows:** Salesforce returns the first 2,000 detail rows of each report run. When a report has more, the result is marked partial and Better Analyst offers a full SOQL query instead. Summary and matrix reports arrive as one table, with a column for each grouping.
- **Filters and dates:** chat can add up to 20 filters to a run and replace the report's standard date range. The saved report in Salesforce never changes.
- **Access:** reports run as the connected Salesforce user, so that user's report-folder sharing and field-level security decide what a run returns.
- **Limits:** Salesforce allows 500 synchronous report runs per org per hour and 20 at a time. Dashboard refreshes of pinned reports count toward this limit.
- **Changes in Salesforce:** if someone edits a pinned report's columns, save the pinned reports again so chat sees the new columns. A Data Flow built on that report stops with a schema-change error; rebuild it from a new chat result.

## Pipeline history

Opportunity History records each change to an opportunity's stage, amount, close date, and probability. Use it to ask how the pipeline changed over time, how long deals spend in each stage, or which close dates slipped.

Other history objects, such as Account History or Case History, record only the fields your admin set up for history tracking (up to 20 per object). Salesforce keeps that history for about 18 months in its interface and 24 months through the API, so Better Analyst can't see older changes.

## Currency

If your org uses multiple currencies, Better Analyst records the corporate currency when it reads your schema. It then converts amounts with `convertCurrency()`, and filters amounts with currency-coded values such as `USD5000`. Totals from aggregate queries are in the corporate currency. Where advanced currency management is on, opportunities, opportunity products, and opportunity history use dated exchange rates. In report results, each amount column gets a matching currency column.

## Data behavior

- Better Analyst writes SOQL `SELECT` queries against the selected objects. Queries that reference any other object are refused.
- Parent relationship fields such as `Account.Name` and semi-joins over selected objects are supported. Parent-to-child subqueries and `TYPEOF` are not.
- Preview requests return at most 1,000 rows. Larger and complete results are capped at 250,000 rows.
- Large record exports run as Bulk API 2.0 query jobs. Aggregate queries (`COUNT`, `SUM`, `GROUP BY`) use the REST query API.
- Pinned reports run through the Salesforce Reports API and return at most 2,000 detail rows per run.
- Dashboard refreshes, scheduled refreshes, alerts, and Data Flows replay the saved structured Salesforce request (a SOQL query or a pinned report run) with the dashboard's date range. They do not infer a new query from chat text. A Data Flow refuses a report run that Salesforce cut off at 2,000 rows.

## API limits

Queries count against your org's daily API request allocation, and Bulk API jobs count against Bulk API limits. Better Analyst does not charge a separate Salesforce fee. Filter by date range or narrow the object list to keep usage low.

## Disconnect and retention

Deleting the last Better Analyst connector that references a Salesforce authorization removes Better Analyst's stored OAuth tokens. Generated dataset artifacts follow Better Analyst's normal retention settings.

To revoke Better Analyst in Salesforce as well, open **Setup → Connected Apps OAuth Usage**, find the Better Analyst app, and revoke it, or remove the app from the user's **Personal Information → Connected Apps** list.

If Salesforce reports an expired or revoked session, choose **Reconnect** on the connector page. Refresh tokens can expire if your admin set a refresh token policy other than "valid until revoked".

## Troubleshooting

- **Reconnect required:** authorize Salesforce again; Better Analyst never exposes stored tokens.
- **Object missing from the list:** confirm the connecting user can read the object and that it is queryable through the API.
- **Field missing:** check field-level security for the connecting user, then use **Refresh selected schema**.
- **"Your Salesforce org has not approved Better Analyst yet" (`OAUTH_APP_BLOCKED` or `OAUTH_APP_ACCESS_DENIED`):** ask a Salesforce admin to install the app as described in [First connection](#first-connection-your-salesforce-admin-installs-the-app), or to allow it for your profile.
- **IP restriction errors:** ask your Salesforce admin to relax IP restrictions for the Better Analyst app.
- **"Salesforce rejected the app's consumer key or secret":** copy both values again from your Salesforce app's **Consumer Key and Secret** page, and update them on the connector page.
- **"The callback URL in your Salesforce app must be exactly …" or `redirect_uri_mismatch`:** set your Salesforce app's callback URL to the exact URL shown on the connector page, with no trailing slash, then wait a few minutes.
- **API limit exceeded:** wait for the daily allocation to reset or narrow the request.
- **Report run limit reached:** Salesforce allows 500 synchronous report runs per hour. Wait, or ask chat to use a SOQL query instead.
- **Report missing from the Reports tab:** confirm the connecting user can see the report's folder. Joined reports show as not supported.

## Next steps

- [Data Connectors Overview](https://betteranalyst.com/docs/connectors/overview)
- [Ask questions in chat](https://betteranalyst.com/docs/ai-chat/asking-questions)
- [Create charts and visualizations](https://betteranalyst.com/docs/ai-chat/charts-visualizations)
