You are here:
Let Flows Execute Apex Actions
Flow Builder provides many capabilities, but sometimes your flow requires functionality beyond the default elements. In that case, call an Apex class from your flow by using an Apex action.
Required Editions
| View supported editions. |
Developers have two options when they’re trying to make an Apex class available as an Action
element for a flow. While the Process.Plugin interface
supports customizing how the class appears in the palette, the @InvocableMethod annotation provides more functionality. The following table
describes the features supported by each option.
@InvocableMethod
annotation instead of the Process.Plugin
interface.Process.Plugin Interface |
@InvocableMethod Annotation |
|
|---|---|---|
| Apex data type support | Doesn’t support:
|
Doesn’t support:
Flow Builder doesn’t support mapping an Apex method’s input or output parameters to a record collection variable. |
| Bulk operations | Not supported | Supported |
| Custom icons | Not supported | Supported |
| Element type in Flow Builder | Action | Action |
| Customizable configuration experience | Not supported | Supported through InvocableActionExtension metadata. Developers can customize input order and grouping, add custom headers, define picklists for inputs, and create custom property editors for specific input parameters. |
| Element name in Flow Builder | Class name or the value of the name
property. |
Class name |
| Reusability | Classes with this interface implemented are available in flows | Classes with this annotation implemented are available in:
|
| More Details in Apex Developer Guide |
Passing Data to a Flow Using the Process.Plugin Interface
|
InvocableMethod Annotation and InvocableVariable Annotation |
This class implements the @InvocableMethod
annotation.
global class lookUpAccountAnnotation {
@InvocableMethod
public static List<String> getAccountIds(List<String> names) {
List<Id> accountIds = new List<Id>();
List<Account> accounts = [SELECT Id FROM Account WHERE Name in :names];
for (Account account : accounts) {
accountIds.add(account.Id);
}
return accountIds;
}
}To invoke Apex from a flow, the running user requires the corresponding Apex class assignment in their profile or permission set.
Starting in API version 66.0, custom Apex classes used as invocable action parameters require an accessible no-argument constructor. For more information, see "Spring '26 (API Version 66.0)" under Versioned Updates.
This class
implements the Process.Plugin
interface.
global class lookUpAccountPlugin implements Process.Plugin {
global Process.PluginResult invoke(Process.PluginRequest request) {
String name = (String) request.inputParameters.get('name');
Account account = [SELECT Id FROM Account WHERE Name = :name LIMIT 1][0];
Map<String,Object> result = new Map<String,Object>();
result.put('accountId', account.Id);
return new Process.PluginResult(result);
}
global Process.PluginDescribeResult describe() {
Process.PluginDescribeResult result = new Process.PluginDescribeResult();
result.Name = 'Look Up Account ID By Name';
result.Tag = 'Account Classes';
result.inputParameters = new
List<Process.PluginDescribeResult.InputParameter>{
new Process.PluginDescribeResult.InputParameter('name',
Process.PluginDescribeResult.ParameterType.STRING, true)
};
result.outputParameters = new
List<Process.PluginDescribeResult.OutputParameter>{
new Process.PluginDescribeResult.OutputParameter('accountId',
Process.PluginDescribeResult.ParameterType.STRING)
};
return result;
}
}Notice that lookupAccountAnnotation is less than half
the length (11 lines) of lookupAccountPlugin (28 lines). In addition,
because the annotation supports bulk operations, lookupAccountAnnotation
performs one query per batch of interviews. lookupAccountPlugin performs
one query per interview.

