Integrating Salesforce with external systems requires making HTTP callouts. This guide covers REST API calls, using Named Credentials for security, and implementing robust error handling.
public class WeatherService {
public static void getWeatherData(String city) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.weather.com/forecast?city=' + city);
request.setMethod('GET');
request.setTimeout(120000);
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
System.debug('Weather Data: ' + response.getBody());
} else {
System.debug('Error: ' + response.getStatus());
}
}
}
Never hardcode API keys or URLs in your code. Use Named Credentials instead.
public class PaymentService {
public static void processPayment(String paymentId, Decimal amount) {
Http http = new Http();
HttpRequest request = new HttpRequest();
// Use callout named credential
request.setEndpoint('callout:PaymentAPI/process');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setTimeout(120000);
String body = JSON.serialize(new Map<String, Object>{
'paymentId' => paymentId,
'amount' => amount
});
request.setBody(body);
try {
HttpResponse response = http.send(request);
handlePaymentResponse(response);
} catch (Exception e) {
System.debug('Callout failed: ' + e.getMessage());
}
}
private static void handlePaymentResponse(HttpResponse response) {
if (response.getStatusCode() == 200) {
System.debug('Payment processed successfully');
} else if (response.getStatusCode() == 400) {
System.debug('Bad request: ' + response.getBody());
} else if (response.getStatusCode() == 401) {
System.debug('Unauthorized');
}
}
}
public class CRMIntegration {
public static void syncCustomer(Account acc) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('callout:CRMSystem/customers');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setHeader('Authorization', 'Bearer ' + getAccessToken());
CustomerWrapper customer = new CustomerWrapper(acc);
String jsonBody = JSON.serialize(customer);
request.setBody(jsonBody);
HttpResponse response = http.send(request);
if (response.getStatusCode() == 201) {
acc.External_ID__c = JSON.deserialize(response.getBody(), Map<String, Object>).get('id').toString();
update acc;
}
}
private static String getAccessToken() {
// Fetch token from cache or request new one
return Cache.SessionCache.getSessionCache().get('crm_token');
}
public class CustomerWrapper {
public String name;
public String email;
public String phone;
public CustomerWrapper(Account acc) {
this.name = acc.Name;
this.email = acc.Email__c;
this.phone = acc.Phone;
}
}
}
public class RobustIntegration {
public static void callExternalAPI(String endpoint, String payload) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(endpoint);
request.setMethod('POST');
request.setBody(payload);
request.setTimeout(120000);
HttpResponse response;
try {
response = http.send(request);
switch on response.getStatusCode() {
when 200, 201 {
handleSuccess(response);
}
when 400 {
handleBadRequest(response);
}
when 401 {
handleUnauthorized(response);
}
when 404 {
handleNotFound(response);
}
when 429 {
handleRateLimit(response);
}
when 500, 502, 503 {
handleServerError(response);
}
when else {
handleUnexpectedError(response);
}
}
} catch (CalloutException e) {
System.debug('Callout timeout or other error: ' + e.getMessage());
// Implement retry logic or logging
} catch (Exception e) {
System.debug('Unexpected error: ' + e.getMessage());
}
}
private static void handleSuccess(HttpResponse response) {
System.debug('Success: ' + response.getBody());
}
private static void handleBadRequest(HttpResponse response) {
System.debug('Bad Request: ' + response.getBody());
// Log to custom error table
}
private static void handleUnauthorized(HttpResponse response) {
System.debug('Refresh credentials and retry');
}
private static void handleRateLimit(HttpResponse response) {
System.debug('Rate limited. Implement exponential backoff');
}
private static void handleServerError(HttpResponse response) {
System.debug('External system error. Queue for retry');
}
private static void handleUnexpectedError(HttpResponse response) {
System.debug('Status: ' + response.getStatusCode() + ' - ' + response.getStatus());
}
}
public class ResilientCallout {
private static final Integer MAX_RETRIES = 3;
private static final Integer TIMEOUT_MS = 120000;
public static void callWithRetry(String endpoint, String payload) {
Integer retries = 0;
while (retries < MAX_RETRIES) {
try {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(endpoint);
request.setMethod('POST');
request.setBody(payload);
request.setTimeout(TIMEOUT_MS);
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
return; // Success
} else if (response.getStatusCode() >= 500) {
retries++;
// Exponential backoff not applicable in sync context
}
} catch (CalloutException e) {
retries++;
if (retries >= MAX_RETRIES) {
throw new CustomException('Callout failed after ' + MAX_RETRIES + ' attempts');
}
}
}
}
}
public class CustomException extends Exception { }