uses the to:
- Read and for user provisioning
- Write to
Authentication is (a certificate-based OAuth flow) - not a stored username/password. Salesforce is retiring the legacy SOAP login() path this setup replaces (mandatory Summer '27).
-
successpro_api_integration - "Allows ActiFi's SuccessPro API user to connect and read / write object level data"
- unchecked (no interactive session to gate for a headless integration user)
-
Salesforce API Integration - a Permission Set License, found under a separate "Permission Set Licenses" group in the dropdown (not "User Licenses"). Required for Object Settings below to be visible/editable.
Grant within this Permission Set:
- View All on Contact, View All on Account, plus any other objects this tenant's integration reads/writes (including Custom Objects).
- Access Activities, Edit Tasks (and Edit Events if writing calendar events)
- - only if in scope for this tenant's integration: Case, Opportunity, Lead. Not universal requirements; scope to what this tenant's integration actually uses.
-
dev+{tenant}@{yourdomain}.com - must be globally unique across every Salesforce org that has ever existed (unlike Email). -
dev@actifi.com, or dev+{tenant}@actifi.com -
Salesforce API Only System Integrations (not minimum API License). -
Salesforce Integration. - JWT Bearer never uses a stored password for this user.
- leave
<None Specified> unless this integration writes activities owned by other users - see Notes below if so.
Assign successpro_api_integration to the integration user.
- (
SuccessPro_Connected_App), if the Salesforce widget is already configured for this tenant - just add the settings below to that same app. - See the Addendum below for a standalone app.
- External Client App Manager -> select the app -> row action menu -> (not "Edit Settings".
- App Policies tab -> Selected Permission Sets -> add
successpro_api_integration.
- External Client App Manager -> select the app -> -> -> -> check
- upload the
.crt - never the .key (private key). The private key goes only to ActiFi's secrets storage, never to Salesforce. - confirm both are present:
- Manage user data via APIs (
api) - Perform requests at any time (
refresh_token, offline_access) - required for the JWT Bearer grant even though no refresh token is actually issued or used. Omitting it fails with invalid_request:
refresh_token scope is required and the connected app should be installed and preauthorized.
Send the Consumer Key / Secret (from the app's Edit Settings -> OAuth screen) to ActiFi.
- optional IP allowlisting for Production/Staging. Not required for the JWT Bearer flow (JWT auth doesn't use a Security Token the way legacy
login() did) - relevant mainly if this tenant also keeps a legacy conn.login() fallback configured. - "Production" IP addresses: 34.207.47.137, 18.215.23.68, 52.7.58.134, 3.84.107.235
- "Staging" IP addresses: 34.238.205.73, 34.236.248.209, 35.153.112.248, 3.84.107.235
- if activity owners have a Role, ensure the API user's Role outranks the role of any user who will own Salesforce activities written via the API user.
- if this tenant's integration needs to relate multiple contacts to a single Task/Event (
TaskRelation), confirm is enabled on the org first (Setup -> Activity Settings -> "Allow Users to Relate Multiple Contacts to Tasks and Events") - a per-org toggle, unrelated to anything above. A plain single-contact Task is unaffected either way.
Use this only if the tenant has no SuccessPro External Client App already set up for the widget.
Create the ECA the same way as the Widget Installation doc's steps 1-6, with these differences:
- use a placeholder value such as " login.salesforce.com "- there's no real widget callback to point it at.
- leave disabled; Canvas is not needed for API-only access.
Complete steps 5-7 above (Selected Permission Sets, JWT Bearer + certificate + scopes, Consumer Key) on this standalone app, exactly the same way.