---
schema_version: "1"
id: 66004160699a5a7149328685fd042cd593fe8274d0d3d3ba02e4f7e655314622
title: Use Apex to Create an Asynchronous Callout to an External Service
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/platform/264-0-0/external_services_async_ops_create.md
canonical_url: https://help.salesforce.com/s/articleView?id=platform.external_services_async_ops_create.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: 08aa4a40ff3ede8332ee773758fe99fb70b9c69fe6a69614d9bfa32af7d0e51e
description: When you register a schema containing a callback, External Services creates an invocable Apex operation with an automatically generated Apex class. Salesforce creates a callback URL on the asynchronous callout (initial callout) that’s read-only. Create an Apex client that’s capable of handling the callback by using the generated Apex interfaces. The client waits for an asynchronous response from the external system for an extended time (up to twenty-four hours).
products:
  - Salesforce Platform
  - Security
release: "264"
---
# Use Apex to Create an Asynchronous Callout to an External Service

When you register a schema containing a callback, External Services creates an invocable Apex operation with an automatically generated Apex class. Salesforce creates a callback URL on the asynchronous callout (initial callout) that’s read-only. Create an Apex client that’s capable of handling the callback by using the generated Apex interfaces. The client waits for an asynchronous response from the external system for an extended time (up to twenty-four hours).

![Important](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-platform-extend_click-264-0-0-production-enus/5f7d9219-b7b1-4552-8891-f1aba9b289fc/images/icon_important.png)

Important Connected apps creation is restricted as of Spring ‘26. You can continue to use existing connected apps during and after Spring ‘26. However, we recommend using [external client apps](https://help.salesforce.com/s/articleView?id=xcloud.external_client_apps.htm&language=en_US) instead. If you must continue creating connected apps, contact Salesforce Support.

See [New connected apps can no longer be created in Spring ‘26](https://help.salesforce.com/s/articleView?id=005228017&type=1&language=en_US) for more details.

Here’s some prerequisite reading and configuration to do before you create your own asynchronous callout.

- Review the fictitious schema on which our examples of asynchronous callbacks are based. See [Example API Specification With Callback Operation](https://help.salesforce.com/s/articleView?id=platform.external_services_async_ops_example.htm&release=264.0.0&type=5).
- To authenticate and create requests [Define an External Credential and a Named Credential](https://help.salesforce.com/s/articleView?id=platform.external_services_define_named_credential.htm&release=264.0.0&type=5 "First, create an external credential to specify an authentication protocol and permission set or profile to use when authenticating to an external system. Second, in order for External Services to authenticate, create a named credential and specify it as the callout endpoint.").
- To receive the asynchronous response, create a connected app as described in [Authorization Through Connected Apps and OAuth 2.0](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_oauth_and_connected_apps.htm). Salesforce Platform callback endpoints are exposed with TLS in Connect API. The caller must authenticate to the Salesforce org by setting up the appropriate connected app.
- Register the API specification, using the normal workflow as described in [Register an External Service](https://help.salesforce.com/s/articleView?id=platform.external_services_register.htm&release=264.0.0&type=5 "Registering an external service takes only a few steps and no code.").

As a comparison, a synchronous callout typically looks like this:

```
ExternalService.AcmeMortgages acme = new ...();

ExternalService.AcmeMortgages.GetApplication_Request request = new ...();
request.applicationNumber = 'X202290';

ExternalService.AcmeMorgages.GetApplication_Response response = 
    acme.GetApplication(request);

ExternalService.AcmeMortgages_MortgageApplication application = response.Code200;
```

To invoke an asynchronous callout, you must write your own Apex code to make the callout. Then, you must implement your own callback object and pass it into your asynchronous invocation method within your Apex code.

The callback handler must be stateless. Salesforce doesn't preserve state information when the response is called back.

Don't nest the callback class. The callback class should implement the callback interface directly. For example:

- Correct: class `MyCallback` extends `ES.ServiceName.OperationName_Callback {...}`
- Not Recommended: class `SomeIntermediateClass` extends `ES.ServiceName.OperationName_Callback {...}` and then `MyCallback` extends `SomeIntermediateClass {...}`

1. From Setup, in the Quick Find box, enter Apex Classes in the Quick Find box, and then select **Apex Classes**.
2. Find the Apex class that contains the callback interface you want to use.
3. Create a callback. Write an Apex callback object that implements the External Services generated callback interface by referencing the corresponding Apex class.
4. After you have a callback definition, pass this callback into your asynchronous invocation method within your Apex code.

![Example](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-platform-extend_click-264-0-0-production-enus/5f7d9219-b7b1-4552-8891-f1aba9b289fc/images/icon_example.png)

Example

```java
// The callback gets called with the mortgage application update
// and handles each outcome, for example application is approved, rejected, ...
global class MyMortgageApplicationCallback extends ExternalService.AcmeMortgage.SubmitApplication_Callback {
    // Application approved
    global override void applicationOutcomeApproved(
            List<ExternalService.AcmeMortgages.SubmitApplication_applicationOutcomeApproved_Callback> callbacks) {
        ExternalService.AcmeMortgages.SubmitApplication_applicationOutcomeApproved_Callback callback = callbacks.get(0);
        if (callback.callbackStatus == CallbackStatus.COMPLETED) {
            Double loanAmount = callback.response.body.approvedAmount;
            // Create a Contact based on the response ...
        }            
    }
    
    // Application rejected
    global override void applicationOutcomeRejected(...) {...}
    
    ...
}

public class MyMortgageApplicationProcess {
    public void submitApplication(...) {
        // Submit mortgage application process
        ExternalService.AcmeMortgages acme = new ...();

        ExternalService.AcmeMortgages.SubmitApplication_Request request = new ...();
        ExternalService.AcmeMortgages_Contact applicant = new ...();
        applicant.Name = 'Joe Miller';
        applicant.Address = '555 Miller St, CA, Milltown';
        request.applicant = applicant;

        // Time out if no response after 1 day
        DateTime timeout = DateTime.now().addDays(1);

        ExternalService.AcmeMorgages.SubmitApplication_Response response = 
        acme.SubmitApplication(request, new MyMortgageApplicationCallback(), timeout);
    
        // Get back application number immediately
        String appNr = response.Code201.applicationNumber;

        // Get invocationId from a successful initial response to check status of the background operation
        String invocationId = response.invocationId;
        ...
    }
}
```