Connect Salesforce to any API with Process Builder or Flow Builder (Free Generic APEX Code)
This document is deprecated, move to https://munawirrahman.medium.com/mini-postman-with-invocablecallout-apex-action-in-salesforce-flow-95f63ff3229f
These days, you can connect your Salesforce Org to any API in the world with API Callout method using APEX Class. But sometimes, it can be pain in the ass because we have to hardcode the URL Endpoint, Headers, Body, etc and also have to create the trigger and handler using another APEX Class. So in this article, I would like to share my Generic APEX Code that can be used in your org and can be called via Process Builder or Flow Builder using Invocable Method.
The use case of this article would be the same with this Trailhead course . Which I will only use the GET Method and using the same endpoint. (https://th-apex-http-callout.herokuapp.com/animals)
a. Create a new APEX Class and Copy and Paste this code (This code can be used for POST (with JSON), GET (with query string), DELETE (with query string). And you can define whether you want to Asynchronous or Synchronous the request.
public class GenericAPICaller {public class ToSend {
@InvocableVariable(label='Payload Template')
public String payloadTemplate;
@InvocableVariable(label='HTTP Method' required=true)
public String httpMethod;
@InvocableVariable(label='URL' required=true)
public String url;
@InvocableVariable(label='Asynchronous')
public Boolean async;
@InvocableVariable(label='Timeout in milliseconds')
public Integer timeout;
@InvocableVariable(label='Header1 Name')
public String header1Name;
@InvocableVariable(label='Header1 Value')
public String header1Value;
@InvocableVariable(label='Header2 Name')
public String header2Name;
@InvocableVariable(label='Header2 Value')
public String header2Value;
@InvocableVariable(label='Name1 String')
public String name1String;
@InvocableVariable(label='Name2 String')
public String name2String;
@InvocableVariable(label='Name3 String')
public String name3String;
@InvocableVariable(label='Name4 String')
public String name4String;
@InvocableVariable(label='Name5 String')
public String name5String;
@InvocableVariable(label='Name6 String')
public String name6String;
@InvocableVariable(label='Name7 String')
public String name7String;
@InvocableVariable(label='Name8 String')
public String name8String;
@InvocableVariable(label='Name9 String')
public String name9String;
@InvocableVariable(label='Name10 String')
public String name10String;
@InvocableVariable(label='Name11 String')
public String name11String;
@InvocableVariable(label='Name12 String')
public String name12String;
@InvocableVariable(label='Name13 String')
public String name13String;
@InvocableVariable(label='Name14 String')
public String name14String;
@InvocableVariable(label='Name15 String')
public String name15String;
@InvocableVariable(label='Name16 String')
public String name16String;
@InvocableVariable(label='Name17 String')
public String name17String;
@InvocableVariable(label='Name18 String')
public String name18String;
@InvocableVariable(label='Name19 String')
public String name19String;
@InvocableVariable(label='Name20 String')
public String name20String;
@InvocableVariable(label='Value1 String')
public String value1String;
@InvocableVariable(label='Value2 String')
public String value2String;
@InvocableVariable(label='Value3 String')
public String value3String;
@InvocableVariable(label='Value4 String')
public String value4String;
@InvocableVariable(label='Value5 String')
public String value5String;
@InvocableVariable(label='Value6 String')
public String value6String;
@InvocableVariable(label='Value7 String')
public String value7String;
@InvocableVariable(label='Value8 String')
public String value8String;
@InvocableVariable(label='Value9 String')
public String value9String;
@InvocableVariable(label='Value10 String')
public String value10String;
@InvocableVariable(label='Value11 String')
public String value11String;
@InvocableVariable(label='Value12 String')
public String value12String;
@InvocableVariable(label='Value13 String')
public String value13String;
@InvocableVariable(label='Value14 String')
public String value14String;
@InvocableVariable(label='Value15 String')
public String value15String;
@InvocableVariable(label='Value16 String')
public String value16String;
@InvocableVariable(label='Value17 String')
public String value17String;
@InvocableVariable(label='Value18 String')
public String value18String;
@InvocableVariable(label='Value19 String')
public String value19String;
@InvocableVariable(label='Value20 String')
public String value20String;
@InvocableVariable(label='QueryString1 String')
public String queryString1;
@InvocableVariable(label='QueryString2 String')
public String queryString2;
public Boolean sandbox;
}
public static String apexCallOutEngine(String JSONString) {
ToSend toSend = ((ToSend)JSON.deserialize(JSONString, ToSend.class));
String url = toSend.url;
String httpMethod = toSend.httpMethod;
Integer timeout = toSend.timeout;
Http h = new Http();
HttpRequest hr = new HttpRequest();
HttpResponse resp = new HttpResponse();
if (toSend.header1Name!=null && toSend.header1Value!=null) { hr.setHeader(toSend.header1Name, toSend.header1Value); }
if (toSend.header2Name!=null && toSend.header2Value!=null) { hr.setHeader(toSend.header2Name, toSend.header2Value); }if (toSend.queryString1!=null) {
url = url.replace('{queryString1}',EncodingUtil.urlEncode(toSend.queryString1,'UTF-8'));
}
if (toSend.queryString2!=null) {
url = url.replace('{queryString2}',EncodingUtil.urlEncode(toSend.queryString2,'UTF-8'));
}
if (toSend.timeout==null) {
hr.setTimeout(10000);
} else {
hr.setTimeout(timeout);
}
if ('GET'.equalsIgnoreCase(httpMethod)) {
hr.setMethod('GET');
if(toSend.name1String != null && toSend.value1String != null && toSend.name1String.length()>0) {
url = url + '?'+EncodingUtil.urlEncode(toSend.name1String,'UTF-8')+'='+EncodingUtil.urlEncode(toSend.value1String,'UTF-8');
}
if(toSend.name2String != null && toSend.value2String != null && toSend.name2String.length()>0) {
url = url + '&'+EncodingUtil.urlEncode(toSend.name2String,'UTF-8')+'='+EncodingUtil.urlEncode(toSend.value2String,'UTF-8');
}
if(toSend.name3String != null && toSend.value3String != null && toSend.name3String.length()>0) {
url = url + '&'+EncodingUtil.urlEncode(toSend.name3String,'UTF-8')+'='+EncodingUtil.urlEncode(toSend.value3String,'UTF-8');
}
if(toSend.name4String != null && toSend.value4String != null && toSend.name4String.length()>0) {
url = url + '&'+EncodingUtil.urlEncode(toSend.name4String,'UTF-8')+'='+EncodingUtil.urlEncode(toSend.value4String,'UTF-8');
}
if(toSend.name5String != null && toSend.value5String != null && toSend.name5String.length()>0) {
url = url + '&'+EncodingUtil.urlEncode(toSend.name5String,'UTF-8')+'='+EncodingUtil.urlEncode(toSend.value5String,'UTF-8');
}
hr.setEndpoint(url);
System.debug('Hit GET with URL: ' + url);
} else
if ('POST'.equalsIgnoreCase(httpMethod)) {
hr.setMethod('POST');
String template = toSend.payloadTemplate;
if (template != null) {
template = template.replace('~'+toSend.name1String+'~','"'+toSend.value1String+'"');
template = template.replace('~'+toSend.name2String+'~','"'+toSend.value2String+'"');
template = template.replace('~'+toSend.name3String+'~','"'+toSend.value2String+'"');
template = template.replace('~'+toSend.name4String+'~','"'+toSend.value2String+'"');
template = template.replace('~'+toSend.name5String+'~','"'+toSend.value2String+'"');
hr.setBody(template);
}
hr.setEndpoint(url);
hr.setHeader('Content-Type', 'application/json');
System.debug('Hit POST with URL: '+url+' JSON: ' + template);
} else
if ('DELETE'.equalsIgnoreCase(httpMethod)) {
hr.setMethod('DELETE');
hr.setEndpoint(url);
System.debug('Hit DELETE with URL: '+url);
}
try {
resp = h.send(hr);
System.debug('Response code: '+resp.getStatusCode());
String body = resp.getBody();
if (body==null) { body = ''; }
String result = '{"http_status_code": '+resp.getStatusCode()+' , "data":'+body+'}';
System.debug('Response: '+result);
return result;
} catch (Exception e) {
System.debug('Callout Error:' + e.getMessage());
}
return null;
}
@future(Callout=true)
public static void apexcallout(String JSONString) {
apexCallOutEngine(JSONString);
return;
}public static Boolean isSandbox() {
Organization organization = [select Id, IsSandbox from Organization limit 1];
if (organization.IsSandbox) {
System.debug('This is Sandbox');
}
else
{
System.debug('This is Production');
}
return organization.IsSandbox;
}
@InvocableMethod(label='Send Generic Data by API call' description='Send Generic Data by API call')
public static List<String> process(List<ToSend> toSends) {
List<String> results = new List<String>();
for (ToSend toSend: toSends) {
toSend.sandbox = isSandbox();
String JSONString = JSON.serialize(toSend);
String result = null;
if (toSend.async == true) {
apexcallout(JSONString);
} else {
result = apexCallOutEngine(JSONString);
}
results.add(result);
}
return results;
}
}
b. Whitelist the endpoint in your Salesforce Org (Setup -> Remote Site Settings -> New Remote Site)
c. Design a new Flow to call the Class (Setup-> Flows -> New Flow)
d. There you go, now you can do API connection to any Endpoint in this world without have to re-write the apex code.
Enjoy, and let me know if you need anything else related to this article in the comment section.