diff --git a/apps/docs/content/docs/en/integrations/salesforce-service-account.mdx b/apps/docs/content/docs/en/integrations/salesforce-service-account.mdx
index 6ff28bf72b1..e77e619391b 100644
--- a/apps/docs/content/docs/en/integrations/salesforce-service-account.mdx
+++ b/apps/docs/content/docs/en/integrations/salesforce-service-account.mdx
@@ -56,7 +56,7 @@ External Client Apps are Salesforce's current-generation connected apps and the
{/* TODO(screenshot): New External Client App form with the basic details filled in */}
- In the OAuth settings section, enable OAuth (exact labels vary by Salesforce release)
+ Open the app's **Edit Settings** → **API (Enable OAuth Settings)** section and turn on **Enable OAuth**
Enter any placeholder **Callback URL** (e.g. `https://login.salesforce.com/services/oauth2/callback`) — it's required by the form but unused by this flow
@@ -81,7 +81,7 @@ External Client Apps are Salesforce's current-generation connected apps and the
Open your app in **External Client App Manager** and edit its **Policies**
- Under **OAuth Policies** → **Client Credentials Flow**, check **Enable Client Credentials Flow** and set **Run As** to the integration user from step 1, then save
+ Under **OAuth Policies** → **Client Credentials Flow**, set **Run As** to the integration user from step 1, then save. That page holds only the Run As picker — the **Enable Client Credentials Flow** checkbox itself lives in **Edit Settings** → **OAuth Settings**, where you set it in step 2
{/* TODO(screenshot): OAuth Policies with the Run As integration user set under Client Credentials Flow */}
@@ -133,9 +133,13 @@ The JWT Bearer Flow authenticates with an uploaded certificate rather than a sha
```
Keep `server.key` somewhere safe — Sim stores it encrypted and never shows it again.
+
+
+ Salesforce requires an **RSA** key of at least 2048 bits for this flow; an ECDSA key is rejected. The uploaded certificate must also stay under 4 KB, which a 2048-bit self-signed cert comfortably is.
+
- In **External Client App Manager** → your app → **Edit Settings** → **OAuth Settings**, enable the **JWT Bearer Flow** toggle and upload `server.crt`. On a legacy Connected App the equivalent is **Use digital signatures** with the same file
+ In **External Client App Manager** → your app → **Edit Settings** → **OAuth Settings**, turn on **Enable OAuth** (the JWT toggle does not appear until it is on), then **Enable JWT Bearer Flow**, and use **Upload Files** to upload `server.crt`. On a legacy Connected App the equivalent is **Use digital signatures** with the same file
Edit the app's **Policies** → **OAuth Policies** and set **Permitted Users** to **Admin approved users are pre-authorized**
@@ -145,7 +149,11 @@ The JWT Bearer Flow authenticates with an uploaded certificate rather than a sha
- Assign the integration user's **profile** or a **permission set** to the app (External Client App Manager → your app → **Policies** → manage profiles/permission sets), so that user is covered by the pre-authorization
+ Assign the integration user's **profile** or a **permission set** to the app, so that user is covered by the pre-authorization
+
+
+ Assign it through the **profile**, or through a **second permission set that does _not_ carry the Salesforce API Integration permission set license**. A permission set backed by that license cannot hold an **Assigned Connected Apps** / **Assigned External Client Apps** section at all, so the app can never be assigned from the same permission set that grants the user its object access. Getting this wrong produces exactly the `user hasn't approved this consumer` failure this step exists to prevent.
+
Copy the **Consumer Key** as in step 4. There is no consumer secret to copy — the JWT flow doesn't use one
@@ -158,7 +166,7 @@ Go to **Setup** and search for **My Domain**. The host is required — Salesforc
- **Production:** `yourorg.my.salesforce.com`
- **Sandbox:** `yourorg--sandboxname.sandbox.my.salesforce.com`
-- **Developer Edition:** `yourorg-dev-ed.develop.my.salesforce.com`
+- **Developer Edition:** `yourorg.develop.my.salesforce.com` (Salesforce appends `-dev-ed` only when it generated the name for you)
Sim also accepts other partitioned My Domain hosts (`scratch`, `demo`, `patch`, `trailblaze`, `free`).
@@ -176,6 +184,15 @@ There's no scope picking beyond the **api** and **openid** scopes on the app —
A permissions gap surfaces at run time as a Salesforce API error; fix it on the integration user's permission sets — no changes are needed in Sim.
+
+On the **Salesforce Integration** (API-only) license specifically, SOQL and CRUD on standard objects are well supported, but two areas are not safe to assume:
+
+- **Reports and dashboards** are unverified on this license. Salesforce documents neither a grant nor a prohibition. Test them in a sandbox before depending on them, and remember the user also needs access to the report or dashboard **folder**.
+- **Anything Apex-related is blocked** — Apex Class Access is one of the permissions this license cannot hold, so Tooling API calls touching `ApexClass` will fail. Custom field and custom object management is unaffected.
+
+If a workflow must run reports, a standard-seat integration user is the safe choice.
+
+
## Adding the Service Account to Sim
@@ -230,7 +247,7 @@ Deactivating or freezing the integration user — the Run As user for client cre
{ question: "Setup → App Manager → New Connected App is greyed out — why?", answer: "Salesforce disabled new Connected App creation by default (new orgs since Summer '25, all orgs since Spring '26); re-enabling it requires a Salesforce Support request. You don't need it — create an External Client App instead (Setup → External Client App Manager), which supports the same Client Credentials Flow and produces the same consumer key and secret." },
{ question: "Why do I have to enter a My Domain host instead of login.salesforce.com?", answer: "Salesforce only supports the Client Credentials Flow at your org's My Domain URL — login.salesforce.com and test.salesforce.com are explicitly rejected for this flow. Find yours under Setup → My Domain." },
{ question: "The credential validates but a specific tool fails with a permission error — why?", answer: "Every call runs as the Run As user, so the failing tool needs a permission that user doesn't have. Common gaps: Customize Application for custom field/object tools, Run Reports plus folder access for report tools, and object or field permissions for the records involved. Fix it on the integration user's permission sets and re-run." },
- { question: "Does this work with sandboxes and Developer Edition orgs?", answer: "Yes — enter the sandbox host (yourorg--sandboxname.sandbox.my.salesforce.com) or Developer Edition host (yourorg-dev-ed.develop.my.salesforce.com) as the My Domain host. Government/military domains (*.my.salesforce.mil) aren't currently supported." },
+ { question: "Does this work with sandboxes and Developer Edition orgs?", answer: "Yes — enter the sandbox host (yourorg--sandboxname.sandbox.my.salesforce.com) or Developer Edition host (yourorg.develop.my.salesforce.com, with a -dev-ed suffix only if Salesforce generated the name for you) as the My Domain host. Government/military domains (*.my.salesforce.mil) aren't currently supported." },
{ question: "How do I rotate the credentials?", answer: "For client credentials, rotate the Consumer Secret from the app's OAuth settings (External Client App: Settings → OAuth Settings → Consumer Key and Secret; legacy Connected App: Manage Consumer Details), then update the credential in Sim with the new secret. For JWT bearer, generate a new key pair, upload the new certificate to the app, and paste the new private key into Sim. Either way, reconnecting asks you to restate the authentication method — Sim never returns a stored secret, so it cannot pre-select it for you." },
{ question: "What happens if the integration user is deactivated or frozen?", answer: "All token minting fails with invalid_grant and every workflow using the credential stops. Reactivate the user (or point Run As at a new integration user) and runs resume — no changes needed in Sim." },
]} />