function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Natasha AliNatasha Ali 

Exposing Data through REST API

Hi,
I need to expose certain Salesforce Data to a third party app that doesn't have a ready-made Salesforce integration. I'm going to use REST API to expose the data and this action will be triggered when a status changes. 

Here is the general process of what should happen 
1. User changes status which triggers the API
2. API call made to an external app and Salesforce Data is exposed, ready to be consumed
3. External App consumes data 

I'm struggling to understand what would I need to ask from the third part? and is there anything else I would need to do?

Any help is much appreciated :)
Many Thanks,
Natasha 


 

Best Answer chosen by Natasha Ali
Adilson Arcoverde JrAdilson Arcoverde Jr
Hi Natasha,

In this case you want to expose a REST API and then you have to code a class with @RestResource annotation.

Check this example:
 
@RestResource(urlMapping='/myserviceendpoint/*')
global with sharing class MyRestService  {

    @HttpGet
    global static void doGet() {
        String result = '';
        RestRequest request = RestContext.request;
        String accountId = request.requestURI.substringAfter( '/myserviceendpoint/' );
        List<Account> accs = [Select Id, Status__c from Account where Id = :accountId LIMIT 1];
        if( accs.size() > 0 ) {
            Account acc = accs[0];
            Map<String,String> resultMap = new Map<String,String> {
                'accountId' => acc.Id,
                'accountStatus' => acc.Status__c
            };

            result = JSON.serialize( resultMap );
        } else {
            result = 'Account with ID ' + accountId + ' not found!';
        }

        RestContext.response.addHeader('Content-Type','application/json');
        RestContext.response.responseBody = Blob.valueOf(result);
    }

    @HttpPost
    global static void doPost() {
        // Add your logic here if you want implement POST method.
    }    
}

So, your third party API will call Salesforce service using https://<your_instance_url>/services/apexrest/myserviceendpoint/<account_id>.

Also, it is necessary to send the Bearer (Salesforce auth) inside the request headers using this format:
'Authorization','Bearer <access_token>

The session ID may be requested using the endpoint https://login.salesforce.com/services/oauth2/token. There are some OAuth2 flows like web flow and password flow. You'll find some guidance here (https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_web_server_oauth_flow.htm).

Regards.

All Answers

Adilson Arcoverde JrAdilson Arcoverde Jr
Hi Natasha,

First of all, you need to get the integration contract. This means you need to understand the data exchange format.

REST API usually user JSON format. Suppose you have an API to change an account status on your legacy system. One integration contract may be:
 
{
    "accountId", "12341231",
    "accountStatus", "Hot"
}

That said, we can move to next step. "User changes status which triggers the API". You'll need to have inside your object trigger (Account in this example) a future method witch callout=true annotation. For example:
 
trigger AccountTrigger on Account (after update) {
    if( Trigger.isAfter && Trigger.isUpdate ) {
        for( Account acc : Trigger.new ) {
            if( acc.Status__c != null && acc.Status__c != Trigger.oldMap.get(acc.Id).Status__c ) {
                sendToLegacy( acc.External_ID_Field__c, acc.Status__c );
            }
        }
    }

    @future(callout=true)
    public void sendToLegacy( String externalId, String status ) {
        Http h = new Http();

        Map<String,String> bodyMap = new Map<String,String> {
            'accountId' => externalId,
            'accountStatus' => status
        };


        HttpRequest request = new HttpRequest();
        request.setEndpoint('<your_api_endpoint_here');
        request.setMethod('<your_api_method>');
        request.setTimeout(120000); // This is the maximum timeout allowed by apex
        request.setBody( JSON.serialize(bodyMap) );

        Map<String,String> headers = new Map<String,String>(); // add headers if applicable
        for( String header : headers.keySet() ) {
            request.setHeader(header, headers.get(header));
        }

        HttpResponse response =  h.send(request);
        // Handle response value
    }
}

Your third-party API should be able (since you got integration contract from them) to process your request.

Let me know if you have any doubts.

Hope you find this solution useful. If it does please mark as Best Answer to help others too.

Regards.
 
Natasha AliNatasha Ali
Hi Adilson, 
Thank you for your prompt response :) 

I'm quite new to dev and the only instructions we got from the third party is that we need to expose data for them to consume it. The user would trigger the callout when the status changes, then the information on that record would be exposed ready to be used.
Just to clarify, I'd need to write a trigger which invokes a REST web service method? Would it be how you've written it above?

Many Thanks!!
Natasha 
Adilson Arcoverde JrAdilson Arcoverde Jr
Hi Natasha,

In this case you want to expose a REST API and then you have to code a class with @RestResource annotation.

Check this example:
 
@RestResource(urlMapping='/myserviceendpoint/*')
global with sharing class MyRestService  {

    @HttpGet
    global static void doGet() {
        String result = '';
        RestRequest request = RestContext.request;
        String accountId = request.requestURI.substringAfter( '/myserviceendpoint/' );
        List<Account> accs = [Select Id, Status__c from Account where Id = :accountId LIMIT 1];
        if( accs.size() > 0 ) {
            Account acc = accs[0];
            Map<String,String> resultMap = new Map<String,String> {
                'accountId' => acc.Id,
                'accountStatus' => acc.Status__c
            };

            result = JSON.serialize( resultMap );
        } else {
            result = 'Account with ID ' + accountId + ' not found!';
        }

        RestContext.response.addHeader('Content-Type','application/json');
        RestContext.response.responseBody = Blob.valueOf(result);
    }

    @HttpPost
    global static void doPost() {
        // Add your logic here if you want implement POST method.
    }    
}

So, your third party API will call Salesforce service using https://<your_instance_url>/services/apexrest/myserviceendpoint/<account_id>.

Also, it is necessary to send the Bearer (Salesforce auth) inside the request headers using this format:
'Authorization','Bearer <access_token>

The session ID may be requested using the endpoint https://login.salesforce.com/services/oauth2/token. There are some OAuth2 flows like web flow and password flow. You'll find some guidance here (https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_web_server_oauth_flow.htm).

Regards.
This was selected as the best answer