Building a Custom Data Action to Call External APIs and Map JSON Responses in Genesys Cloud Architect
What You Will Build
- You will build a custom Python script that executes as a Genesys Cloud Data Action via the Genesys Cloud Task API.
- This script will accept input variables from a flow, make an authenticated HTTP request to an external REST API, parse the JSON response, and return mapped values to Architect variables.
- The tutorial covers Python implementation using the
requestslibrary, deployment via the Genesys Cloud API, and configuration within the Architect flow.
Prerequisites
- Genesys Cloud Environment: A Genesys Cloud organization with Administrator or Architect permissions.
- OAuth Client: A Client Credentials OAuth client with the following scopes:
task:write(to create and update the Data Action)task:read(to verify the action exists)architect:flow:write(optional, if you are creating the flow via API)
- External API: A publicly accessible REST API endpoint for testing. For this tutorial, we will use
https://jsonplaceholder.typicode.com/users/1as a mock external service. - Python Environment: Python 3.9+ with
requestsandpurecloud-platform-clientinstalled. - Dependencies:
pip install requests purecloud-platform-client
Authentication Setup
To interact with the Genesys Cloud APIs for deploying the Data Action, you must obtain an OAuth access token. The following Python code demonstrates how to retrieve a token using Client Credentials.
import requests
import json
import os
def get_genesys_access_token(client_id: str, client_secret: str, base_url: str) -> str:
"""
Retrieves an OAuth access token from Genesys Cloud using Client Credentials.
Args:
client_id: The OAuth client ID.
client_secret: The OAuth client secret.
base_url: The Genesys Cloud base URL (e.g., 'https://api.mypurecloud.com').
Returns:
The access token string.
"""
token_url = f"{base_url}/oauth/token"
# The body for Client Credentials grant
body = {
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret
}
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
try:
response = requests.post(token_url, data=body, headers=headers)
response.raise_for_status()
token_data = response.json()
return token_data["access_token"]
except requests.exceptions.HTTPError as e:
if response.status_code == 401:
raise Exception("Authentication failed. Check client ID and secret.")
elif response.status_code == 403:
raise Exception("Forbidden. The client may not have the required scopes.")
else:
raise Exception(f"HTTP Error: {response.status_code} - {response.text}")
except Exception as e:
raise Exception(f"Failed to retrieve token: {str(e)}")
Implementation
Step 1: Define the Data Action Script
The core of this tutorial is the Python script that runs inside the Genesys Cloud Data Action. This script receives input from the flow, calls the external API, and returns the result.
The script must adhere to the Genesys Cloud Data Action contract:
- Accept
inputdictionary from the flow. - Return a dictionary with
outputkeys. - Handle errors gracefully by returning an
errorkey if necessary.
Create a file named data_action_script.py. This is the code that will be uploaded to Genesys Cloud.
import requests
import json
import sys
def main(input_data):
"""
Main entry point for the Genesys Cloud Data Action.
Args:
input_data (dict): Dictionary containing inputs passed from Architect.
Returns:
dict: Dictionary containing output keys to be mapped back to Architect variables.
"""
# 1. Extract inputs from the flow
# The flow will pass 'user_id' as an integer
user_id = input_data.get("user_id")
if not user_id:
return {
"error": "Missing required input: user_id",
"success": False
}
# 2. Define the external API endpoint
# For this example, we use JSONPlaceholder
api_url = f"https://jsonplaceholder.typicode.com/users/{user_id}"
# 3. Prepare headers if authentication is needed for the external API
# In a real scenario, you might pass an API key from the flow inputs
headers = {
"Accept": "application/json",
"Content-Type": "application/json"
}
try:
# 4. Make the HTTP request
# Note: In production, always set a timeout to prevent hanging threads
response = requests.get(api_url, headers=headers, timeout=10)
# 5. Handle HTTP errors
response.raise_for_status()
# 6. Parse the JSON response
json_response = response.json()
# 7. Map specific fields to output variables
# Genesys Cloud Architect expects specific keys in the return dictionary
# These keys must match the Output Definitions in the Data Action configuration
output = {
"user_name": json_response.get("name", "Unknown"),
"user_email": json_response.get("email", "Unknown"),
"user_phone": json_response.get("phone", "Unknown"),
"success": True
}
return output
except requests.exceptions.Timeout:
return {
"error": "Request to external API timed out.",
"success": False
}
except requests.exceptions.HTTPError as e:
# Handle specific HTTP errors from the external API
if response.status_code == 404:
return {
"error": f"User not found: {user_id}",
"success": False
}
else:
return {
"error": f"External API Error: {response.status_code}",
"success": False
}
except Exception as e:
# Catch-all for any other unexpected errors
return {
"error": f"Unexpected error: {str(e)}",
"success": False
}
Step 2: Upload the Script via the Task API
Genesys Cloud Data Actions are managed via the Task API. You must create a DataAction resource and upload the script code. The script code must be base64-encoded.
The following function creates the Data Action resource in Genesys Cloud.
import base64
import os
from purecloudplatformclientv2 import (
ApiClient,
TaskApi,
DataAction,
DataActionDefinition,
DataActionInputDefinition,
DataActionOutputDefinition
)
def create_data_action(api_client: ApiClient, script_file_path: str, data_action_name: str) -> str:
"""
Creates a Data Action in Genesys Cloud and uploads the script.
Args:
api_client: The configured PureCloudPlatformClientV2 API client.
script_file_path: Path to the Python script file.
data_action_name: The name of the Data Action.
Returns:
The ID of the created Data Action.
"""
task_api = TaskApi(api_client)
# 1. Read and Base64 encode the script
with open(script_file_path, "rb") as f:
script_content = f.read()
encoded_script = base64.b64encode(script_content).decode("utf-8")
# 2. Define Input Parameters
# These must match the keys used in the Python script's input_data.get()
input_defs = [
DataActionInputDefinition(
name="user_id",
datatype="integer",
required=True,
description="The ID of the user to fetch"
)
]
# 3. Define Output Parameters
# These must match the keys returned in the Python script's output dictionary
output_defs = [
DataActionOutputDefinition(
name="user_name",
datatype="string",
description="The name of the user"
),
DataActionOutputDefinition(
name="user_email",
datatype="string",
description="The email of the user"
),
DataActionOutputDefinition(
name="user_phone",
datatype="string",
description="The phone number of the user"
),
DataActionOutputDefinition(
name="success",
datatype="boolean",
description="Whether the API call succeeded"
),
DataActionOutputDefinition(
name="error",
datatype="string",
description="Error message if success is false"
)
]
# 4. Create the Data Action Definition
definition = DataActionDefinition(
name="GetUserDetails",
description="Fetches user details from an external API",
inputs=input_defs,
outputs=output_defs,
code=encoded_script,
language="python3"
)
# 5. Create the Data Action Resource
data_action = DataAction(
name=data_action_name,
description="Data Action to call external user API",
definition=definition
)
try:
# POST /api/v2/tasks/dataactions
response = task_api.post_task_dataactions(body=data_action)
print(f"Created Data Action with ID: {response.id}")
return response.id
except Exception as e:
print(f"Failed to create Data Action: {str(e)}")
raise
Step 3: Configure the Data Action in Architect
While the API creates the backend resource, you must configure the flow in Genesys Cloud Architect.
- Open Architect in the Genesys Cloud Admin console.
- Create a new flow or edit an existing one.
- Add a Data Action node.
- In the Data Action configuration panel:
- Name: Enter a name for the step (e.g., “Fetch User Info”).
- Data Action: Select the Data Action you created via the API (
GetUserDetails). - Inputs: Map the flow variable containing the user ID to the
user_idinput. For example, if your flow has a variable{{User.ID}}, map it touser_id. - Outputs: Map the output definitions to flow variables.
user_name→{{User.Name}}user_email→{{User.Email}}user_phone→{{User.Phone}}success→{{API.Success}}error→{{API.ErrorMessage}}
Step 4: Test the Integration
To verify the integration, you can use the Test Mode in Architect.
- Click Test Mode in Architect.
- Enter a test value for the input variable (e.g.,
1for user ID). - Run the test.
- Observe the output variables. If successful,
{{API.Success}}should betrue, and{{User.Name}}should contain the name from the JSONPlaceholder API.
Complete Working Example
The following script combines authentication, Data Action creation, and script upload into a single executable module. Replace the placeholder credentials with your actual Genesys Cloud OAuth client details.
import requests
import base64
import os
from purecloudplatformclientv2 import (
ApiClient,
TaskApi,
DataAction,
DataActionDefinition,
DataActionInputDefinition,
DataActionOutputDefinition,
Configuration
)
# Configuration
CLIENT_ID = os.getenv("GENESYS_CLIENT_ID")
CLIENT_SECRET = os.getenv("GENESYS_CLIENT_SECRET")
BASE_URL = "https://api.mypurecloud.com"
SCRIPT_FILE = "data_action_script.py"
DATA_ACTION_NAME = "ExternalUserLookup"
def get_access_token(client_id: str, client_secret: str, base_url: str) -> str:
token_url = f"{base_url}/oauth/token"
body = {
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret
}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(token_url, data=body, headers=headers)
response.raise_for_status()
return response.json()["access_token"]
def main():
if not CLIENT_ID or not CLIENT_SECRET:
raise Exception("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET environment variables must be set.")
# 1. Authenticate
print("Authenticating with Genesys Cloud...")
access_token = get_access_token(CLIENT_ID, CLIENT_SECRET, BASE_URL)
# 2. Configure API Client
configuration = Configuration()
configuration.host = BASE_URL
configuration.access_token = access_token
api_client = ApiClient(configuration)
# 3. Create Data Action
print("Creating Data Action...")
# Read script
if not os.path.exists(SCRIPT_FILE):
raise FileNotFoundError(f"Script file {SCRIPT_FILE} not found.")
with open(SCRIPT_FILE, "rb") as f:
script_content = f.read()
encoded_script = base64.b64encode(script_content).decode("utf-8")
# Define Inputs
input_defs = [
DataActionInputDefinition(name="user_id", datatype="integer", required=True)
]
# Define Outputs
output_defs = [
DataActionOutputDefinition(name="user_name", datatype="string"),
DataActionOutputDefinition(name="user_email", datatype="string"),
DataActionOutputDefinition(name="user_phone", datatype="string"),
DataActionOutputDefinition(name="success", datatype="boolean"),
DataActionOutputDefinition(name="error", datatype="string")
]
# Define Definition
definition = DataActionDefinition(
name="GetUserDetails",
description="Fetches user details from external API",
inputs=input_defs,
outputs=output_defs,
code=encoded_script,
language="python3"
)
# Define Data Action
data_action = DataAction(
name=DATA_ACTION_NAME,
description="Data Action for external user lookup",
definition=definition
)
# Upload
task_api = TaskApi(api_client)
try:
response = task_api.post_task_dataactions(body=data_action)
print(f"Success! Data Action created with ID: {response.id}")
print(f"Data Action Name: {response.name}")
except Exception as e:
print(f"Error creating Data Action: {str(e)}")
if __name__ == "__main__":
main()
Common Errors & Debugging
Error: 401 Unauthorized
- Cause: The OAuth token is invalid, expired, or the client credentials are incorrect.
- Fix: Verify your
GENESYS_CLIENT_IDandGENESYS_CLIENT_SECRET. Ensure the OAuth client has thetask:writescope. - Code Check: Inspect the
get_access_tokenresponse body for error details.
Error: 403 Forbidden
- Cause: The OAuth client lacks the required scopes.
- Fix: Go to the Genesys Cloud Admin console, navigate to Setup > OAuth > Clients, edit your client, and add
task:writeandtask:readscopes.
Error: Data Action Execution Timeout
- Cause: The external API call exceeds the Genesys Cloud Data Action timeout limit (typically 30-60 seconds depending on configuration).
- Fix: Optimize the external API call. Add a
timeoutparameter to therequests.get()call in your script. Ensure the external API is responsive. - Code Fix:
response = requests.get(api_url, timeout=5)
Error: Output Mapping Mismatch
- Cause: The keys returned by the Python script do not match the Output Definitions in the Data Action configuration.
- Fix: Ensure the dictionary keys in the
returnstatement ofmain()exactly match thenamefields inDataActionOutputDefinition. Case sensitivity matters.
Error: Script Syntax Error
- Cause: The Python script contains syntax errors or uses unsupported libraries.
- Fix: Genesys Cloud Data Actions support a limited set of Python libraries. Stick to standard library and
requests. Test the script locally before uploading. Check the Data Action logs in Genesys Cloud for specific syntax error messages.