How to Securely Store and Use API Keys for Callouts in Salesforce

Introduction

When integrating Salesforce with external services via API callouts, one of the first questions that comes up is: “Where should I store the API key?”
Hardcoding it in Apex? Not ideal. Using Custom Metadata? Maybe. Let’s walk through the most secure and scalable options — and why it matters.

Why Storing API Keys Securely Matters

API keys are sensitive credentials that grant access to external systems. If they’re exposed (e.g., in Apex code or debug logs), they could be misused, leading to data breaches or service abuse. Salesforce provides several secure ways to store and manage these keys.

Recommended Approaches

Hardcoding in Apex

String apiKey = 'sk_test_123456';

Major Anti-Pattern. Definitely a BIG NO for obvious reason

Custom Labels

While easy to use, Custom Labels are not encrypted. Anyone with metadata access can read them.

Only use for non-sensitive identifiers or environment flags.

Slightly better. But there are better options.

Public Custom Metadata/Labels

Public metadata is visible to anyone with access to your org’s metadata — even if read-only. If this is not an issue, certainly. But is there any other more secured way?

Protected Custom Metadata or Custom Settings

Use Protected Custom Metadata Types in a Managed Package to store keys. But this approach is heavier in customization as any changes to the key will need deployment. So any better ones?

Named Credentials (Most Recommended)

Why: Secure, encrypted, managed by Salesforce, and avoids manual token injection in Apex.

Go to Setup → Named Credentials

Create a Named Credential with:

Authentication Type: Named Principal or Per User (depending on use case)

Endpoint URL: e.g., https://api.example.com

Allow Merge Fields in HTTP Header/Body:

Custom Headers: Add Authorization: Bearer {{$Credential.Password}}

Then in Apex:

HttpRequest req = new HttpRequest(); req.setEndpoint('callout:My_External_Service/resource'); req.setMethod('GET'); Http http = new Http(); HttpResponse res = http.send(req);

🔒 Bonus: Passwords/keys in Named Credentials are encrypted and never exposed in debug logs.

MethodSecurityEase of UseEncryptedBest ForCan Be Updated Without Deployment?
Named Credentials⭐⭐⭐⭐⭐ (Very High)⭐⭐⭐⭐✅ YesSecure callouts with API keys or tokens✅ Yes
Protected Custom Metadata⭐⭐⭐⭐ (High)⭐⭐✅ (in package)Semi-sensitive config in managed packages❌ No
Public Custom Metadata⭐⭐⭐ (Moderate)⭐⭐⭐❌ NoOrg-specific keys (internal use)✅ Yes
Custom Labels⭐ (Low)⭐⭐⭐⭐❌ NoNon-sensitive flags or identifiers✅ Yes
Hardcoded in Apex🚫 (Very Poor)⭐⭐⭐⭐❌ No🔥 Never recommended – insecure & inflexible❌ No

Leave a comment