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

# Salesforce setup

ConfigView reads your Salesforce org through the Salesforce REST and Tooling APIs, signing in as a **dedicated integration user** through an **External Client App** that you create in Salesforce.

You will end up with **3 secrets** in ConfigView (`SALESFORCE_INSTANCE_URL`, `SALESFORCE_CLIENT_ID`, `SALESFORCE_CLIENT_SECRET`) when setup is complete.

> **Scope of this integration today.** ConfigView reads who has Salesforce and with what profile, role and licence, who effectively holds admin powers (Modify All Data, View All Data, Manage Users, Customize Application, Author Apex), the outside apps people have authorized with their Salesforce account, connected apps and installed packages, where Salesforce is set up to send data, login history and the Setup Audit Trail. ConfigView only reads. It never creates or changes anything, and it never reads your CRM records: no accounts, contacts, leads, opportunities or cases.

**Editions:** Enterprise, Unlimited, Performance and Developer Edition. Professional Edition works only with the API add-on. Essentials has no API access.

***

## Step 1: Open the Salesforce page in ConfigView

Open ConfigView in a second browser tab and leave it open:

`https://{companyname}.configview.com/admin/integrations/salesforce`

***

## Step 2: Create the integration user

ConfigView's calls all run as one Salesforce user. Use a dedicated one, so the access is easy to see and nobody leaving the company breaks it.

1. In Salesforce, open **Setup → Users → Users → New User**
2. **User License:** `Salesforce Integration` (orgs get a few free). **Profile:** `Minimum Access - API Only Integrations`. If your org has no Salesforce Integration licences, any licence works with a profile that has **API Enabled**
3. Use an address you control for the email, such as `configview-integration@yourcompany.com`, and save

Then give it read access to settings with a permission set:

1. **Setup → Permission Sets → New**. Name it `ConfigView Read Only`. Leave **License** set to `--None--` (or `Salesforce Integration`)
2. Open **System Permissions → Edit** and turn on:

| Permission | Why ConfigView needs it |
| - | - |
| **API Enabled** | To call the API at all |
| **View Setup and Configuration** | Permission sets, connected apps, named credentials, remote sites, installed packages, the Setup Audit Trail |
| **View All Users** | Every user, not only the ones the sharing model shows |
| **Monitor Login History** | Everyone's login history. Without it only the integration user's own logins come back |
| **Customize Application** *(optional, recommended)* | Salesforce shows the full list of OAuth-authorized apps only to users with this permission. Without it ConfigView sees only the integration user's own, and **Authorized Apps** stays nearly empty |
| **View Event Log Files** *(optional)* | Lists the Event Monitoring log files Salesforce produces each day |

3. Save, click **Manage Assignments → Add Assignment**, and assign it to the integration user

**Customize Application** is a write permission for Setup in the Salesforce UI. ConfigView never writes, and the integration user can't sign in to the UI with the `API Only` profile. If your policy doesn't allow it, leave it off and accept a partial **Authorized Apps** list.

***

## Step 3: Create the External Client App

1. **Setup → External Client App Manager → New External Client App**
2. Name it `ConfigView`, enter a contact email, and set **Distribution State** to `Local`
3. Under **API (Enable OAuth Settings)**, check **Enable OAuth**. Enter any callback URL (`https://login.salesforce.com/services/oauth2/success` works; this flow doesn't use it)
4. **OAuth Scopes:** add only `Manage user data via APIs (api)`
5. Check **Enable Client Credentials Flow**. Leave the other flow options as they are, and create the app
6. Open the app's **Policies** tab, click **Edit**, and under **OAuth Policies → Client Credentials Flow** set **Run As** to the integration user from Step 2. Save
7. Open the **Settings** tab, expand **OAuth Settings**, and click **Consumer Key and Secret**. Salesforce emails you a verification code first

If your org still uses classic connected apps, a connected app with **Enable Client Credentials Flow** and a **Run As** user under **Manage → Edit Policies** works the same way.

***

## Step 4: Paste the secrets into ConfigView

| Secret | Value |
| - | - |
| `SALESFORCE_INSTANCE_URL` | Your My Domain URL, e.g. `https://acme.my.salesforce.com` (**Setup → My Domain**). `login.salesforce.com` won't work: it doesn't issue client-credentials tokens |
| `SALESFORCE_CLIENT_ID` | The **Consumer Key** |
| `SALESFORCE_CLIENT_SECRET` | The **Consumer Secret** |

Paste each one under **Credentials** and click the save icon.

***

## Step 5: Connect and verify

1. Click **Connect**. ConfigView creates its tables and schedules every collector at your default run time. Stop any you don't want under **Collectors**:

| Script | Notes |
| - | - |
| **Users** | Every Salesforce user: username, email, active flag, user type, profile, role, licence, last login and when the account was created. |
| **Frozen and Locked Users** | Whether each user is frozen by an admin or locked out after failed passwords. Frozen users are still active and still count against licences. |
| **Permission Sets** | Permission sets, permission set groups and the hidden set behind every profile, with the powerful permissions each grants. |
| **Permission Set Assignments** | Which user holds which permission set or group, including the one every profile assigns, and when a time-limited assignment expires. |
| **Authorized Apps (OAuth Tokens)** | Every outside app a user has signed in to Salesforce with: the app's name, whose account it acts as, how often and when it was last used. |
| **Connected Apps** | Connected apps installed or created in the org, and how locked down each is. |
| **Installed Packages** | AppExchange and other managed packages installed in the org: package name, namespace and installed version. |
| **Outbound Endpoints** | Where Salesforce is set up to send data: named credentials, remote site settings and trusted browser sites, with the destination host. |
| **Login History** | Every login to the org over the last six months: who, when, from which IP and country, by browser, API or SSO, and whether it succeeded. |
| **Setup Audit Trail** | Every configuration change an admin made in Setup over the last six months: what changed, where, by whom. |
| **Event Log Files** | Which Event Monitoring log files Salesforce produced each day, and their size. File contents aren't downloaded. |

2. Click **Verify now**. The health check gets a token, reports how much of your org's daily API allocation is left, reads one user, then checks each optional permission.

If a check fails:

* **Token request fails with `invalid_client` or `invalid_client_id`.** The consumer key or secret is wrong, or the app was created minutes ago. New External Client Apps can take up to 10 minutes to start working.
* **Token request fails with `no client credentials user enabled`.** The app has no **Run As** user. Set it in Step 3.6.
* **SOQL on User fails with `INSUFFICIENT_ACCESS` or `API_DISABLED_FOR_USER`.** The permission set from Step 2 isn't assigned to the Run As user, or it lacks **API Enabled**.
* **"OauthToken visibility" is a warning.** The integration user lacks **Customize Application**, so ConfigView sees only its own authorized apps.
* **"LoginHistory visibility" is a warning.** The integration user lacks **Monitor Login History**.
* **"Daily API allocation" fails.** Your org has used more than 80% of its 24-hour API allocation. ConfigView pauses its collectors above that level so your other integrations keep working. It resets on a rolling 24 hours.

***

## Data Tables

Once the scripts run, these tables are created in your database. Each includes a `run_at` column and a `raw_json` column holding the record as Salesforce returned it, minus anything listed under *What isn't collected*. Ids are Salesforce's 18-character record Ids, so join users on `user_id`.

**Snapshot tables** keep only the newest run. **History tables** (login history, Setup Audit Trail, event log files) keep every record ever collected. Salesforce deletes these after six months, so ConfigView's copy is the only one that lasts longer.

| Table | Source | Key Columns |
| - | - | - |
| `salesforce_users` | SOQL `User` | user\_id, username, email, name, is\_active, user\_type, profile\_id, profile\_name, user\_license, role\_id, role\_name, last\_login\_date, created\_date, federation\_identifier, department, title, manager\_id |
| `salesforce_user_logins` | SOQL `UserLogin` | user\_login\_id, user\_id, is\_frozen, is\_password\_locked, last\_modified\_date |
| `salesforce_permission_sets` | SOQL `PermissionSet` | permission\_set\_id, name, label, is\_owned\_by\_profile, profile\_id, profile\_name, set\_type, permission\_set\_group\_id, modify\_all\_data, view\_all\_data, api\_enabled, manage\_users, customize\_application, author\_apex, view\_setup, view\_all\_users, manage\_profiles\_permissionsets, assign\_permission\_sets, reset\_passwords, modify\_metadata, manage\_internal\_users, view\_event\_log\_files |
| `salesforce_permission_set_assignments` | SOQL `PermissionSetAssignment` | assignment\_id, assignee\_id, permission\_set\_id, permission\_set\_group\_id, expiration\_date, is\_active |
| `salesforce_oauth_tokens` | SOQL `OauthToken` | token\_id, app\_name, user\_id, use\_count, last\_used\_date, created\_date, app\_menu\_item\_id |
| `salesforce_connected_apps` | SOQL `ConnectedApplication` | connected\_app\_id, name, created\_date, admin\_approved\_users\_only, refresh\_token\_expires\_on\_inactivity, refresh\_token\_validity\_period, has\_session\_level\_policy, start\_url\_host |
| `salesforce_installed_packages` | Tooling `InstalledSubscriberPackage` | install\_id, package\_id, package\_name, namespace\_prefix, version\_name, major\_version, minor\_version, patch\_version |
| `salesforce_outbound_endpoints` | SOQL `NamedCredential`, `CspTrustedSite`; Tooling `RemoteProxy` | kind, record\_id, name, label, endpoint\_host, is\_active, detail |
| `salesforce_login_history` *(history)* | SOQL `LoginHistory` | login\_id, user\_id, login\_time, login\_type, status, source\_ip, country\_iso, application, browser, platform, api\_type, login\_url\_host |
| `salesforce_setup_audit_trail` *(history)* | SOQL `SetupAuditTrail` | audit\_id, action, section, display, created\_by\_id, created\_by\_username, created\_date, delegate\_user |
| `salesforce_event_log_files` *(history)* | SOQL `EventLogFile` | file\_id, event\_type, log\_date, log\_file\_length, log\_interval |

***

## Things worth knowing

**Profiles are permission sets too.** Every profile has a hidden permission set behind it (`is_owned_by_profile = 1`), and every user has an assignment to their profile's one. So to find who holds a permission, join assignments to permission sets: that covers profiles, permission sets and permission set groups in one query.

**API calls come out of your org's daily allocation.** Salesforce gives each org a rolling 24-hour API request allocation (Enterprise: 100,000 plus 1,000 per licence), shared by every integration you run. A full ConfigView run on a 1,000-user org is a few dozen calls, plus one call per 2,000 new logins. Each collector stops cleanly once the org passes 80% of its allocation, and the next run picks up where it stopped.

**Authorized apps need Customize Application.** Without it, Salesforce returns only the integration user's own OAuth tokens. The collector notices and says so in its log, and the health check shows a warning.

**Salesforce stops a single OAuth token query at 2,500 rows.** On large orgs ConfigView counts the tokens first and reads them in date windows small enough to come back whole.

**Login history and the audit trail only go back six months.** That's how long Salesforce keeps them. The first run backfills all six months. After that ConfigView keeps every record, so the history grows past six months from the day you connect.

**Outbound endpoints are hosts only.** A named credential or remote site is stored as `api.example.com`, never the full URL, which can carry keys.

**Event log files without Event Monitoring.** Orgs without the Event Monitoring add-on still get Login, Logout and API Total Usage files, kept for one day. ConfigView records that each file exists, never its contents.

## What isn't collected

* CRM records: accounts, contacts, leads, opportunities, cases, or any custom object's records
* OAuth access tokens, refresh tokens and revoke handles. Only the app name, owner and usage counts are read
* Event log file contents
* Full URLs of named credentials, remote sites and connected app start pages. Hosts only
* Passwords, security tokens and any credential stored in a named or external credential


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.