Using the Same Connected App Across All Environments
“Your sandbox should not talk to production APIs. Ever.”
What Happened
I had one Connected App with one set of OAuth credentials used everywhere — dev, staging, prod. A junior developer testing in sandbox triggered a flow that called the production payment endpoint. Real charges. Real customers. Real angry client. We had to issue refunds and I had to explain to the CEO why their sandbox sent live invoices.
The Wrong Way
// Same Custom Metadata or Custom Setting in every sandbox: API_Endpoint__c = 'https://api.payments.com/v1/charge' Client_Id__c = 'prod_client_abc123' Client_Secret__c = 'prod_secret_xyz789' // Sandbox refreshes copy prod values. Nobody remembers to change them.
The Right Way
// Custom Metadata Type: Integration_Config__mdt
// Production record:
// DeveloperName: PaymentAPI
// Endpoint__c: https://api.payments.com/v1/charge
// Named_Credential__c: PaymentAPI_Prod
// Sandbox post-refresh class:
public class SandboxPostRefresh implements SandboxPostCopy {
public void runApexClass(SandboxContext ctx) {
// Override integration endpoints for sandbox
List<Integration_Config__mdt> configs = [
SELECT DeveloperName FROM Integration_Config__mdt
];
// Named Credentials per environment - sandbox uses sandbox keys
// Alert: post-copy script reminds admin to verify endpoints
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new List<String>{'admin@company.com'});
mail.setSubject('Sandbox ' + ctx.sandboxName() + ' refreshed - verify integrations');
mail.setPlainTextBody('Check Named Credentials and integration endpoints.');
Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{mail});
}
}The Lesson
Every environment gets its own credentials and endpoints. Use Named Credentials per environment and SandboxPostCopy to reset configs on refresh.
Enjoyed this? Get more like it.
Glen's Musings — AI, investing, and building things. Occasional. Free.
More Integration Mistakes
Making a Callout from a Trigger
You cannot make HTTP callouts from a synchronous trigger context. Period.
Read moreCareer-EndingHardcoding API Credentials Instead of Using Named Credentials
Hardcoded API keys in Apex are a security audit's worst nightmare.
Read moreAnnoyingNo Retry Logic on External API Calls
External APIs fail. Your integration should expect that.
Read more