API Integration in Salesforce
1. Introduction
Overview of API Integration
What is API integration?
API integration involves connecting Salesforce with external systems to exchange data and
perform tasks.
Importance of API integration in Salesforce
Enables automation of business processes and data synchronization between Salesforce and
external systems.
Types of APIs in Salesforce
SOAP API: Used for integrating Salesforce with enterprise applications that require robust
security and transaction control.
REST API: Lightweight and easier to use, suitable for mobile and web applications.
Bulk API: Designed to handle large data volumes asynchronously.
Metadata API: Used to manage Salesforce metadata, such as custom object definitions and
page layouts.
SOAP API
Description: SOAP API allows for robust and secure integration between Salesforce and other
enterprise applications. It supports transaction control and has built-in retry logic.
Use Cases: Ideal for integrations requiring strong security and complex transactions.
Example:
// SOAP API integration using WSDL
MyServiceSoap myService = new MyServiceSoap();
MyServiceSoap.MyRequest request = new MyServiceSoap.MyRequest();
request.Field1 = 'Value1';
MyServiceSoap.MyResponse response =
myService.MyOperation(request);
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
REST API
Description: REST API is lightweight and easy to use, making it suitable for mobile and web
applications. It uses standard HTTP methods (GET, POST, PUT, DELETE).
Use Cases: Ideal for building simple and quick integrations, especially for mobile and web apps.
Example:
// REST API integration
HttpRequest request = new HttpRequest();
request.setEndpoint('https://instance.salesforce.com/services/data
/v52.0/sobjects/Account');
request.setMethod('POST');
request.setHeader('Authorization', 'Bearer ' + sessionId);
request.setHeader('Content-Type', 'application/json');
request.setBody('{"Name":"New Account"}');
HttpResponse response = http.send(request);
Bulk API
Description: Bulk API is designed to handle large data volumes asynchronously. It allows for the
processing of large datasets in a single API call.
Use Cases: Ideal for data migrations, data loads, and other bulk data operations.
Example:
// Bulk API integration example
HttpRequest request = new HttpRequest();
request.setEndpoint('https://instance.salesforce.com/services/async
/52.0/job');
request.setMethod('POST');
request.setHeader('Authorization', 'Bearer ' + sessionId);
request.setHeader('Content-Type', 'application/xml');
request.setBody('<?xml version="1.0" encoding="UTF-8"?><jobInfo
xmlns="http://www.force.com/2009/06/asyncapi/dataload"><operation>i
nsert</operation><object>Account</object></jobInfo>');
HttpResponse response = http.send(request);
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Metadata API
Description: Metadata API is used to manage Salesforce metadata, such as custom object
definitions, page layouts, and more.
Use Cases: Ideal for deploying changes between Salesforce environments, managing customization,
and building deployment tools.
Example:
// Metadata API integration example
MetadataService.MetadataPort service = new
MetadataService.MetadataPort();
service.SessionHeader = new
MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = sessionId;
MetadataService.CustomObject customObject = new
MetadataService.CustomObject();
customObject.fullName = 'CustomObject__c';
customObject.label = 'Custom Object';
customObject.pluralLabel = 'Custom Objects';
customObject.nameField = new MetadataService.CustomField();
customObject.nameField.type_x = 'Text';
customObject.nameField.label = 'Name';
MetadataService.AsyncResult[] results = service.create(new
MetadataService.Metadata[] { customObject });
2. Setting Up API Integration
Auth Provider
What is an Auth Provider?
An Auth Provider in Salesforce allows you to authenticate users via third-party services using
OAuth 2.0.
Steps to create an Auth Provider in Salesforce
a. Navigate to Setup: In Salesforce, go to Setup.
b. Search for Auth Providers: In the Quick Find box, type "Auth Providers" and select it.
c. Create a New Auth Provider: Click "New" and choose the provider type (e.g., Google, Facebook).
d. Configure the Auth Provider: Fill in the necessary fields such as Consumer Key, Consumer
Secret, and Callback URL.
e. Save the Auth Provider: Click Save.
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Configuration settings and parameters:
Auth Endpoint URL: The URL to which users are directed to authenticate.
Token Endpoint URL: The URL to obtain the access token.
User Info Endpoint URL: The URL to fetch user information.
Example: Setting up OAuth with Google
Google Developer Console: Create a new project, enable the Google+ API, and create OAuth
credentials.
Salesforce Setup: Create an Auth Provider using the Google credentials.
Configuration: Use the Client ID and Client Secret from Google, set the Authorize Endpoint
URL to https://accounts.google.com/o/oauth2/auth, Token Endpoint URL to
https://accounts.google.com/o/oauth2/token, and Default Scopes to openid
profile email.
Connected App
What is a Connected App?
A Connected App allows external applications to integrate with Salesforce using APIs.
Creating a Connected App in Salesforce
a. Navigate to Setup: In Salesforce, go to Setup.
b. Search for App Manager: In the Quick Find box, type "App Manager" and select it.
c. Create a New Connected App: Click "New Connected App" and fill in the required fields.
Configuring OAuth settings
Enable OAuth Settings: Check "Enable OAuth Settings".
Callback URL: Set the Callback URL to the endpoint where Salesforce should redirect after
successful authentication.
Scopes: Define the OAuth scopes required (e.g., api, refresh_token, openid).
Managing permissions and scopes
Permission Sets: Assign permission sets to control access to the Connected App.
OAuth Policies: Configure OAuth policies like IP ranges, session timeout, and token validity.
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Example: Setting up a Connected App for an external API
External System: Configure the external system with the Salesforce Connected App's Client
ID and Client Secret.
OAuth Flow: Demonstrate the OAuth flow where the external system requests an access
token from Salesforce using the Connected App's credentials.
3. Keywords and Concepts
API Terminology
Endpoint: The specific URL where an API is accessible (e.g.,
https://api.example.com/data).
Request and Response: The communication between the client and server. A request is sent
by the client, and a response is returned by the server.
Authentication vs. Authorization: Authentication verifies the identity of a user or system.
Authorization determines what resources the authenticated user or system can access.
Tokens (Access Token, Refresh Token): Tokens are used for securing API requests. An
access token is used for accessing resources, while a refresh token is used to obtain a new
access token when the current one expires.
Headers: Additional information sent with an API request or response (e.g., Content-Type:
application/json).
JSON and XML: Data formats used in API communication. JSON (JavaScript Object Notation)
is lightweight and easy to read, while XML (eXtensible Markup Language) is more verbose and
used for complex data structures.
Rate Limits and Quotas: Restrictions on the number of API calls that can be made within a
specific time period to prevent abuse and ensure fair usage.
HTTP Status Codes
HTTP status codes are issued by a server in response to a client's request made to the server.
They are important for understanding the result of API calls. Here are some commonly used
HTTP status codes:
200 OK: The request has succeeded.
Example:
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
// Success
}
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
201 Created: The request has been fulfilled and resulted in a new resource being created.
Example:
request.setEndpoint('https://api.example.com/records');
request.setMethod('POST');
request.setBody('{"name":"New Record"}');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 201) {
// Record created successfully
}
400 Bad Request: The server could not understand the request due to invalid syntax.
Example:
HttpResponse response = http.send(request);
if (response.getStatusCode() == 400) {
// Handle Bad Request
}
401 Unauthorized: The client must authenticate itself to get the requested response.
Example:
HttpResponse response = http.send(request);
if (response.getStatusCode() == 401) {
// Handle Unauthorized
}
403 Forbidden: The client does not have access rights to the content.
Example:
HttpResponse response = http.send(request);
if (response.getStatusCode() == 403) {
// Handle Forbidden
}
404 Not Found: The server can not find the requested resource.
Example:
HttpResponse response = http.send(request);
if (response.getStatusCode() == 404) {
// Handle Not Found
}
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
500 Internal Server Error: The server has encountered a situation it doesn't know how to
handle.
Example:
HttpResponse response = http.send(request);
if (response.getStatusCode() == 500) {
// Handle Internal Server Error
}
4. API Integration in Apex
Apex HTTP Callouts
Overview of HTTP classes (Http, HttpRequest, HttpResponse)
Http: Represents an HTTP request and response.
HttpRequest: Configures the HTTP request (e.g., setting the endpoint, method, headers).
HttpResponse: Represents the response received from the HTTP request.
Making a basic GET request
Example:
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/data');
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
String responseBody = response.getBody();
// Process the response
} else {
// Handle errors
}
-Handling responses and errors
Parse the response body and check the status code to handle errors appropriately.
Example: Fetching data from a REST API
Fetch a list of users from an external system:
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://jsonplaceholder.typicode.com/users
');
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
List<User> users = (List<User>)
JSON.deserialize(response.getBody(), List<User>.class);
// Process the list of users
} else {
// Handle errors
}
POST, PUT, DELETE Methods
Making a POST request with a JSON payload
Example:
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://jsonplaceholder.typicode.com/posts');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setBody('{"title":"foo","body":"bar","userId":1}');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 201) {
String responseBody = response.getBody();
// Process the response
} else {
// Handle errors
}
Making PUT and DELETE requests
PUT Example:
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://jsonplaceholder.typicode.com/posts/1');
request.setMethod('PUT');
request.setHeader('Content-Type', 'application/json');
request.setBody('{"id":1,"title":"foo","body":"bar","userId":1}');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
String responseBody = response.getBody();
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
// Process the response
} else {
// Handle errors
}
DELETE Example:
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://jsonplaceholder.typicode.com/posts/1');
request.setMethod('DELETE');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
// Record deleted successfully
} else {
// Handle errors
}
Handling different HTTP status codes
Explain common HTTP status codes like 200 (OK), 201 (Created), 400 (Bad Request), 401
(Unauthorized), 404 (Not Found), 500 (Internal Server Error).
Example: Creating, updating, and deleting records via API
Real-time example using a sample API to create, update, and delete records:
// POST Request to create a record
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/records');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setBody('{"name":"New Record"}');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 201) {
// Record created successfully
} else {
// Handle errors
}
// PUT Request to update a record
request.setEndpoint('https://api.example.com/records/1');
request.setMethod('PUT');
request.setBody('{"name":"Updated Record"}');
response = http.send(request);
if (response.getStatusCode() == 200) {
// Record updated successfully
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
} else {
// Handle errors
}
// DELETE Request to delete a record
request.setEndpoint('https://api.example.com/records/1');
request.setMethod('DELETE');
response = http.send(request);
if (response.getStatusCode() == 200) {
// Record deleted successfully
} else {
// Handle errors
}
Error Handling in API Callouts
Try-Catch blocks:
Example:
try {
HttpResponse response = http.send(request);
} catch (Exception e) {
// Handle exceptions
System.debug('Error: ' + e.getMessage());
}
Handling specific HTTP errors:
Example: Checking the status code and handling different error responses.
HttpResponse response = http.send(request);
Integer statusCode = response.getStatusCode();
if (statusCode == 200) {
// Success
} else if (statusCode == 400) {
// Handle Bad Request
} else if (statusCode == 401) {
// Handle Unauthorized
} else {
// Handle other errors
}
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Retrying failed requests:
Implement retry logic for transient errors (e.g., network issues).
Integer retries = 3;
while (retries > 0) {
try {
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
// Success
break;
}
} catch (Exception e) {
retries--;
if (retries == 0) {
// Log the error and exit
System.debug('Error: ' + e.getMessage());
}
}
}
Logging and monitoring API calls:
Use custom logging mechanisms to track API call activity.
try {
HttpResponse response = http.send(request);
} catch (Exception e) {
// Log the error
System.debug('Error: ' + e.getMessage());
insert new ApiCallLog(ErrorMessage=e.getMessage(),
Endpoint=request.getEndpoint());
}
5. Advanced API Integration Techniques
Batch Apex for API Callouts
Overview of Batch Apex
Batch Apex allows processing of large datasets asynchronously, ideal for making bulk API
callouts.
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Writing a batch class for API callouts
Example batch class:
global class MyBatchClass implements Database.Batchable<SObject> {
global Database.QueryLocator start(Database.BatchableContext BC)
{
return Database.getQueryLocator([SELECT Id, Name FROM
Account]);
}
global void execute(Database.BatchableContext BC, List<Account>
scope) {
Http http = new Http();
for (Account acc : scope) {
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/accounts/' +
acc.Id);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
// Process the response
} else {
// Handle errors
}
}
}
global void finish(Database.BatchableContext BC) {
// Finalize batch processing
}
}
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Handling large data volumes:
Break data into manageable chunks and process asynchronously.
Example: Batch processing of API data
Fetch data from an external system and update Salesforce records.
global class FetchAccountDataBatch implements
Database.Batchable<SObject> {
global Database.QueryLocator start(Database.BatchableContext BC)
{
return Database.getQueryLocator([SELECT Id, ExternalId__c
FROM Account]);
}
global void execute(Database.BatchableContext BC, List<Account>
scope) {
Http http = new Http();
for (Account acc : scope) {
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/accounts/' +
acc.ExternalId__c);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
Map<String, Object> accountData = (Map<String,
Object>) JSON.deserializeUntyped(response.getBody());
acc.Name = (String) accountData.get('name');
acc.Industry = (String) accountData.get('industry');
update acc;
} else {
// Handle errors
}
}
}
global void finish(Database.BatchableContext BC) {
// Finalize batch processing
}
}
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Future Methods for API Callouts
Overview of Future methods
Future methods are used for asynchronous processing, allowing API callouts without blocking
the main thread.
Writing a future method for asynchronous callouts
Example:
@future(callout=true)
public static void fetchAccountData(String accountId) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/accounts/' +
accountId);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
Map<String, Object> accountData = (Map<String, Object>)
JSON.deserializeUntyped(response.getBody());
Account acc = [SELECT Id FROM Account WHERE Id = :accountId
LIMIT 1];
acc.Name = (String) accountData.get('name');
acc.Industry = (String) accountData.get('industry');
update acc;
} else {
// Handle errors
}
}
Limits and best practices
Best practices include avoiding DML operations in loops, using appropriate governor limits,
and handling exceptions properly.
Example: Making callouts in a future method
Update Salesforce records with data from an external API asynchronously.
public class AccountService {
@future(callout=true)
public static void updateAccountIndustry(String accountId) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/accounts/' +
accountId);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Map<String, Object> accountData = (Map<String, Object>)
JSON.deserializeUntyped(response.getBody());
Account acc = [SELECT Id FROM Account WHERE Id
= :accountId LIMIT 1];
acc.Industry = (String) accountData.get('industry');
update acc;
} else {
// Handle errors
}
}
}
Queueable Apex for API Callouts
Overview of Queueable Apex
Queueable Apex provides more flexibility than future methods and allows job chaining and monitoring.
Writing a Queueable class for API callouts
Example:
public class AccountUpdateQueueable implements Queueable {
private String accountId;
public AccountUpdateQueueable(String accountId) {
this.accountId = accountId;
}
public void execute(QueueableContext context) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/accounts/' +
accountId);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
Map<String, Object> accountData = (Map<String, Object>)
JSON.deserializeUntyped(response.getBody());
Account acc = [SELECT Id FROM Account WHERE Id
= :accountId LIMIT 1];
acc.Name = (String) accountData.get('name');
acc.Industry = (String) accountData.get('industry');
update acc;
} else {
// Handle errors
}
}
}
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Chaining Queueable jobs
Example:
public class AccountUpdateQueueable implements Queueable {
private String accountId;
public AccountUpdateQueueable(String accountId) {
this.accountId = accountId;
}
public void execute(QueueableContext context) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/accounts/' +
accountId);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
Map<String, Object> accountData = (Map<String, Object>)
JSON.deserializeUntyped(response.getBody());
Account acc = [SELECT Id FROM Account WHERE Id
= :accountId LIMIT 1];
acc.Name = (String) accountData.get('name');
acc.Industry = (String) accountData.get('industry');
update acc;
// Chain another Queueable job
System.enqueueJob(new AnotherQueueableJob(acc.Id));
} else {
// Handle errors
}
}
}
Example: Using Queueable Apex for API integration
Demonstrate using Queueable Apex to update multiple Salesforce records in sequence.
public class AccountUpdateQueueable implements Queueable {
private List<String> accountIds;
public AccountUpdateQueueable(List<String> accountIds) {
this.accountIds = accountIds;
}
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
public void execute(QueueableContext context) {
for (String accountId : accountIds) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/accounts/' +
accountId);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
Map<String, Object> accountData = (Map<String,
Object>) JSON.deserializeUntyped(response.getBody());
Account acc = [SELECT Id FROM Account WHERE Id
= :accountId LIMIT 1];
acc.Name = (String) accountData.get('name');
acc.Industry = (String) accountData.get('industry');
update acc;
} else {
// Handle errors
}
}
}
}
// Usage
List<String> accountIds = new List<String>{'001xxxxxxxxxxxx',
'002xxxxxxxxxxxx'};
System.enqueueJob(new AccountUpdateQueueable(accountIds));
Scheduled Apex for Regular API Callouts
Overview of Scheduled Apex:
Scheduled Apex allows you to schedule Apex classes to run at specific times.
Writing a scheduled Apex class for API callouts:
Example:
public class AccountDataScheduler implements Schedulable {
public void execute(SchedulableContext context) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/accounts');
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
List<Account> accounts = (List<Account>)
JSON.deserialize(response.getBody(), List<Account>.class);
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
for (Account acc : accounts) {
// Process and update Salesforce records
}
} else {
// Handle errors
}
}
}
// Schedule the class to run every day at midnight
String cronExpression = '0 0 0 * * ?';
System.schedule('Account Data Sync', cronExpression, new
AccountDataScheduler());
Setting up scheduled jobs in Salesforce
Schedule the class using the System.schedule method with a CRON expression.
Example: Automating daily data synchronization with an external API
Demonstrate scheduling a job to run daily and synchronize data with an external system.
public class DailyAccountSync implements Schedulable {
public void execute(SchedulableContext context) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://api.example.com/daily-accounts-
sync');
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
List<Account> accounts = (List<Account>)
JSON.deserialize(response.getBody(), List<Account>.class);
for (Account acc : accounts) {
// Process and update Salesforce records
}
} else {
// Handle errors
}
}
}
// Schedule the class to run every day at 2 AM
String cronExpression = '0 0 2 * * ?';
System.schedule('Daily Account Sync', cronExpression, new
DailyAccountSync());
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
6. Best Practices and Tips
Security Considerations:
Protecting API keys and credentials
Use named credentials or encrypted custom settings to store sensitive information.
Enforcing IP whitelisting
Restrict API access to specific IP ranges for enhanced security.
Using OAuth for secure authentication
Prefer OAuth over basic authentication for secure and standardized access.
Handling API Limits and Quotas:
Understanding Salesforce API limits
Familiarize yourself with Salesforce's API usage limits to avoid hitting governor limits.
Implementing rate limiting strategies
Implement backoff strategies and rate-limiting mechanisms to handle API quotas gracefully.
Using Bulk API for large data operations
Use Bulk API for high-volume data operations to optimize performance and stay within limits.
Optimizing Performance:
Caching responses
Cache responses where possible to reduce redundant API calls and improve performance.
Minimizing API callouts
Reduce the number of API callouts by batching requests or using efficient data retrieval
methods.
Using asynchronous processing
Offload long-running tasks to asynchronous processes like Batch Apex, Future methods, or
Queueable Apex.
https://www.linkedin.com/in/iam-murali/
API Integration in Salesforce
Example: Implementing security measures and performance optimizations
Named Credential Setup:
// Create a named credential in Salesforce for API authentication
// Navigate to Setup -> Named Credentials -> New Named Credential
// Fill in the details and save
Caching API Responses:
// Example of caching an API response
public class ApiCache {
private static Map<String, String> cache = new Map<String,
String>();
public static String getCachedResponse(String key) {
if (cache.containsKey(key)) {
return cache.get(key);
}
return null;
}
public static void cacheResponse(String key, String response) {
cache.put(key, response);
}
}
// Usage
String key = 'https://api.example.com/data';
String cachedResponse = ApiCache.getCachedResponse(key);
if (cachedResponse == null) {
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(key);
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
cachedResponse = response.getBody();
ApiCache.cacheResponse(key, cachedResponse);
}
}
https://www.linkedin.com/in/iam-murali/