To consume REST services there is a lot of boilerplate code needed:

  1. Build Apex Objects to model the responses
  2. Code to deserialize REST responses to those classes
  3. Handling of HTTP requests, responses and errors
  4. ...

Did anyone come up with patterns or best practices codified into an open source library or framework that one could just reuse in a similar project without reinventing the callout-wheel over an over again?

Like the zillions of trigger-frameworks that exist as repos on Github...


The ffhttp library should do the trick: https://github.com/financialforcedev/ffhttp-core

It includes error handling, redirections, building header fields, oauth, mime attachments and more.

EDIT - Sample code

Say you want to consume the JSONPlaceholder /users rest resource. You could create a Named Credential for the URL.

JSONPlaceholder named credential

Then you can use ffhttp to make the request, handle the failure or successful response and deserialize into the intended format. FFHTTP only includes an OAuth client but it's pretty simple to create your own...

public with sharing class ffhttpSample {

    * DTO for remote object result
    private class RemoteUser {
        Integer id;
        String name;
        String username;
        String email;

    * Vanilla HTTP request
    public static RemoteUser[] getUsers() {
        Http http = new Http();

        HttpRequest request = new HttpRequest();

        HttpResponse response = http.send(request);        
        if (response.getStatusCode() == 200) {
            return (RemoteUser[])JSON.deserialize(response.getBody(), List<RemoteUser>.class);
        } else {
            return new RemoteUser[]{};

    * FFHTTP request
    public static RemoteUser[] getUsersFfhttp() {
        SimpleClient client = new SimpleClient();
        client.setCredentials(new ffhttp_Client.NamedCredentials('JSONPlaceholder'));

        SimpleClientRequest request = new SimpleClientRequest(
            new ffhttp_JsonDeserializer(List<RemoteUser>.class));

        // Execute and parse the response.
        // Alternatively you can use executeUnparsed() to return the response body as a String
        return (RemoteUser[])request.execute();

    * FFHTTP client implementations
    private class SimpleClient extends ffhttp_Client.AbstractClient {}
    private class SimpleClientRequest extends ffhttp_Client.AbstractClientRequest {
        SimpleClientRequest(IAbstractClient client, String endpoint, String requestMethod, ffhttp_IDeserialize deserializer) {
            super(client, endpoint, requestMethod, null, deserializer);
  • 2
    Awesome. Actually a fully sufficient answer but I will leave it open to invite more people to share. Apr 3 '19 at 20:59
  • would you mind adding a few snippets intro your answer outlining how to use the library? How it handles certain aspects of REST consumption, de/serializing responses and such. I checked the repo and also the specific repos using this but its still somewhat hard to grasp the core concepts. But.. I have no doubt that it is like the fflib the best thing out there... (I would grant a big bounty to you for that in case you care about some SFSE points ;-) Apr 4 '19 at 20:53
  • I couldn't find an example on how to correctly test such a RESTClien implementation build on the lib. Regarding mocks and support of testing by the lib... Is there any class you can point me to? Jul 1 '19 at 8:19

There is a new open source framework for simplifying HTTP Callouts in apex. This framework can be deployed to any salesforce org by click of a button and has some great features like:-

  1. All the callout information is configurable using custom metadata.
  2. You don't have to define different mock classes for test coverage of each callout. There is a pre defined generalized mock class that you can use.
  3. Named credentials are supported.
  4. Asynchronous callouts are very easy to implement in VF Pages as well as in lightning components.
  5. Test coverage for request and responses are covered automatically.

For example, I have made a dry api at:- https://sfdcstop.herokuapp.com/blogs which gives us a simple JSON response similar to the one as shown below:-

  "author": "Rahul Malhotra",
  "blogs": [
      "id": "1",
      "title": "Salesforce Integration Tutorial Part 1 - Introduction and Setting up Workbench",
      "url": "https://www.sfdcstop.com/2019/11/salesforce-integration-tutorial-part-1.html"
      "id": "2",
      "title": "Salesforce Integration Tutorial Part 2 - Exploring GET Method",
      "url": "https://www.sfdcstop.com/2019/11/salesforce-integration-tutorial-part-2.html"

So, once I have installed the framework in my org. To hit this API from Salesforce, I simply created a remote site setting record:-

Remote Site Setting Record for SFDCStop API

And I created a record of my HTTPCalloutConfiguration metadata as shown below:-

SFDCStop callout metadata

You can see above that my metadata has a name SFDCStopBlogs and I have specified all the necessary information that I need for my callout in my metadata record like:- Request method, Endpoint URL, Header parameters, URL parameters, Request body, Timeout etc.

And that's it. In order to call my API, I can simply execute a single line of code in my developer console like:-

HttpCalloutService service = new HTTPCalloutService('SFDCStopBlogs');

So, I just created an instance of my HTTPCalloutService class, passed the metadata name in the constructor and added some debug statements in which the first debug is printing the request and inside the second debug, we're sending the request and returning the response body which is printed. Once, you'll execute this statement, salesforce will perform a callout using the framework and you'll get an output as shown below:-

SFDC Stop API Response

As you can see above we're getting a successful response from the API. So, that's how you can very easily setup a callout from salesforce using HTTPCalloutFramework. To know more or install the framework you can checkout the github repository here:- https://github.com/rahulmalhotra/HTTPCalloutFramework

Hope It helps :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.