The short answer: use a Named Credential paired with an External Credential for every outbound callout, and never put a secret in Apex, a custom setting or a custom metadata record. The platform then handles token refresh, header construction and certificate presentation for you, and your code contains a single line naming the credential. The only decision left is whether the external system should see one shared identity or each Salesforce user individually.
The shape of the modern configuration
The old single Named Credential has been split into two objects, and the split is the point. An External Credential holds the authentication: protocol, secrets, principals. A Named Credential holds the endpoint URL and references the external credential. Access is granted by giving a permission set access to a named principal on the external credential.
That last part is what people miss on first configuration. Getting the OAuth flow to authenticate is not enough. Without the permission set mapping, the callout fails for every user. It is the single most common “it works in my dev org” difference.
The Apex is trivial once the configuration is right:
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:ERP_API/v2/orders');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setBody(JSON.serialize(payload));
HttpResponse res = new Http().send(req);
No token, no header building, no refresh logic. If your callout class contains any of those things, the configuration is wrong and the class is carrying the consequence.
Choosing an authentication protocol
- OAuth 2.0. The default for modern APIs. The platform stores the refresh token and obtains new access tokens without your code knowing. Supports the usual grant types, including client credentials for server-to-server.
- JWT and JWT bearer token exchange. Right when the far end wants a signed assertion rather than a stored refresh token. Signing uses a certificate you hold in Certificate and Key Management.
- Basic. Fine for an internal system behind a network boundary, and a liability anywhere else. Still better than a password in a custom setting.
- AWS Signature v4. Native support, which saves writing the signing algorithm in Apex. People have written it in Apex. It is not fun.
- No authentication with custom headers, for APIs using a static key. The key lives in the external credential rather than your code.
Named principal or per-user
Named principal means every callout uses one identity. The external system sees “Salesforce” doing everything. Correct for batch jobs, scheduled syncs and anything running asynchronously, because there is no user context to speak of in a scheduled job at 2am. It also means your audit trail on the far side is useless for attribution, so pass the acting user’s identity in the payload if the other system cares.
Per-user means each Salesforce user authenticates individually and the far end applies its own permissions. Correct when the external system has its own security model that must be honoured, typically document management or finance systems.
Per-user has a real operational cost. Every user must complete the authentication flow once, from a Salesforce UI page, and re-authenticate when their grant is revoked or expires. That is a support process, not a technical detail, and it is what stops per-user working for a 4,000-user org. Per-user also cannot work in a context with no user, so any batch or scheduled path needs a named principal alongside it.
Certificates
Two separate uses, frequently confused.
Presenting a client certificate for mutual TLS. You generate or upload a certificate in Certificate and Key Management, the far end trusts it, and the external credential presents it. Self-signed is acceptable when the other party will pin or trust it directly. A CA-signed certificate is needed when they will not.
Signing, for JWT flows, using the same certificate store.
Certificates expire, usually at an inconvenient moment. Salesforce-generated self-signed certificates have a validity period you choose at creation, and nothing reminds you. Put the expiry date in a calendar the day you create it, and know that rotating a certificate requires coordination with the other party. Certificate expiry is a leading cause of integrations that worked for two years and then stopped on a Tuesday.
Frequently asked
Can I read the access token in Apex? No, and that is deliberate. If you need the token for something the callout framework cannot do, the requirement is usually wrong.
What about the endpoint in a sandbox? Named Credentials deploy, external credential secrets do not. Every environment needs its secrets configured after deployment. Build that into the release checklist rather than discovering it during a smoke test.
Do I still need Remote Site Settings? Not for endpoints reached through a Named Credential. They remain for callouts that hardcode a URL, which is another reason not to hardcode one.
