---
schema_version: "1"
id: 74919d9a38607b59e043a230322e253671cec1bd77742cfcf8c551a8e856f89a
title: Let Flows Execute Apex Actions
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/platform/264-0-0/flow_build_extend_apex.md
canonical_url: https://help.salesforce.com/s/articleView?id=platform.flow_build_extend_apex.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: 91b4dc5bb801561cab745758460b6d8f77572d55bc9040479a790d72913f8265
description: 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.
products:
  - Flow Builder
  - Salesforce Platform
release: "264"
---
# 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

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small edition"><colgroup><col></colgroup><tbody><tr class=""><td class="slds-cell-wrap" style="vertical-align:top;"><a href="https://help.salesforce.com/s/articleView?id=platform.flow_ref_supported_editions.htm&amp;release=264.0.0&amp;type=5" title="Learn about the editions and user interfaces that support Flow Builder. Some Flow Builder features integrate with other Salesforce products that require additional licenses.">View supported editions.</a></td></tr></tbody></table>

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.

![Tip](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-platform-platform_automation-264-0-0-production-enus/60568438-ec7e-4665-acd1-7c80dcbe60d5/images/icon_tip.png)

Tip We recommend using the `@InvocableMethod` annotation instead of the `Process.Plugin` interface.

![Important](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-platform-platform_automation-264-0-0-production-enus/60568438-ec7e-4665-acd1-7c80dcbe60d5/images/icon_important.png)

Important Legacy Apex actions aren’t supported in auto-layout in Flow Builder. Legacy Apex actions are only available to be added in free-form in Flow Builder. Existing actions can be edited in both auto-layout and free-form mode.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
      <colgroup>
        <col style="width:17.391304347826086%">
        <col style="width:41.04347826086956%">
        <col style="width:41.56521739130435%">
      </colgroup>
      <thead class="slds-text-title_caps ">
        <tr class="">
          <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d98827e83">&nbsp;</th>
          <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d98827e85"><code>Process.Plugin</code> Interface</th>
          <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d98827e90"><code>@InvocableMethod</code> Annotation</th>
        </tr>
      </thead>
      <tbody>
        <tr class="">
          <td data-label="" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e83 ">
            <strong>Apex data type support</strong>
          </td>

          <td data-label="Process.Plugin Interface" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e85 ">
            <p>Doesn’t support:</p>
            <ul>
              <li>Blob</li>
              <li>Collection</li>
              <li>sObject</li>
              <li>Time</li>
            </ul>
          </td>

          <td data-label="@InvocableMethod Annotation" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e90 ">
            <p>Doesn’t support:</p>
            <ul>
              <li>Generic Object</li>
              <li>Sets</li>
              <li>Maps</li>
              <li>Enums</li>
            </ul>
            <p style="margin-bottom:0;">Flow Builder doesn’t support mapping an Apex method’s input or output parameters
              to a record collection variable.</p>
          </td>

        </tr>
        <tr class="">
          <td data-label="" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e83 ">
            <strong>Bulk operations</strong>
          </td>

          <td data-label="Process.Plugin Interface" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e85 ">Not supported</td>

          <td data-label="@InvocableMethod Annotation" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e90 ">Supported</td>

        </tr>
        <tr class="">
          <td data-label="" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e83 ">
            <strong>Custom icons</strong>
          </td>

          <td data-label="Process.Plugin Interface" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e85 ">Not supported</td>

          <td data-label="@InvocableMethod Annotation" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e90 ">Supported</td>

        </tr>
        <tr class="">
          <td data-label="" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e83 ">
            <strong>Element type in Flow Builder</strong>
          </td>

          <td data-label="Process.Plugin Interface" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e85 ">Action</td>

          <td data-label="@InvocableMethod Annotation" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e90 ">Action</td>

        </tr>
        <tr class="">
          <td data-label="" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e83 "><strong>Customizable configuration experience</strong></td>

          <td data-label="Process.Plugin Interface" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e85 ">Not supported </td>

          <td data-label="@InvocableMethod Annotation" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e90 ">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.</td>

        </tr>
        <tr class="">
          <td data-label="" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e83 ">
            <strong>Element name in Flow Builder</strong>
          </td>

          <td data-label="Process.Plugin Interface" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e85 ">Class name or the value of the <code>name</code>
            property.</td>

          <td data-label="@InvocableMethod Annotation" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e90 ">Class name</td>

        </tr>
        <tr class="">
          <td data-label="" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e83 ">
            <strong>Reusability</strong>
          </td>

          <td data-label="Process.Plugin Interface" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e85 ">Classes with this interface implemented are available in flows</td>

          <td data-label="@InvocableMethod Annotation" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e90 ">
            <p>Classes with this annotation implemented are available in:</p>
            <ul>
              <li>Flows</li>
              <li>Processes</li>
              <li>Rest API</li>
            </ul>
          </td>

        </tr>
        <tr class="">
          <td data-label="" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e83 ">
            <strong>More Details in <cite>Apex Developer Guide</cite></strong>
          </td>

          <td data-label="Process.Plugin Interface" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e85 ">
            <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_process_plugin_using.htm" target="_blank">Passing Data to a Flow Using the <code>Process.Plugin</code> Interface</a>
          </td>

          <td data-label="@InvocableMethod Annotation" class="slds-cell-wrap" style="vertical-align:top;" headers="d98827e90 "><a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm" target="_blank"><code>InvocableMethod</code> Annotation</a> and <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_InvocableVariable.htm" target="_blank"><code>InvocableVariable</code> Annotation</a></td>

        </tr>
      </tbody>
    </table>

![Example](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-platform-platform_automation-264-0-0-production-enus/60568438-ec7e-4665-acd1-7c80dcbe60d5/images/icon_example.png)

Example To illustrate the difference between these two implementation methods, here are two classes that do the same thing: get an account name from a flow and return that account’s ID.

This class implements the `@InvocableMethod` annotation.

```java
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;
   }
}
```

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-platform-platform_automation-264-0-0-production-enus/60568438-ec7e-4665-acd1-7c80dcbe60d5/images/icon_note.png)

Note

To invoke Apex from a flow, the running user requires the corresponding Apex class assignment in their profile or permission set.

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-platform-platform_automation-264-0-0-production-enus/60568438-ec7e-4665-acd1-7c80dcbe60d5/images/icon_note.png)

Note

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.

```java
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.