Overview
The ExternalCredential metadata type (externalCredentials/<Name>.externalCredential-meta.xml), introduced in API version 56.0, defines how Salesforce authenticates to an external system and which principals are permitted to initiate callouts. Linked from one or more NamedCredential definitions, an ExternalCredential separates authentication protocols (Oauth, AwsSv4, Custom, Basic, Jwt) and principal definitions (NamedPrincipal, PerUserPrincipal) from endpoint URLs.
Crucially, ExternalCredential metadata files in Git contain only structural configuration (protocol, AWS region/service, JWT claims, principal names, sequence numbers, and runtime header formulas)—never plaintext API keys or client secrets. Secrets are encrypted at rest inside Salesforce’s credential vault and entered post-deployment via Setup or the Connect REST API (/services/data/v68.0/named-credentials/external-credentials).
As shown in the diagram above, ExternalCredential defines the authenticationProtocol, NamedPrincipal slots, and AuthHeader formula expressions in source control, while actual secret values live in the org’s encrypted vault and access is gated by PermissionSet metadata.
Prerequisites
- Permissions: “Customize Application” to deploy
ExternalCredentialmetadata; “Manage Auth. Providers” and “Customize Application” to populate credential secrets in Setup. - Permission Set Grant: Every principal (
NamedPrincipalorPerUserPrincipal) must be enabled in a PermissionSet (<externalCredentialPrincipalAccesses>) or Profile assigned to the running user. - API Version: Introduced in API version 56.0. Verified against API version
68.0(Winter ’27).
Key ExternalCredentialParameter Types
parameterType |
Purpose & Required Sibling Fields |
|---|---|
NamedPrincipal |
Creates a shared credential slot (parameterName = Principal Name, sequenceNumber = priority 1..N). |
PerUserPrincipal |
Creates a per-user credential slot (parameterName = Principal Name). |
AuthHeader |
Injects a runtime authentication header (parameterName = Header Name, parameterValue = Formula such as {!$Credential.Stripe_Auth.SecretKey}, sequenceNumber = header order). |
AuthParameter |
Protocol-specific settings such as AwsRegion, AwsService, AwsAccountId, or OAuth Scope. |
SigningCertificate |
References a certificate in Certificate and Key Management (certificate field) for JWT Bearer Flow or AWS STS RolesAnywhere. |
AdditionalRefreshStatusCode |
Triggers OAuth token refresh on custom HTTP status codes in addition to 401. |
Tip
When using authenticationProtocol = Custom (for API keys or custom Bearer tokens), use the {!$Credential.ExternalCredName.PrincipalKeyName} merge syntax inside an AuthHeader parameterValue. This injects the encrypted secret inside Salesforce’s outbound HTTP proxy so the secret is never visible in Apex debug logs!
Querying ExternalCredential via Tooling API
Query ExternalCredential and ExternalCredentialParameter using the Tooling API (sf data query --use-tooling-api).
1. List All External Credentials and Their Protocols (Tooling API)
SELECT Id, DeveloperName, MasterLabel, AuthenticationProtocol,
Description, LastModifiedDate
FROM ExternalCredential
ORDER BY DeveloperName ASC2. Inspect Principals, Auth Headers, and Parameters (Tooling API)
SELECT ExternalCredential.DeveloperName, ParameterName, ParameterType,
ParameterValue, SequenceNumber, Certificate.DeveloperName
FROM ExternalCredentialParameter
ORDER BY ExternalCredential.DeveloperName ASC, SequenceNumber ASCExample
The following two examples show:
- A Custom Header API Key
ExternalCredential(Stripe_Auth.externalCredential-meta.xml) that injects aBearer {!$Credential.Stripe_Auth.ApiKey}header. - An AWS Signature Version 4 (
AwsSv4)ExternalCredential(AWS_S3_Archive.externalCredential-meta.xml) for signing S3 requests.
1. Custom API Key Bearer Header ExternalCredential
<?xml version="1.0" encoding="UTF-8"?>
<ExternalCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<authenticationProtocol>Custom</authenticationProtocol>
<description>Authenticates Stripe API callouts using an encrypted Bearer API key header.</description>
<externalCredentialParameters>
<parameterGroup>NamedPrincipal</parameterGroup>
<parameterName>NamedPrincipal</parameterName>
<parameterType>NamedPrincipal</parameterType>
<sequenceNumber>1</sequenceNumber>
</externalCredentialParameters>
<externalCredentialParameters>
<parameterGroup>DefaultGroup</parameterGroup>
<parameterName>Authorization</parameterName>
<parameterType>AuthHeader</parameterType>
<parameterValue>'Bearer ' & {!$Credential.Stripe_Auth.ApiKey}</parameterValue>
<sequenceNumber>1</sequenceNumber>
</externalCredentialParameters>
<label>Stripe Auth</label>
</ExternalCredential>2. AWS Signature Version 4 (AwsSv4) ExternalCredential
<?xml version="1.0" encoding="UTF-8"?>
<ExternalCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<authenticationProtocol>AwsSv4</authenticationProtocol>
<description>Signs outbound S3 requests in us-east-1 using AWS Signature Version 4.</description>
<externalCredentialParameters>
<parameterName>S3ServiceAccount</parameterName>
<parameterType>NamedPrincipal</parameterType>
<sequenceNumber>1</sequenceNumber>
</externalCredentialParameters>
<externalCredentialParameters>
<parameterName>AwsService</parameterName>
<parameterType>AuthParameter</parameterType>
<parameterValue>s3</parameterValue>
</externalCredentialParameters>
<externalCredentialParameters>
<parameterName>AwsRegion</parameterName>
<parameterType>AuthParameter</parameterType>
<parameterValue>us-east-1</parameterValue>
</externalCredentialParameters>
<label>AWS S3 Archive</label>
</ExternalCredential>Limits and Gotchas
- Post-Deployment Secret Population Required: After deploying
Stripe_Auth.externalCredential-meta.xmlto a new org, callouts will fail until an administrator opens Setup → Named Credentials → External Credentials → Stripe Auth, clicks New under Custom Headers / Principals, and saves theApiKeysecret value. - Principal Naming in PermissionSet: In PermissionSet, the
<externalCredentialPrincipal>value combines theExternalCredentialDeveloperName and the Principal’sparameterNameseparated by a hyphen (Stripe_Auth-NamedPrincipalorAWS_S3_Archive-S3ServiceAccount). sequenceNumberRequired onNamedPrincipal: Omitting<sequenceNumber>on aNamedPrincipalparameter causes a deployment error.
Related Official Documentation
- ExternalCredential Metadata API Reference: Complete XML specification for
ExternalCredentialandExternalCredentialParameter. - Named Credentials Connect REST API: Programmatically populating credential secrets after metadata deployment.
Frequently asked questions
Are secret keys, passwords, or OAuth client secrets exported in ExternalCredential XML?
No. For security compliance, Metadata API never retrieves or deploys sensitive credential secrets (such as AWS Secret Keys, Client Secrets, or Custom Header secret values) in .externalCredential-meta.xml. Secrets must be entered once per org in Setup or via Connect REST API.
What is the difference between NamedPrincipal and PerUserPrincipal on an ExternalCredential?
A NamedPrincipal uses a single shared service identity for all authorized users who have the linked PermissionSet. A PerUserPrincipal requires each individual user to authenticate their own external account.
How does Salesforce decide which NamedPrincipal to use if a user has multiple PermissionSets?
When a user is assigned multiple PermissionSets that grant access to different NamedPrincipals on the same ExternalCredential, Salesforce selects the NamedPrincipal with the lowest sequenceNumber integer.
How do I inject an API key into an HTTP header using a Custom ExternalCredential?
Set authenticationProtocol to Custom, define a NamedPrincipal parameter (for example, ApiKeyPrincipal), and add an AuthHeader parameter whose parameterValue uses the {!$Credential.ExternalCredName.KeyName} formula syntax.
How do I trigger automatic OAuth token refreshes on non-401 HTTP status codes?
Add an externalCredentialParameters entry with parameterType set to AdditionalRefreshStatusCode and specify the custom 4xx, 6xx, 7xx, 8xx, or 9xx HTTP status code.
How do I query ExternalCredential metadata using SOQL?
Use the Tooling API (--use-tooling-api) to query ExternalCredential and ExternalCredentialParameter to inspect AuthenticationProtocol, ParameterType, ParameterName, and ParameterValue.
Comments
Questions, corrections and tips are welcome. Comments are GitHub Discussions, so you sign in with GitHub.