Salesforce DML Before and After Callout

In Salesforce, when making a callout (an external API request), you must carefully handle DML(Data Manipulation Language) operations due to governor limits and transaction restrictions.

In this tutorial, we will learn about Salesforce DML before and after a callout. In that, I will explain what a callout in Salesforce is and why DML before a callout is not allowed. After that, we will see how to use DML before and after callout with real-time scenarios and step-by-step explanations.

What is a Callout in Salesforce?

A callout is a request made from Salesforce to an external system via protocols like HTTP, REST, or SOAP to fetch or send data. Callouts are essential for integrating Salesforce with external systems such as payment gateways, third-party APIs, or other cloud services.

DML Before Callout in Salesforce

Salesforce does not allow DML operations before a callout in the same transaction. This restriction ensures that the external callout is successful before making any database changes, thus preventing data inconsistency.

Why is DML Before Callout Not Allowed?

If DML operations were allowed before a callout and the callout failed, Salesforce would have already committed the DML operation, leading to partial data updates. To maintain data integrity, Salesforce enforces this rule.

Example: Salesforce DML Before Callout (Incorrect Approach)

In the below Apex code, we performed the DML operation before calling the external application. As we execute this code, we will get an error. We cannot perform a DML operation before the callout.

public class Demo {   
    public static void makeCallout() {
        
        Account acc = new Account(Name = 'Test Account');
        insert acc;  
        
        HttpRequest request = new HttpRequest();

        request.setEndpoint('https://https://api.example.com/data');
        request.setMethod('GET');
        Http http = new Http();
        HttpResponse response = http.send(request);
    }
}

The System.CalloutException: You have uncommitted work pending. An error in Salesforce occurs when you attempt to make an HTTP callout (external API request) after performing DML operations within the same transaction without committing to or rolling back the database changes.

Salesforce DML Before and After Callout

Use Future Method For DML After Callout in Salesforce

Performing DML operations after a callout is allowed and ensures that data is updated only when the callout succeeds. For that, we always check the callout response status before performing DML operations and use try-catch blocks to handle exceptions.

Also, Salesforce does not allow DML after a callout in the same transaction. For that, we need to move the DML operation to a future method, which runs in a separate transaction.

This Apex class contains a future method that performs a callout to an external API to fetch and update a credit score for a given Account in Salesforce.

@Future(callout=true) annotation is used to execute the method in the background. It is required when making callouts (HTTP requests to external systems) from Salesforce. The method constructs an HttpRequest to fetch data from ‘HTTP://api.example.com/data’ + accountID using an HTTP GET request. The response is expected to contain the credit score from the provided account ID.

getStatusCode() retrieves the HTTP response code. 200 means “OK”, indicating the API request was successful. If the condition is true, it means we received a valid response, and we proceed to extract the credit score.

response.getBody() retrieves the body of the HTTP response. The response body is expected to contain the credit score as a number in string format (e.g., “750”). Integer.valueOf(response.getBody()) is used to convert the response body (a string) into an integer.

After that, we wrote a SOQL query to fetch the account information with the provided account ID, and then, using the UPDATE DML operation, we updated the account record.

public class Demo {   
@Future(callout=true)
    public static void updateCreditScore (Id accountId) {

        Http http = new Http();
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint( 'https://api.example.com/data' + accountId);
        req.setMethod('GET');

        HttpResponse response = http.send(req);
        
        if (response.getStatusCode() == 200) {
            Integer creditScore = Integer.valueOf(response.getBody());

            Account acc = [SELECT Id, Name FROM Account WHERE Id = :accountId];
            acc.Customer_Credit_Score__c = creditScore;
            update acc;
        }
    }
} 

In this way, we can use a DML operation after a callout in Salesforce to update records in the org.

Use Queueable Apex For DML After Callout in Salesforce

In Salesforce, a callout is used to interact with external systems via HTTP requests (REST/SOAP APIs), while DML operations are used to insert, update, delete, or upsert records in the Salesforce database.

Salesforce does not allow performing DML operations after a callout in a synchronous transaction, but queueable Apex provides a way to bypass this restriction.

In the below queueable Apex class, which implements the Queueable and Database.AllowsCallouts interfaces allow performing both an HTTP callout and a DML operation in the same transaction.

Inside the execute() method, an HTTP request is sent to https://api.example.com/data (external API) using a GET method. The response from the external API is checked for a 200 (success) status code. If successful, a new account record named “New Account from API” is inserted into Salesforce. If the callout fails, a debug log prints the failure message.

public class CalloutAndDMLQueueable implements Queueable, Database.AllowsCallouts {
    public void execute(QueueableContext context) {

        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) {
            Account acc = new Account(Name = 'New Account from API');
            insert acc;
        } else {
            System.debug('API Callout Failed: ' + response.getBody());
        }
    }
}

In this way, we can also use the queueable apex class for DML operations after a callout in Salesforce to insert records in the org.

Conclusion

I hope you have an idea about Salesforce DML before and after callout. In that, I have explained what a callout in Salesforce is and why DML before a callout is not allowed. After that, we have seen how to use DML before and after callout with real-time scenarios and step-by-step explanations.

You may like to read:

Agentforce in Salesforce

DOWNLOAD FREE AGENTFORCE EBOOK

Start with AgentForce in Salesforce. Create your first agent and deploy to your Salesforce Org.

Salesforce flows complete guide

FREE SALESFORCE FLOW EBOOK

Learn how to work with flows in Salesforce with 5 different real time examples.