HTTP Callouts from Triggers?

HTTP Callouts from Triggers?

On August 1, 2025, Posted by , In Apex,Salesforce Technical Questions, With Comments Off on HTTP Callouts from Triggers?
HTTP Callouts from Triggers

Question

I have a trigger on a custom object that calls a class. This class makes an HTTP GET request to an external web service. However, I encounter the following error:

Callout from triggers are currently not supported.

How can I send data to an external web service from a trigger and receive an acknowledgment? While I can use an @future method, it only supports void and cannot return a result. I need a way to make the callout and process the response within Salesforce.

Answer

Callouts cannot be made directly from triggers because they would pause the database transaction until the external service responds, which can take up to 120 seconds. This would cause delays, impact system performance, and create contention with other transactions.

CRS Info Solutions offers expert Salesforce online training with real-time projects, certification guidance, interview coaching, and a job-ready approach. Enroll for free demo today!!!

The only way to perform a callout from a trigger is to do it asynchronously using a method annotated with @future or by leveraging queueable Apex. However, @future methods cannot return values, so you cannot get an immediate acknowledgment.

A common workaround is to store the response on the record after the asynchronous callout completes. You can pass the record ID to the @future or Queueable method, perform the callout, and then update the record once the response is received.

Here’s how you can do it using a @future method:

public class CalloutService {
    @future(callout=true)
    public static void makeCallout(Set<Id> recordIds) {
        for (Id recordId : recordIds) {
            // Perform HTTP Callout
            Http http = new Http();
            HttpRequest request = new HttpRequest();
            request.setEndpoint('https://example.com/api');
            request.setMethod('GET');
            
            HttpResponse response = http.send(request);
            
            // Update the record with the response
            if (response.getStatusCode() == 200) {
                MyCustomObject__c obj = [SELECT Id, ResponseField__c FROM MyCustomObject__c WHERE Id = :recordId LIMIT 1];
                obj.ResponseField__c = response.getBody();
                update obj;
            }
        }
    }
}

Explanation: The CalloutService class defines a @future method makeCallout, which performs an asynchronous HTTP GET request for a set of record IDs. After sending the request, it checks if the response is successful (status code 200) and updates the corresponding MyCustomObject__c record with the response body. Since @future methods run asynchronously, they allow the callout to execute without blocking the trigger’s database transaction.

And here’s how the trigger calls the asynchronous method:

trigger MyTrigger on MyCustomObject__c (after insert) {
    Set<Id> recordIds = new Set<Id>();
    for (MyCustomObject__c obj : Trigger.new) {
        recordIds.add(obj.Id);
    }
    CalloutService.makeCallout(recordIds);
}

Explanation: This trigger runs after a new record is inserted into MyCustomObject__c. It collects the IDs of the newly inserted records into a Set<Id> and passes them to the makeCallout method in the CalloutService class. Since callouts cannot be made directly from triggers, this method is expected to be asynchronous (e.g., using @future or Queueable Apex) to handle the HTTP request in the background.

Alternative Approach:

Queueable Apex

A more flexible approach is using Queueable Apex, which allows chaining and stateful processing. This is useful if you need to process the response further or chain multiple callouts.

public class CalloutQueueable implements Queueable, Database.AllowsCallouts {
    private Id recordId;
    
    public CalloutQueueable(Id recordId) {
        this.recordId = recordId;
    }

    public void execute(QueueableContext context) {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://example.com/api');
        request.setMethod('GET');
        
        HttpResponse response = http.send(request);
        
        if (response.getStatusCode() == 200) {
            MyCustomObject__c obj = [SELECT Id, ResponseField__c FROM MyCustomObject__c WHERE Id = :recordId LIMIT 1];
            obj.ResponseField__c = response.getBody();
            update obj;
        }
    }
}

Explanation: This Queueable Apex class allows asynchronous execution of an HTTP callout by implementing Queueable and Database.AllowsCallouts. It takes a record ID in the constructor, makes a GET request to an external API in the execute method, and updates the corresponding record’s ResponseField__c with the response body if the request is successful. This approach ensures the callout runs independently of the trigger, avoiding synchronous callout restrictions.

Modify the trigger to enqueue the job:

trigger MyTrigger on MyCustomObject__c (after insert) {
    for (MyCustomObject__c obj : Trigger.new) {
        System.enqueueJob(new CalloutQueueable(obj.Id));
    }
}

Explanation: This trigger runs after an insert operation on MyCustomObject__c. For each newly inserted record, it creates a new instance of the CalloutQueueable class, passing the record ID to it. The trigger then enqueues the job using System.enqueueJob, which executes the callout asynchronously without blocking the transaction.

Summing Up

Since triggers cannot make direct callouts due to transaction blocking, the best approach is to execute them asynchronously using @future or Queueable Apex. While @future methods are simpler, Queueable Apex offers more flexibility, such as chaining and handling complex responses. To provide real-time feedback, UI components should poll the updated record rather than relying on immediate callout responses.

Salesforce Training in Chennai: Unlock Your Potential

Elevate your career with our comprehensive Salesforce training in Chennai, designed to equip you with expertise in Admin, Developer, and AI modules. Our program offers unparalleled certification guidance, rigorous interview preparation, and industry-aligned training to ensure you gain a competitive edge. With in-depth modules and expert-led sessions, you’ll build a solid foundation in Salesforce while mastering advanced techniques to meet real-world demands.

Our unique learning approach combines practical hands-on sessions with detailed class notes, enabling you to gain job-ready skills and confidence. Whether you’re starting fresh or upskilling, our training ensures you stand out in the fast-paced Salesforce ecosystem.

Take the first step toward your success by joining our free demo class today and experience the best in Salesforce education!!!

Related Posts:

Writing Test Classes for Invocable and @Future Apex Methods
Salesforce CRM Using Apex And Visualforce Training


Comments are closed.