Our company uses Salesforce CRM to manage its business. To manage the customer support, I created an Agentforce Service Agent for order-related support and deployed it on the Salesforce Experience (Community) Site.
We have stored all order information in Salesforce objects, so the AI agent can easily read it and provide the correct answer to the customer.
But sometimes the customer may ask something that is not stored in Salesforce. In this case, the agent cannot find the information directly from Salesforce objects.
For example, a customer asks, “What is the city name for this ZIP code?” If we don’t have ZIP code details stored in Salesforce, the agent will not be able to respond using internal data.
In this article, we will learn how to create a custom action to retrieve external data using APIs in Salesforce Agentforce that connects to an external API.
When the customer requests city details for a ZIP code, the custom action sends the ZIP code to the external API, retrieves the city information, and returns it to the agent.
Retrieve External API Data Using Custom Actions in Agentforce
In the steps below, I will explain how we can create a custom action for the AI agent to send a customer request to an external API.
Before creating a Custom Action to Connect an external API
In the image below, you can see that the customer has asked the Agentforce service agent to provide the city name for the ZIP code they entered.
But since we don’t have this information stored in Salesforce and haven’t created a custom action to send this request to an external API, the Agentforce service agent is unable to provide an answer. Instead, it transfers the request to a human agent.

External Service: Zipcode Stack
If you don’t already have an account on Zipcode Stack (the external service that provides ZIP code details), I will explain how to create one and what information you need from this service in the next section.
These details will be used to set up a custom agent action in Salesforce Agentforce so the agent can retrieve city information from the external API.
First, navigate to the ZipCode Stack website and click the Get Free API Key to get the API Key and log in to the ZipCode Stack service.
After that, you will see different options. Choose the appropriate option, such as Gmail or email, and you will get logged in.

After you log in to Zipcode Stack, you will see your Default API Key on the dashboard. If you want to create a new key, you can go to the ‘API Keys’ section.
This API Key is very important because it is required to connect Salesforce Agentforce with the external API and retrieve ZIP code details through your custom agent action.

Along with the API Key, we also need the Request URL. This URL will be used in the Apex class to call the external service and retrieve the ZIP code details.
Without the correct Request API URL, the custom action in Agentforce will not be able to connect to the external system.
To get the required Request URL, go to the ‘Request Playground’ in Zipcode Stack. In the ‘Endpoint & Parameters’ section, choose the option for which you want to generate the URL.
In our case, we want to search for a city name based on the provided ZIP code, so I selected ‘V1 Search’ as the endpoint.
Next, to test the API, enter any ZIP code in the ‘Codes’ field, choose the Country, and click the ‘Send’ button.
You will see the API Response, which includes the city name and other details. If the response is correct, it means the URL is working properly.
You can then copy the ‘Generated Request URL’ and use it in your Apex class for the Agentforce custom action.

Apex Class to Callout External API in Salesforce
Below, I will explain the Apex class and how it connects to the external API to retrieve the ZIP code details. This Apex class will be used by the custom agent action in Salesforce Agentforce to get the required information and return it to the customer.
Before creating the Apex class, we first need to create a Custom Label in Salesforce to store the API Key.
This helps us keep the key secure and allows the Apex class to read it easily when connecting to the external API.
Below, I provided ZipCode_API_Key as a custom label for our API Key. We will use this label in the Apex class.

We also need to create a Remote Site Setting in Salesforce so our Apex class can call the external API.
Without adding this URL to Remote Site Settings, Salesforce will block the API request for security reasons.

This Apex class ZipCodeName is used to find the city name based on a zip code. It has a method called getCityForZipCode(), which accepts a list of zip codes.
Because the method is marked with @InvocableMethod, it can only accept a List<Integer>, so we pass the zip code as a list.
Inside the method, we make a simple REST API callout. We call the external API by sending the zip code and our API key. Salesforce will only allow this callout if the API URL is added in Remote Site Settings, which we have already added. This way, Salesforce allows the call to this external endpoint and returns the city name from the API response.
The code also includes try-catch for error handling to avoid flow failures and always returns a meaningful message. Finally, it returns a List<String> containing the city name or the error message.
public class ZipCodeName {
@InvocableMethod (callout=true
description='Finds the name of the City based on the given Zipcode')
public static List<String> getCityForZipCode(List<Integer> zipCodes) {
List<String> cityNames = new List<String>();
try {
Integer zipCodeToFind = zipCodes[0];
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('https://api.zipcodestack.com/v1/search?codes=' + zipCodeToFind + '&country=us');
req.setMethod('GET');
// Use a custom label that stores your real API key
req.setHeader('apikey', Label.ZipCode_API_Key);
HttpResponse res = h.send(req);
System.debug('Response Status Code: ' + res.getStatusCode());
System.debug('Response Body: ' + res.getBody());
// Only parse JSON when status is 200 and body looks like JSON
if (res.getStatusCode() == 200 && res.getBody() != null
&& (res.getBody().startsWith('{') || res.getBody().startsWith('['))) {
Map<String, Object> responseMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
Map<String, Object> resultMap = (Map<String, Object>) responseMap.get('results');
List<Object> zipData = (List<Object>) resultMap.get(String.valueOf(zipCodeToFind));
if (zipData != null && !zipData.isEmpty()) {
Map<String, Object> finalZipResult = (Map<String, Object>) zipData[0];
String cityName = (String) finalZipResult.get('city');
cityNames.add(cityName);
} else {
cityNames.add('No data for zip: ' + zipCodeToFind);
}
} else {
cityNames.add('HTTP ' + res.getStatusCode() + ' - ' + res.getStatus());
}
} catch (Exception e) {
cityNames.add('Exception: ' + e.getMessage());
}
return cityNames;
}
}Create a Custom Action Using an Apex Class in Salesforce
Below, I will explain how to create a Custom Action and assign it to the AI Agent. This ensures that whenever a customer asks for information not stored in Salesforce, such as city details from a ZIP code, the agent can trigger the action and call the external API to retrieve the correct response.
Now, we need to create an action in Salesforce for an agent. To do that, search for Agentforce Assets in Quick Find, then click it.
There, you will see the Topics and Actions option. Click actions, then click the New Agent Action button to create a new one.

Fill in the details below:
- Referenced Action Type: First, you will only see this field. We need to select Apex because we created an action in the Apex class.
- Referenced Action Category: Select Invocable Methods in this field.
- Referenced Action: Select the label you provided in the Apex class. In our apex class, we provided ZipCodeName as a label.
- Then, the Agent Action Label and API Name will automatically populate.
Then click the Next button to proceed.

Now, you will see that the Agent Action Instruction field is auto-populated, and this information comes from the description field in the Apex class.
This field is very important because it is what the Atlas reasoning engine uses to determine whether this action will solve this particular task.
In the Loading Text, provide the text that will display when the agent searches the details of your query.

In the Input section, we can see that the Apex method was expecting the zipCodes. Then, we have to instruct the Atlas reasoning engine on what information should be passed here.
Then, in the instruction’s Output section, we tell the agent that when you invoke this apex class passing the Zip Code, you will get some output, and we instruct it on what to do with that output.
After that, click the Finish button to create the action.

Assign Created Custom Action to Agentforce Service Agent in Salesforce
Now, let’s assign the created custom action to an agent. For that, navigate to the Setup -> In Quick Find, search for the Agentforce Agents -> Select the Agent for which you want to assign a custom action.
Here, I have selected ‘Service Agent for Orders,’ which is a Service Agent. -> Then click on the Open in Builder button to add an action.

Then, if the agent is Active, you must Deactivate it before adding the action. Here I have created a topic to find a City from a Zip Code. Now, in this topic, we will add the create action.
Below, I have provided the Classification Description, Scope, and Instructions, which you can use to create a topic for this use case.
- Classification Description: This Topic returns the Name of the City based on the given zipcode. For example, when the user asks for the name of the City whose zip code is 90210, it returns the city name.
- Scope: Your job is only to assist users in finding the city associated with a given zip code. Do not handle unrelated requests or provide additional information beyond the city lookup.
- Instructions – 1: The User should provide a Zip code. If the user has not provided a Zip code, prompt them to provide one.
- Instructions – 2: The given zip code should be valid. If the user enters an invalid zip code, prompt them to enter a valid one.

As you open the topic, click the This Topic’s Actions option. Since we just created this topic, we haven’t added any action for it.
Now, to add the created action, click the New button -> Add from Asset Library.

Then, select the action you want to assign to this agent. You can also select multiple actions, including both standard and custom options. Then click the Finish button.
Here, we have created a ZipCodeName action, which was generated from the apex class in Salesforce Agentforce.
Then click the Finish button. We have successfully created a custom action to retrieve external data via APIs in Salesforce Agentforce and added it to the service agent. Next, we need to Activate the agent.

Now, in the image below, you can see that when the customer asked the Agentforce service agent to provide the city name for the ZIP code they entered, the agent responded correctly with the city name.
This is possible because we created the Custom Action, connected it to the external API, and added the Apex class to fetch the ZIP code details in real time.

In this way, we can retrieve any information that is not stored in Salesforce by using a Custom Action, an Apex class, and an external API.
Conclusion
I hope you now have a clear idea of how to create a Custom Action in Salesforce Agentforce to retrieve external data using APIs.
With this setup, whenever a customer or user asks for information that is not stored in Salesforce, the agent can trigger the Custom Action, call the external API, fetch the required details in real time, and provide an accurate response to the customer.
You may like to read:
- Transfer Customer Request From AI Agent to Human Agent in Salesforce Agentforce
- Create & Assign Custom Actions to AI Agents in Salesforce Agentforce
- Deploy Agentforce Service Agent to Slack Workspace in Salesforce
- Prompt Builder and Prompt Template in Salesforce Agentforce

Shubham is a Certified Salesforce Developer with technical skills for Building applications using custom objects, approval processes, validation rule salesforce flows, and UI customization. He is proficient in writing Apex classes, triggers, controllers, Apex Batches, and bulk load APIs. I am also familiar with Visualforce Pages and Lighting Web Components. Read more | LinkedIn Profile