Not verified hands-on. This article was written from primary documentation rather than reproduced in an org, so it carries no tested-release badge. If you run it and something differs, say so in the comments and it gets tested and corrected.

In one sentence: give every integration its own user, on an integration licence where you can, with a profile that grants almost nothing, permission sets that grant exactly what that integration touches, login IP ranges that match the calling system, and enough logging that you can answer “what did it change and when” without guessing. The failure mode is always the same: one shared account with a System Administrator profile, used by six systems, with a password in a wiki.

Licence first

Salesforce sells an Integration user licence intended precisely for this. It is API-only, it cannot log into the user interface, and Salesforce includes a small number at no extra cost in most orgs with more available to buy. Access is granted through a permission set licence rather than a rich profile, which pushes you towards the right design whether you meant to or not.

Where that licence does not fit, a standard Salesforce licence with the API Only User permission is the fallback. That permission blocks UI login while leaving the API open, and it is the single most valuable setting on an integration profile. Without it, a leaked credential gets somebody a full session in the browser.

Profile and permission sets

The profile should be a clone of a minimal one, not of System Administrator. What it needs: API Enabled, the right licence, a sensible default record type set, and nothing else. Put every object permission, field permission, Apex class access and named credential access in permission sets instead.

The reason is auditability. When someone asks what the ERP integration can see, you want the answer to be a permission set called ERP_Integration_Access that you can read in thirty seconds, not a profile page you have to scroll through.

Be specific about field-level security. An integration that syncs five fields on Account should have read and write on those five, not on all of Account. This is tedious once and pays for itself the first time somebody asks whether the integration could have written to a compliance field.

Watch View All and Modify All. They are convenient and they defeat the sharing model entirely. Prefer a sharing rule granting the integration user access to the records it actually needs, or ownership of a role at the top of a branch of the hierarchy if the data is genuinely org-wide.

Network restrictions

Login IP ranges on the profile are enforced absolutely: a login from outside the range is refused, with no verification code fallback. For an integration running from known infrastructure, this is the strongest control available and costs nothing.

Get the ranges from the calling system’s egress addresses, not from someone’s laptop. If the caller sits on a cloud platform with rotating outbound IPs, put a static egress in front of it.

Connected app IP relaxation interacts with this. If the app is set to relax IP restrictions, it can override the profile’s ranges for that app’s sessions. Check both, together, or you will conclude the restriction is working when it is not.

Credentials

Prefer the JWT bearer flow with a certificate over a stored password, and the Client Credentials flow where the caller is a server that needs no user context. Both remove the password from the equation. Rotate the certificate on a schedule you have actually written down.

Never reuse one integration user across systems. You lose attribution in every log, you cannot revoke one integration without breaking the others, and the permission set for that user becomes the union of everything anyone ever needed.

What to log

  • Login History for the integration user: source IP, application, status, API version. Alert on any login from an unexpected address.
  • Setup Audit Trail for changes to the user, its profile and its permission sets. Somebody adding Modify All to an integration user should generate a conversation.
  • Event Monitoring where available: the API and REST API event types give you per-call records with row counts, which is the only way to spot an integration quietly extracting far more than it should.
  • Your own trail. Stamp a source field on records the integration writes. When a number is wrong six months later, this is what tells you which system wrote it.

Frequently asked

Can an integration user own records? Yes, and for records that have no natural human owner that is often the tidiest answer. Give it a role so sharing behaves predictably.

Should the integration user have a real email address? A monitored distribution list, yes. Salesforce sends security and API deprecation notices to that address, and nobody reads a mailbox called noreply.

What about sharing rules versus Modify All? Start with sharing rules. Reach for Modify All only when the integration genuinely needs every record of an object, and record why.