---
schema_version: "1"
id: 338c1612f010b4b216ad49de446ddf6f898fea14a6b40f1e4bdc009f629d44c2
title: Integration Procedure Invocation from Apex
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/xcloud/264-0-0/os_integration_procedure_invocation_from_apex_55724.md
canonical_url: https://help.salesforce.com/s/articleView?id=xcloud.os_integration_procedure_invocation_from_apex_55724.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: e55bd08ef70c761cc9e5109d56c37329e313a019a38c4bece4d672dc4b513167
description: Starting with Summer’ 25, use the ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput) Connect API for Integration Procedure calls from the IntegrationProcedureService Apex class. This Connect API removes the dependency on the managed package and provides up to 21% better performance for Integration Procedure calls from an Apex class compared to the previous method.
products:
  - Omnistudio
release: "264"
---
# Integration Procedure Invocation from Apex

Starting with Summer’ 25, use the ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput) Connect API for Integration Procedure calls from the IntegrationProcedureService Apex class. This Connect API removes the dependency on the managed package and provides up to 21% better performance for Integration Procedure calls from an Apex class compared to the previous method.

![Important](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-xcloud-omnistudio-264-0-0-production-enus/f526eaa8-ae05-487a-8944-4bb99b0b78ac/images/icon_important.png)

Important The performance figures in this document are provided for informational purposes only and are based on internal validation and testing under specific conditions. Actual results may vary depending on your component design, production environment, and other factors. These figures provide ‌general guidance and aren't a guarantee of performance.

## Prerequisites

Before using the Connect API for Integration Procedure invocations, enable **Enhanced Runtime Performance** on the Omnistudio Settings page. When **Enhanced Runtime Performance** is disabled, requests do not route through the Connect API.

For instructions, see [Enable Enhanced Runtime Performance of Components](https://help.salesforce.com/s/articleView?id=xcloud.os_setting_runtime_perf.htm&type=5&language=en_US).

## Invoke an Integration Procedure and return its data

Invokes an Integration Procedure and returns its data. Ignores Sharing Rules and Custom Permissions, which ensures that the Integration Procedure is private. See Sharing Rules and Custom Permissions in Salesforce Help.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
        <colgroup>
          <col style="width:50%">
          <col style="width:50%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e72">Connect API for Integration Procedure Invocation</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e75">Existing Method (Replace with Connect API)</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Connect API for Integration Procedure Invocation" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e72 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>String <strong>ipName</strong> = 'FindContacts_LastNames';
Map&lt;String, Object&gt; <strong>inputMap</strong> = new Map&lt;String, Object&gt;();
inputMap.put('ContactLastName', 'Smith');

Map&lt;String, Object&gt; <strong>optionsMap</strong> = new Map&lt;String, Object&gt;();
optionsMap.put('isDebug', false);

ConnectAPI.IntegrationProcedureServiceRunInputRepresentation apexInput = new ConnectAPI.IntegrationProcedureServiceRunInputRepresentation();
List&lt;String&gt; stringList = new List&lt;String&gt;();
<strong>String serializedInputMap = JSON.serialize(inputMap);</strong>
stringList.add(serializedInputMap);
apexInput.input = stringList;

ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation options = new ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation();
for (String key: optionsMap.keySet()){
    if (key == 'isDebug') {
        options.isDebug = (Boolean)optionsMap.get(key);
    } else if (key == 'chainable') {
        options.chainable = (Boolean)optionsMap.get(key);
    } else if (key == 'resetCache') {
        options.resetCache = (Boolean)optionsMap.get(key);
    } else if (key == 'ignoreCache') {
        options.ignoreCache = (Boolean)optionsMap.get(key);
    } else if (key == 'queueableChainable') {
        options.queueableChainable = (Boolean)optionsMap.get(key);
    } else if (key == 'useQueueableApexRemoting') {
        options.useQueueableApexRemoting = (Boolean)optionsMap.get(key);
    } else if (key == 'vlcApexResponse') {
        options.vlcApexResponse = (Boolean)optionsMap.get(key);
    } else if (key == 'useFuture') {
        options.useFuture = (Boolean)optionsMap.get(key);
    } else if (key == 'useQueueable') {
        options.useQueueable = (Boolean)optionsMap.get(key);
    } else if (key == 'vlcIPData') {
        options.vlcIPData = (String)optionsMap.get(key);
    } else if (key == 'vlcStatus') {
        options.vlcStatus = (String)optionsMap.get(key);
    } else if (key == 'vlcMessage') {
        options.vlcMessage = (String)optionsMap.get(key);
    }
}
options.<strong>shouldSendLegacyResponse</strong> = true;
apexInput.options = options;

<strong>ConnectAPI.IntegrationProcedureServiceRunOutputRepresentation output = ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput);</strong>

List&lt;String&gt; responseList = output.response;
String currentSerResponse = responseList[0];
Map&lt;String, Object&gt; currentResponseObj = (Map&lt;String, Object&gt;)JSON.deserializeUntyped(currentSerResponse);

<strong>Object ipOutput = currentResponseObj.get('result');</strong></code></pre>
            </td>

            <td data-label="Existing Method (Replace with Connect API)" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e75 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>String <strong>ipName</strong> = 'FindContacts_LastNames';
Map&lt;String, Object&gt; <strong>inputMap</strong> = new Map&lt;String, Object&gt;();
inputMap.put('ContactLastName',
'Smith');

Map&lt;String, Object&gt; <strong>optionsMap</strong> = new Map&lt;String, Object&gt;();
optionsMap.put('isDebug', false);

<strong>Object ipOutput = devopsimpkg11.Integration ProcedureService.runIntegrationService(ipName, inputMap, optionsMap);</strong></code></pre>
            </td>

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

## Invoke an Integration Procedure and return its data ignoring Sharing Rules and Custom Permissions

Invokes an Integration Procedure and returns its data. Ignores sharing rules and custom permissions, which ensures that the Integration Procedure is private. See [Sharing Rules](https://help.salesforce.com/s/articleView?id=platform.security_about_sharing_rules.htm&type=5&language=en_US) and [Custom Permissions](https://help.salesforce.com/s/articleView?id=platform.custom_perms_overview.htm&type=5&language=en_US) in Salesforce Help.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
        <colgroup>
          <col style="width:49.504950495049506%">
          <col style="width:50.495049504950494%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e161">Connect API for IP Invocation </th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e164">Existing Method (Replace with Connect API)</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Connect API for IP Invocation" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e161 ">
              <p>Users must have appropriate permissions to execute the
                Integration Procedure.</p>
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>
String <strong>ipName</strong> = 'FindContacts_LastNames';
Map&lt;String, Object&gt; <strong>inputMap</strong> = new Map&lt;String, Object&gt;();
inputMap.put('ContactLastName', 'Smith');

Map&lt;String, Object&gt; <strong>optionsMap</strong> = new Map&lt;String, Object&gt;();
optionsMap.put('isDebug', false);

ConnectAPI.IntegrationProcedureServiceRunInputRepresentation apexInput = new ConnectAPI.IntegrationProcedureServiceRunInputRepresentation();
List&lt;String&gt; stringList = new List&lt;String&gt;();
<strong>String serializedInputMap = JSON.serialize(inputMap);</strong>
stringList.add(serializedInputMap);
apexInput.input = stringList;

ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation options = new ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation();
for (String key: optionsMap.keySet()){
    if (key == 'isDebug') {
        options.isDebug = (Boolean)optionsMap.get(key);      
    } else if (key == 'chainable') {
        options.chainable = (Boolean)optionsMap.get(key);  
    } else if (key == 'resetCache') {
        options.resetCache = (Boolean)optionsMap.get(key);  
    } else if (key == 'ignoreCache') {
        options.ignoreCache = (Boolean)optionsMap.get(key);  
    } else if (key == 'queueableChainable') {
        options.queueableChainable = (Boolean)optionsMap.get(key);  
    } else if (key == 'useQueueableApexRemoting') {
        options.useQueueableApexRemoting = (Boolean)optionsMap.get(key);  
    } else if (key == 'vlcApexResponse') {
        options.vlcApexResponse = (Boolean)optionsMap.get(key);  
    } else if (key == 'useFuture') {
        options.useFuture = (Boolean)optionsMap.get(key);  
    } else if (key == 'useQueueable') {
        options.useQueueable = (Boolean)optionsMap.get(key);  
    } else if (key == 'vlcIPData') {
        options.vlcIPData = (String)optionsMap.get(key);  
    } else if (key == 'vlcStatus') {
        options.vlcStatus = (String)optionsMap.get(key);  
    } else if (key == 'vlcMessage') {
        options.vlcMessage = (String)optionsMap.get(key);  
    } 
}
options.<strong>shouldSendLegacyResponse</strong> = true;
apexInput.options = options;

<strong>ConnectAPI.IntegrationProcedureServiceRunOutputRepresentation output = ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput)</strong>;

List&lt;String&gt; responseList = output.response;
String currentSerResponse = responseList[0];
Map&lt;String, Object&gt; currentResponseObj = (Map&lt;String, Object&gt;)JSON.deserializeUntyped(currentSerResponse);
<strong>
Object ipOutput = currentResponseObj.get('result');</strong>
</code></pre>
            </td>

            <td data-label="Existing Method (Replace with Connect API)" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e164 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>
String <strong>ipName</strong> = 'FindContacts_LastNames';
Map&lt;String, Object&gt; <strong>inputMap</strong> = new Map&lt;String, Object&gt;();
inputMap.put('ContactLastName', 'Smith');

Map&lt;String, Object&gt; <strong>optionsMap</strong> = new Map&lt;String, Object&gt;();
optionsMap.put('isDebug', false);
<strong>Object ipOutput = devopsimpkg11.IntegrationProcedureService.runIntegrationProcedureServiceFromApex(ipName, inputMap, optionsMap);
</strong></code></pre>
            </td>

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

## Invoke an Integration Procedure with a @future annotation applied

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
        <colgroup>
          <col style="width:50%">
          <col style="width:50%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e243">Connect API for Integration Procedure Invocation</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e246">Existing Method (Replace with Connect API)</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Connect API for Integration Procedure Invocation" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e243 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>
String <strong>ipName</strong> = 'FindContacts_LastNames';
String <strong>inputMap</strong> = '{"ContactLastName": "Smith"}';
String <strong>optionsMap</strong> = '{"isDebug": false}';

ConnectAPI.IntegrationProcedureServiceRunInputRepresentation apexInput = new ConnectAPI.IntegrationProcedureServiceRunInputRepresentation();
List&lt;String&gt; stringList = new List&lt;String&gt;();
stringList.add(inputMap);
apexInput.input = stringList;

Map&lt;String, Object&gt; optionsMapDeserialized = (Map&lt;String, Object&gt;)JSON.deserializeUntyped(optionsMap);

ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation options = new ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation();
 
 for (String key: optionsMapDeserialized.keySet()){
    if (key == 'isDebug') {
        options.isDebug = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'chainable') {
        options.chainable = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'resetCache') {
        options.resetCache = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'ignoreCache') {
        options.ignoreCache = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'queueableChainable') {
        options.queueableChainable = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'useQueueableApexRemoting') {
        options.useQueueableApexRemoting = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'vlcApexResponse') {
        options.vlcApexResponse = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'useFuture') {
        options.useFuture = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'useQueueable') {
        options.useQueueable = (Boolean)optionsMapDeserialized.get(key);  
    } else if (key == 'vlcIPData') {
        options.vlcIPData = (String)optionsMapDeserialized.get(key);  
    } else if (key == 'vlcStatus') {
        options.vlcStatus = (String)optionsMapDeserialized.get(key);  
    } else if (key == 'vlcMessage') {
        options.vlcMessage = (String)optionsMapDeserialized.get(key);  
    } 
}
  
options.<strong>shouldSendLegacyResponse</strong> = true;
options.<strong>useFuture</strong> = true;
apexInput.options = options;

<strong>ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput)</strong>;
</code></pre>
            </td>

            <td data-label="Existing Method (Replace with Connect API)" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e246 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>String <strong>ipName</strong> = 'FindContacts_LastNames';
String <strong>inputMap</strong> = '{"ContactLastName": "Smith"}';
String <strong>optionsMap</strong> = '{"isDebug": false}';

<strong>devopsimpkg11.IntegrationProcedureService.runIntegrationServiceFuture(ipName, inputMap, optionsMap);</strong></code></pre>
            </td>

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

## Invoke an Integration Procedure as a Queueable Apex Job for Asynchronous Processing

Returns the ID of the Queueable job. See [Queueable Apex](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_queueing_jobs.htm) in Salesforce Help.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
        <colgroup>
          <col style="width:50%">
          <col style="width:50%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e327">Connect API for Integration Procedure Invocation</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e330">Existing Method (Replace with Connect API)</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Connect API for Integration Procedure Invocation" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e327 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>
String <strong>ipName</strong> = 'FindContacts_LastNames';

Map&lt;String, Object&gt; <strong>inputMap</strong> = new Map&lt;String, Object&gt;();
inputMap.put('ContactLastName', 'Smith');

Map&lt;String, Object&gt; <strong>optionsMap</strong> = new Map&lt;String, Object&gt;();
optionsMap.put('isDebug', false);

ConnectAPI.IntegrationProcedureServiceRunInputRepresentation apexInput = new ConnectAPI.IntegrationProcedureServiceRunInputRepresentation();
List&lt;String&gt; stringList = new List&lt;String&gt;();
<strong>String serializedInputMap = JSON.serialize(inputMap);</strong>
stringList.add(serializedInputMap);
apexInput.input = stringList;

ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation options = new ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation();
for (String key: optionsMap.keySet()){
    if (key == 'isDebug') {
        options.isDebug = (Boolean)optionsMap.get(key);  
    } else if (key == 'chainable') {
        options.chainable = (Boolean)optionsMap.get(key);  
    } else if (key == 'resetCache') {
        options.resetCache = (Boolean)optionsMap.get(key);  
    } else if (key == 'ignoreCache') {
        options.ignoreCache = (Boolean)optionsMap.get(key);  
    } else if (key == 'queueableChainable') {
        options.queueableChainable = (Boolean)optionsMap.get(key);  
    } else if (key == 'useQueueableApexRemoting') {
        options.useQueueableApexRemoting = (Boolean)optionsMap.get(key);  
    } else if (key == 'vlcApexResponse') {
        options.vlcApexResponse = (Boolean)optionsMap.get(key);      
    } else if (key == 'useFuture') {
        options.useFuture = (Boolean)optionsMap.get(key);  
    } else if (key == 'useQueueable') {
        options.useQueueable = (Boolean)optionsMap.get(key);  
    } else if (key == 'vlcIPData') {
        options.vlcIPData = (String)optionsMap.get(key);  
    } else if (key == 'vlcStatus') {
        options.vlcStatus = (String)optionsMap.get(key);  
    } else if (key == 'vlcMessage') {
        options.vlcMessage = (String)optionsMap.get(key);  
    } 
}    
options.<strong>shouldSendLegacyResponse</strong> = true;
<strong>options.useQueueable = true;</strong>
apexInput.options = options;

<strong>ConnectAPI.IntegrationProcedureServiceRunOutputRepresentation output = ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput);</strong>

List&lt;String&gt; responseList = output.response;
String currentSerResponse = responseList[0];
Map&lt;String, Object&gt; currentResponseObj = (Map&lt;String, Object&gt;)JSON.deserializeUntyped(currentSerResponse);

Object currentResult = currentResponseObj.get('result');
Map&lt;String, Object&gt; mapCurrentResult = (Map&lt;String, Object&gt;)currentResult;

Object ipResultObj = mapCurrentResult.get('IPResult');
Map&lt;String, Object&gt; IpResultMap = (Map&lt;String, Object&gt;)ipResultObj;<strong>
Id ipOutput = (Id)IpResultMap.get('queueableJobId');</strong>
</code></pre>
            </td>

            <td data-label="Existing Method (Replace with Connect API)" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e330 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>
String <strong>ipName</strong> = 'FindContacts_LastNames';
Map <strong>inputMap</strong> = new Map();
inputMap.put('ContactLastName', 'Smith');
Map <strong>optionsMap</strong> = new Map();
optionsMap.put('isDebug', false);


Id <strong>ipOutput</strong> = devopsimpkg11.IntegrationProcedureService.runIntegrationProcedureQueueable(ipName, inputMap, optionsMap);
</code></pre>
            </td>

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

## Invokes an Integration Procedure passing in a map of input parameters and receiving the output in another map

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
        <colgroup>
          <col style="width:50%">
          <col style="width:50%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e410">Connect API for Integration Procedure Invocation</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d28729e413">Existing Method (Replace with Connect API)</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Connect API for Integration Procedure Invocation" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e410 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>
String <strong>ipName</strong> = 'FindContacts_LastNames';
    
Map&lt;String, Object&gt; <strong>inputMap</strong> = new Map&lt;String, Object&gt;();
inputMap.put('ContactLastName', 'Smith');
   Map&lt;String, Object&gt; <strong>outputMap</strong> = new Map&lt;String, Object&gt;();


Map&lt;String, Object&gt; <strong>optionsMap</strong> = new Map&lt;String, Object&gt;();
optionsMap.put('isDebug', false);

ConnectAPI.IntegrationProcedureServiceRunInputRepresentation apexInput = new ConnectAPI.IntegrationProcedureServiceRunInputRepresentation();
List&lt;String&gt; stringList = new List&lt;String&gt;();
<strong>String serializedInputMap = JSON.serialize(inputMap);</strong>
stringList.add(serializedInputMap);
apexInput.input = stringList;

ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation options = new ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation();
for (String key: optionsMap.keySet()){
    if (key == 'isDebug') {
        options.isDebug = (Boolean)optionsMap.get(key);  
    } else if (key == 'chainable') {
        options.chainable = (Boolean)optionsMap.get(key);      
    } else if (key == 'resetCache') {
        options.resetCache = (Boolean)optionsMap.get(key);  
    } else if (key == 'ignoreCache') {
        options.ignoreCache = (Boolean)optionsMap.get(key);  
    } else if (key == 'queueableChainable') {
        options.queueableChainable = (Boolean)optionsMap.get(key);  
    } else if (key == 'useQueueableApexRemoting') {
        options.useQueueableApexRemoting = (Boolean)optionsMap.get(key);  
    } else if (key == 'vlcApexResponse') {
        options.vlcApexResponse = (Boolean)optionsMap.get(key);  
    } else if (key == 'useFuture') {
        options.useFuture = (Boolean)optionsMap.get(key);  
    } else if (key == 'useQueueable') {
        options.useQueueable = (Boolean)optionsMap.get(key);  
    } else if (key == 'vlcIPData') {
        options.vlcIPData = (String)optionsMap.get(key);  
    } else if (key == 'vlcStatus') {
        options.vlcStatus = (String)optionsMap.get(key);  
    } else if (key == 'vlcMessage') {
        options.vlcMessage = (String)optionsMap.get(key);  
    } 

}

options.<strong>shouldSendLegacyResponse</strong> = true;
apexInput.options = options;

<strong>ConnectAPI.IntegrationProcedureServiceRunOutputRepresentation output = ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput);</strong>

List&lt;String&gt; responseList = output.response;
String currentSerResponse = responseList[0];
Map&lt;String, Object&gt; currentResponseObj = (Map&lt;String, Object&gt;)JSON.deserializeUntyped(currentSerResponse);
Object <strong>ipOutput</strong> = currentResponseObj.get('result');

if (options.useQueueable == true) {
    Map&lt;String, Object&gt; mapCurrentResult = (Map&lt;String, Object&gt;)ipOutput;
    Object ipResultObj = mapCurrentResult.get('IPResult');
    ipOutput = ipResultObj;
}
else if (options.useFuture == true) {
    ipOutput = new Map&lt;String, Object&gt;();
}    

<strong>outputMap.put('IPResult', ipOutput);</strong>
</code></pre>
            </td>

            <td data-label="Existing Method (Replace with Connect API)" class="slds-cell-wrap" style="vertical-align:top;" headers="d28729e413 ">
              <pre class="line-numbers slds-box slds-box_x-small slds-theme_shade slds-m-top_medium slds-m-bottom_medium slds-scrollable_x"><code>
String <strong>ipName</strong> = 'FindContacts_LastNames';

Map&lt;String, Object&gt; <strong>inputMap</strong> = new Map&lt;String, Object&gt;();
inputMap.put('ContactLastName', 'Smith');
<strong>
Map&lt;String, Object&gt; outputMap = new Map&lt;String, Object&gt;();</strong>

Map&lt;String, Object&gt; <strong>optionsMap</strong> = new Map&lt;String, Object&gt;();
optionsMap.put('isDebug', false);

devopsimpkg11.IntegrationProcedureService ipService = new devopsimpkg11.IntegrationProcedureService();

<strong>ipService.invokeMethod(ipName, inputMap, outputMap, optionsMap);</strong> // Returns Boolean

<strong>Object ipOutput = outputMap.get('IPResult');</strong></code></pre>
            </td>

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

## Integration Procedure Call Examples

You can invoke an Integration Procedure from Apex code in two ways using the IntegrationProcedureService class.

Example 1

```

class IntegrationProcedureService {
/*
procedureAPIName - the Type_SubType of Procedure
input - The payload / initial data in the Map<String, Object> format for the Procedure
*/

String ipName = 'FindContacts_LastNames';
Map<String, Object> inputMap = new Map<String, Object>();
inputMap.put('ContactLastName', 'Smith');

Map<String, Object> optionsMap = new Map<String, Object>();
optionsMap.put('isDebug', false);

ConnectAPI.IntegrationProcedureServiceRunInputRepresentation apexInput = new ConnectAPI.IntegrationProcedureServiceRunInputRepresentation();
List<String> stringList = new List<String>();
String serializedInputMap = JSON.serialize(inputMap);
stringList.add(serializedInputMap);
apexInput.input = stringList;

ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation options = new ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation();
for (String key: optionsMap.keySet()){
if (key == 'isDebug') {
        options.isDebug = (Boolean)optionsMap.get(key);
    } else if (key == 'chainable') {
        options.chainable = (Boolean)optionsMap.get(key);
    } else if (key == 'resetCache') {
        options.resetCache = (Boolean)optionsMap.get(key);
    } else if (key == 'ignoreCache') {
        options.ignoreCache = (Boolean)optionsMap.get(key);
    } else if (key == 'queueableChainable') {
        options.queueableChainable = (Boolean)optionsMap.get(key);
    } else if (key == 'useQueueableApexRemoting') {
        options.useQueueableApexRemoting = (Boolean)optionsMap.get(key);
    } else if (key == 'vlcApexResponse') {
        options.vlcApexResponse = (Boolean)optionsMap.get(key);
    } else if (key == 'useFuture') {
        options.useFuture = (Boolean)optionsMap.get(key);
    } else if (key == 'useQueueable') {
        options.useQueueable = (Boolean)optionsMap.get(key);
    } else if (key == 'vlcIPData') {
        options.vlcIPData = (String)optionsMap.get(key);
    } else if (key == 'vlcStatus') {
        options.vlcStatus = (String)optionsMap.get(key);
    } else if (key == 'vlcMessage') {
        options.vlcMessage = (String)optionsMap.get(key);
    }
}
options.shouldSendLegacyResponse = true;
apexInput.options = options;

ConnectAPI.IntegrationProcedureServiceRunOutputRepresentation output = ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput);

List<String> responseList = output.response;
String currentSerResponse = responseList[0];
Map<String, Object> currentResponseObj = (Map<String, Object>)JSON.deserializeUntyped(currentSerResponse);

Object ipOutput = currentResponseObj.get('result');
```

Example 2

```
/* Initialize variables */
String procedureName = 'Type_SubType';
Map<String, Object> ipInput = new Map<String, Object> ();
Map<String, Object> ipOutput = new Map<String, Object> ();
Map<String, Object> ipOptions = new Map<String, Object> ();

/* Populating input map for an Integration Procedure. 
Follow whatever structure your VIP expects */
String orderId = '80100000000abcd';
ipInput.put('orderId', orderId);

/* Call the Integration Procedure via runIntegrationService, 
and save the output to ipOutput */
ipOutput = (Map<String, Object>) 

String ipName = 'FindContacts_LastNames';
Map<String, Object> inputMap = new Map<String, Object>();
inputMap.put('ContactLastName', 'Smith');

Map<String, Object> optionsMap = new Map<String, Object>();
optionsMap.put('isDebug', false);

ConnectAPI.IntegrationProcedureServiceRunInputRepresentation apexInput = new ConnectAPI.IntegrationProcedureServiceRunInputRepresentation();
List<String> stringList = new List<String>();
String serializedInputMap = JSON.serialize(inputMap);
stringList.add(serializedInputMap);
apexInput.input = stringList;

ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation options = new ConnectAPI.IntegrationProcedureServiceRunOptionsRepresentation();
for (String key: optionsMap.keySet()){
    if (key == 'isDebug') {
        options.isDebug = (Boolean)optionsMap.get(key);
    } else if (key == 'chainable') {
        options.chainable = (Boolean)optionsMap.get(key);
    } else if (key == 'resetCache') {
        options.resetCache = (Boolean)optionsMap.get(key);
    } else if (key == 'ignoreCache') {
        options.ignoreCache = (Boolean)optionsMap.get(key);
    } else if (key == 'queueableChainable') {
        options.queueableChainable = (Boolean)optionsMap.get(key);
    } else if (key == 'useQueueableApexRemoting') {
        options.useQueueableApexRemoting = (Boolean)optionsMap.get(key);
    } else if (key == 'vlcApexResponse') {
        options.vlcApexResponse = (Boolean)optionsMap.get(key);
    } else if (key == 'useFuture') {
        options.useFuture = (Boolean)optionsMap.get(key);
    } else if (key == 'useQueueable') {
        options.useQueueable = (Boolean)optionsMap.get(key);
    } else if (key == 'vlcIPData') {
        options.vlcIPData = (String)optionsMap.get(key);
    } else if (key == 'vlcStatus') {
        options.vlcStatus = (String)optionsMap.get(key);
    } else if (key == 'vlcMessage') {
        options.vlcMessage = (String)optionsMap.get(key);
    }
}
options.shouldSendLegacyResponse = true;
apexInput.options = options;

ConnectAPI.IntegrationProcedureServiceRunOutputRepresentation output = ConnectAPI.OmniDesignerConnect.integrationProcedureExecute(ipName, apexInput);

List<String> responseList = output.response;
String currentSerResponse = responseList[0];
Map<String, Object> currentResponseObj = (Map<String, Object>)JSON.deserializeUntyped(currentSerResponse);

Object ipOutput = currentResponseObj.get('result');

System.debug('IP Output: ' + ipOutput);
```