Rest Integration in Salesforce
Consuming REST API
We are going to use this website : https://reqres.in/ to test out API consumption from Salesforce. This website is really useful to test out sample endpoints which let you test out API consumption.
Using Postman
Before we can consume the APIs in Salesforce, we can use Postman to test APIs before implementing it in salesforce.
Postman can be installed in all the systems and it allows you to call out to any third parties.
The above example is sending out a GET request to the https://reqres.in/ endpoint. Similarly we can send a POST request to the https://reqres.in/ endpoint too, with specifying the JSON body in the request via Postman too.
HTTP Classes in Salesforce
We can use the HTTPRequest and HTTPResponse classes in salesforce to consume any third party REST APIs.
Let’s say we want to connect to this endpoint : https://reqres.in/api/users/2 with the GET method, we can do that by apex like this :
HttpRequest req = new HttpRequest(); Http http = new Http(); req.setEndpoint('https://reqres.in/api/users/2'); req.setMethod('GET'); req.setTimeout(120000); HttpResponse res = http.send(req);
The Http class is used to send the request to the endpoint. The setTimeout method is used to set the maximum time that the system will wait for a response from the external system.
NOTE : The maximum value possible in the timeout is 120 seconds in salesforce. The setTimeout function accepts value in milliseconds so the max value possible is 120000.
The GET method doesn’t accept any body to be sent in the request, but in the POST method we can send a body in the request like this,
HttpRequest req = new HttpRequest(); HttpResponse res = new HttpResponse(); Http http = new Http(); req.setHeader('Content-Type','application/json;charset=UTF-8'); req.setEndpoint('https://reqres.in/api/users'); req.setMethod('POST'); String body = '{ "name" : "' + name + '" , "job" : "' + job + '"}'; req.setBody(body); // Increase timeout value req.setTimeout(120000); res = http.send(req); String responseJSON = res.getBody();
We are setting the body in the JSON format using the setBody() method. And then the response we receive back can be stored in a string variable by using the getBody() method.
Here is the complete apex class implementing this functionality :
public class WebserviceConsumer { public static void consumeGet() { HttpRequest req = new HttpRequest(); HttpResponse res = new HttpResponse(); Http http = new Http(); req.setEndpoint('https://reqres.in/api/users/2'); req.setMethod('GET'); // Increase timeout value req.setTimeout(120000); res = http.send(req); system.debug(res.getBody()); } // Constructing JSON body dynamically public static void consumePost(String name,String job) { HttpRequest req = new HttpRequest(); HttpResponse res = new HttpResponse(); Http http = new Http(); req.setHeader('Content-Type','application/json;charset=UTF-8'); req.setEndpoint('https://reqres.in/api/users'); req.setMethod('POST'); String body = '{ "name" : "' + name + '" , "job" : "' + job + '"}'; req.setBody(body); // Increase timeout value req.setTimeout(120000); res = http.send(req); system.debug(res.getBody()); String responseJSON = res.getBody(); } }
Output response for both GET and POST requests :
{"data":{"id":2,"email":"janet.weaver@reqres.in","first_name":"Janet","last_name":"Weaver","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"},"ad":{"company":"StatusCode Weekly","url":"http://statuscode.org/","text":"A weekly newsletter focusing on software development, infrastructure, the server, performance, and the stack end of things."}}
Exposing REST API
Connected App
An important step before we can expose any functionality from our salesforce org for outside systems is to create a connected app in salesforce. This connected App will provide a way for an external non-salesforce system to authenticate with salesforce.
Go to Setup-> Apps -> Connected Apps and click on New
Enter the details and check the Enable OAuth Settings since it is required and set up the authorisation settings.
The different OAuth scopes dictate what level of access and permissions will the user have when they use this connected app to authenticate.
The callback url is used for re-direction of the user once they have authenticated successfully.
Once created, the connected app will give you a client id and client secret. These then can be used along with your salesforce username and password to authenticate with the salesforce system.
Once we have all this data we can make a POST request from any external system using these parameters like this (using Postman as example) :
If successful, you will see a response like this :
{ "access_token": "00DR00000008oBT!AQwAQCPqzc_HBE59c80QmEJD4rQKRRc1GRLvYZEq...", "instance_url": "https://na1.salesforce.com", "id": "https://login.salesforce.com/id/00DR00000008oBTMAY/005R0000000IUUMIA4", "token_type": "Bearer", "issued_at": "1513887500425", "signature": "3PiFUIioqKkHpHxUiCCDzpvSiM2F6//w2/CslNTuf+o=" }
We can use the access_token returned in the response to call out to any salesforce APIs.
@RestResource Classes
In order to expose any custom functionality from salesforce to external systems, we need to use the @RestResource notation.
Here is an example :
@RestResource(urlMapping = '/firstwebservice/*') global class MyFirstWebservice { @HttpGet global static list getAccounts () { list accList = [SELECT Id, Name FROM Account]; return accList; } @HttpPost global static list findAccounts (InputWrapper wrap) { list accList = [SELECT Id, Name FROM Account WHERE Id =: wrap.accId OR Name =: wrap.name]; return accList; } global class InputWrapper { global String accId; global String name; } }
The urlMapping = ‘/firstwebservice/* statement will bind this apex class to a particular endpoint and then you can define a method for each http method with the @HttpGet, @HttpPost methods which correspond to the GET and POST method respectively.
Then we should be able to call this service from Postman like this :
Here the access token is the one which we got in the connected app authorisation, which will be needed to be used here to call the API in salesforce.
This will return us the response like this in Postman :
[ { "attributes" : { "type" : "Account", "url" : "/services/data/v48.0/sobjects/Account/0012w0000053llHAAQ" }, "Id" : "0012w0000053llHAAQ", "Name" : "TsysUpdatedUpdated" }, { "attributes" : { "type" : "Account", "url" : "/services/data/v48.0/sobjects/Account/0012w000008tLVdAAM" }, "Id" : "0012w000008tLVdAAM", "Name" : "SFDC" }, { "attributes" : { "type" : "Account", "url" : "/services/data/v48.0/sobjects/Account/0012w000006XopFAAS" }, "Id" : "0012w000006XopFAAS", "Name" : "queueable job" } ]
We can also use the REST Explorer tool in Workbench to test our APIs :
You can find this tool after logging into workbench by going to Utilities -> Rest Explorer.
The output returned for the request will be like this :
[ { "attributes" : { "type" : "Account", "url" : "/services/data/v48.0/sobjects/Account/0012w0000053llHAAQ" }, "Id" : "0012w0000053llHAAQ", "Name" : "TsysUpdatedUpdated" }, { "attributes" : { "type" : "Account", "url" : "/services/data/v48.0/sobjects/Account/0012w000008tLVdAAM" }, "Id" : "0012w000008tLVdAAM", "Name" : "SFDC" }, { "attributes" : { "type" : "Account", "url" : "/services/data/v48.0/sobjects/Account/0012w000006XopFAAS" }, "Id" : "0012w000006XopFAAS", "Name" : "queueable job" }]