> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.deepmask.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Salesforce Integration Setup

> Connect a Salesforce org to DeepMask by creating an External Client App and pasting the Consumer Key and Secret.

## Overview

This guide walks you through creating a Salesforce **External Client App** (ECA) in your org. Once complete, you will have a **Consumer Key** and **Consumer Secret** to paste into DeepMask's Salesforce connector — enabling your users to search records, review opportunities, and log activity from inside DeepMask.

| What You'll Get | Details |
| - | - |
| **External Client App** | A Salesforce app that DeepMask uses to request access on behalf of your users. |
| **Delegated OAuth** | Each user signs in with their own Salesforce credentials. They only see records their profile, permission sets, and sharing rules already allow. |
| **Consumer Key** | The app's public client ID. Paste this into DeepMask. |
| **Consumer Secret** | The app's confidential client secret. Paste this into DeepMask. Treat it like a password. |

<Info>
  DeepMask uses OAuth 2.0 delegated authentication (authorization code + PKCE). DeepMask never stores Salesforce passwords. Every action runs as the signed-in user — DeepMask cannot see more than that user already can in Salesforce.
</Info>

<Note>
  One DeepMask connection equals **one Salesforce org**. A user who works in several orgs connects each org separately.
</Note>

<Tip>
  Already connected? See the [Salesforce (Enterprise) connector actions](/connectors/Salesforce/overview) for everything the AI can do in Salesforce — finding records, summarizing pipeline, logging activity, and more.
</Tip>

***

## Prerequisites

### Required Access

* **Salesforce org with API access** — Any Lightning / Salesforce Cloud edition that can use the REST API (including Developer Edition, Enterprise, Unlimited, and sandboxes).
* **Permission to create External Client Apps** — A System Administrator, or a user who can open **Setup → External Client App Manager**.
* **API Enabled** on every user who will connect — this is a profile / permission-set flag in Salesforce.

### What You Do Not Need

* No Salesforce managed package (for a Local / bring-your-own app)
* No developer tools or command line
* No service account or shared integration user

<Warning>
  A **Local** External Client App only authorizes users of the org that created it. That is the correct setup for a single customer org or a sandbox. Connecting a second, unrelated org requires either a packaged ECA or a separate Local ECA in that org.
</Warning>

***

## Step 1 — Allow External Client Apps

<Steps>
  <Step title="Open Salesforce Setup">
    Sign in to the org you want to connect. Click the gear icon and choose **Setup**.
  </Step>

  <Step title="Enable ECA creation">
    In Quick Find, type **External Client App Settings**. Open it and allow users to create External Client Apps if that toggle is off.
  </Step>
</Steps>

***

## Step 2 — Create the External Client App

<Steps>
  <Step title="Open External Client App Manager">
    In Quick Find, type **External Client App Manager** and click **New External Client App**.
  </Step>

  <Step title="Fill in the basic details">
    | Field | Value |
    | - | - |
    | **External Client App Name** | `DeepMask Salesforce Connector` |
    | **API Name** | Accept the default (`DeepMask_Salesforce_Connector`) |
    | **Contact Email** | Your admin email |
    | **Distribution State** | **Local** |
  </Step>
</Steps>

<Info>
  **Local** means this app belongs to this org only. Do not switch Distribution State to Packaged unless you are publishing a managed package for many customer orgs.
</Info>

***

## Step 3 — Configure OAuth Settings

Still on the new app (or **Settings → OAuth Settings** after save), enable OAuth and apply **exactly** these values.

### Callback URL

Enter this value **exactly** (no trailing slash). DeepMask redirects here after Salesforce sign-in.

```
https://chat.deepmask.io/api/user/connectors/oauth/callback
```

The field accepts multiple URLs, one per line. You only need this one line for [chat.deepmask.io](https://chat.deepmask.io).

### OAuth scopes

Move **exactly these three** into **Selected OAuth Scopes**. Requesting a scope the app does not grant fails the entire login with `invalid_scope`.

| Selected scope (Salesforce label) | Why it is required |
| - | - |
| Manage user data via APIs (`api`) | REST API access as the signed-in user |
| Perform requests at any time (`refresh_token`, `offline_access`) | So DeepMask can mint a fresh access token without asking the user to sign in every time |
| Access unique user identifiers (`openid`) | Resolves the signed-in user ("me") and verifies the connection |

Leave every other scope in **Available** (do not add Full access, Web, Chatter, Visualforce, or custom permissions).

### Flow Enablement

Match this checkbox set:

| Setting | Value |
| - | - |
| **Enable Client Credentials Flow** | On |
| **Enable Authorization Code and Credentials Flow** | On |
| **Require user credentials in the POST body for Authorization Code and Credentials Flow** | On |
| **Enable Device Flow** | Off |
| **Enable JWT Bearer Flow** | Off |
| **Enable Token Exchange Flow** | Off |

<Info>
  DeepMask's connector uses **Authorization Code** (the user signs in) plus the **Client ID** and **Client Secret** you paste in DeepMask. User actions still run as that Salesforce user — not as a client-credentials service account.
</Info>

### Security

Match this checkbox set:

| Setting | Value |
| - | - |
| **Require secret for Web Server Flow** | On |
| **Require secret for Refresh Token Flow** | Off |
| **Require Proof Key for Code Exchange (PKCE) extension for Supported Authorization Flows** | On (Salesforce-required; contact Support to change) |
| **Enable Refresh Token Rotation** | On (Salesforce-required; contact Support to change) |
| **Issue JSON Web Token (JWT)-based access tokens for named users** | Off — keep access tokens opaque |
| **Limit Idle Refresh Token Time-to-Live (TTL) to 90 Days** | On (Salesforce-required; contact Support to change) |
| **Enforce Refresh Token IP Allowlist** | Off |

<Check>
  PKCE and refresh-token rotation stay on. JWT-based access tokens stay off. DeepMask stores the latest refresh token when Salesforce rotates it.
</Check>

Save the app. Salesforce often takes **2–10 minutes** to propagate a new ECA before the first login works.

***

## Step 4 — Set OAuth Policies

Open the app → **Policies** (or **OAuth Policies**) and set:

| Policy | Value |
| - | - |
| **Permitted Users** | All users may self-authorize |
| **IP Relaxation** | Relax IP restrictions |
| **Refresh Token Policy** | Follow org defaults. Rotation and the 90-day idle TTL are already set under **Security** (Step 3). |

<Info>
  "All users may self-authorize" lets each teammate connect their own Salesforce user. If you restrict this to pre-authorized users, an admin must approve every DeepMask connection.
</Info>

***

## Step 5 — Copy the Consumer Key and Secret

<Steps>
  <Step title="Open OAuth Settings">
    In External Client App Manager, open **DeepMask Salesforce Connector** → **Settings** → **OAuth Settings**.
  </Step>

  <Step title="Reveal the credentials">
    Click **Consumer Key and Secret**. Salesforce may ask you to verify your identity.
  </Step>

  <Step title="Copy both values">
    DeepMask's Salesforce connector asks for **Client ID** and **Secret**. Map the Salesforce labels like this:

    | Salesforce label | Paste into DeepMask as |
    | - | - |
    | **Consumer Key** | **Client ID** |
    | **Consumer Secret** | **Secret** |
  </Step>
</Steps>

<Warning>
  The Consumer Secret is a secret. Do not put it in chat, tickets, or a public repo. Only DeepMask's connector settings (or your own secret store) should hold it.
</Warning>

***

## Step 6 — Connect Salesforce in DeepMask

<Steps>
  <Step title="Open DeepMask">
    Go to [chat.deepmask.io](https://chat.deepmask.io) and sign in.
  </Step>

  <Step title="Open Connectors">
    In the chat toolbar, click **Add connectors** (or **Connectors** in the left navigation).
  </Step>

  <Step title="Start the Salesforce connector">
    Find the **Salesforce** tile and click **Connect**.
  </Step>

  <Step title="Paste Client ID and Secret">
    DeepMask prompts for two fields:

    * **Client ID** — the Consumer Key from Step 5
    * **Secret** — the Consumer Secret from Step 5

    If DeepMask also asks for an environment, choose **Production** (`login.salesforce.com`) or **Sandbox** (`test.salesforce.com`).
  </Step>

  <Step title="Save and sign in to Salesforce">
    Click **Save & Connect**. A Salesforce login window opens. Sign in as the Salesforce user who should own this connection and approve the requested scopes.
  </Step>

  <Step title="Confirm">
    You return to DeepMask. The Salesforce tile shows **Connected**. The AI can now use Salesforce in this workspace, limited to that user's records.
  </Step>
</Steps>

<Check>
  Ask something like "What's on my plate in Salesforce today?" or "Find open opportunities I own." If the connector is live, DeepMask will call Salesforce and return records with Lightning links.
</Check>

<Note>
  **Local / Developer Edition orgs:** if Salesforce returns *Cross-org OAuth flows are not supported*, start the login at the org's **My Domain** (`https://<mydomain>.my.salesforce.com`) instead of `login.salesforce.com`. Sandboxes use `test.salesforce.com` or the sandbox My Domain.
</Note>

***

## Troubleshooting

### "invalid\_scope" during sign-in

**Cause:** DeepMask requested `api`, `refresh_token`, and `openid`, but the ECA does not grant one of them (usually `openid`).

**Resolution:** Edit the ECA OAuth scopes, enable all three, save, wait a few minutes, and retry.

***

### "Cross-org OAuth flows are not supported"

**Cause:** A **Local** ECA cannot complete OAuth at `login.salesforce.com` / `test.salesforce.com` for some Developer Edition and scratch orgs.

**Resolution:** Authorize at the org **My Domain** (`https://<name>.my.salesforce.com/services/oauth2/authorize`). Production packaged apps use `login.salesforce.com`.

***

### Redirect URI mismatch

**Cause:** The Callback URL in the ECA does not exactly match the URL DeepMask sends.

**Resolution:** In OAuth Settings, the Callback URL must be exactly:

`https://chat.deepmask.io/api/user/connectors/oauth/callback`

No trailing slash. No `http://` variant.

***

### User connects but sees no records (or only some)

**Cause:** Salesforce sharing, field-level security, or a missing **API Enabled** permission — not a DeepMask bug.

**Resolution:**

* Confirm the user can see the same records in the Salesforce UI.
* Confirm their profile has **API Enabled**.
* Custom objects must be queryable and visible to that profile.

***

### "Need admin approval" or users cannot self-authorize

**Cause:** **Permitted Users** is not "All users may self-authorize", or the org requires admin-approved apps.

**Resolution:** Set Permitted Users to **All users may self-authorize**, or pre-authorize each user on the ECA Policies page.

***

### Login works in Salesforce but DeepMask still says unauthorized

**Cause:** The access token expired, the refresh token was revoked, or the org **instance URL** stored on the connection is stale.

**Resolution:** Disconnect and connect again. After a sandbox refresh or My Domain change, users must reconnect so DeepMask stores the new `instance_url`.

***

## Security & Privacy

### Delegated authentication

* Every Salesforce call runs as the signed-in user.
* Salesforce enforces profile, permission sets, sharing rules, and field-level security. DeepMask adds no extra visibility.
* Removing a user's Salesforce access immediately removes what they can see in DeepMask.

### No stored passwords

DeepMask stores a refresh token and the org host (`instance_url`), encrypted at rest. It does not store the user's Salesforce password.

### Writes are confirmed; there is no delete

Users can create and update records (and log calls / meetings). Updates and multi-record creates require an explicit confirm after a preview. **DeepMask cannot delete Salesforce records.**

### Revoking access

* In DeepMask → **Connectors** → **Salesforce** → **Disconnect**.
* In Salesforce Setup → **External Client App Manager** → your app → revoke or delete the app.

Either action invalidates tokens. Users must connect again to restore access.

<Info>
  Questions about data residency, compliance, or security? Contact DeepMask support at [support@deepmask.io](mailto:support@deepmask.io).
</Info>
