Send Canned Responses in Genesys Cloud Chat via the Conversations API
What You Will Build
- A script that authenticates to Genesys Cloud and sends a pre-configured canned response to an active chat conversation.
- This tutorial uses the Genesys Cloud Platform API v2, specifically the Conversations and Messaging endpoints.
- The implementation uses Python with the
requestslibrary and the official Genesys Cloud Python SDK.
Prerequisites
- OAuth Client Type: Confidential Client (Client Credentials Grant) or Authorization Code Grant with PKCE. For this backend automation example, we use Client Credentials.
- Required Scopes:
conversation:chat:write(to send messages in a chat)cannedresponse:read(to fetch the canned response text if needed, though often you just need the ID)user:read(optional, for debugging user context)
- SDK Version:
genesys-cloud-purecloud-platform-client>= 110.0.0 - Language/Runtime: Python 3.8+
- External Dependencies:
requestsgenesys-cloud-purecloud-platform-clientpyyaml(for optional config loading)
Authentication Setup
Genesys Cloud APIs require OAuth 2.0 authentication. For server-to-server interactions (like sending a canned response from a bot or backend service), the Client Credentials Grant is the standard flow. You must obtain an access token and refresh it before expiration.
The following code sets up the client and handles token acquisition. We use the SDK’s built-in authentication manager, which simplifies token caching and refresh logic.
import os
from purecloudplatform.client import PlatformClient
from purecloudplatform.client.rest import ApiException
def get_platform_client(client_id: str, client_secret: str, env_name: str = "mypurecloud.com") -> PlatformClient:
"""
Initializes and returns a configured Genesys Cloud PlatformClient.
Args:
client_id: The OAuth client ID.
client_secret: The OAuth client secret.
env_name: The Genesys Cloud environment (e.g., 'mypurecloud.com').
Returns:
PlatformClient instance ready for API calls.
"""
client = PlatformClient()
# Configure the OAuth settings
client.set_config(
client_id=client_id,
client_secret=client_secret,
env_name=env_name
)
# Get the access token. The SDK handles caching and automatic refresh.
try:
token = client.get_access_token()
if not token:
raise Exception("Failed to obtain access token")
return client
except ApiException as e:
print(f"Authentication failed: {e}")
raise
# Load credentials from environment variables for security
CLIENT_ID = os.getenv("GENESYS_CLIENT_ID")
CLIENT_SECRET = os.getenv("GENESYS_CLIENT_SECRET")
if not CLIENT_ID or not CLIENT_SECRET:
raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET environment variables must be set.")
platform_client = get_platform_client(CLIENT_ID, CLIENT_SECRET)
Implementation
Step 1: Identify the Conversation and Canned Response
Before sending a message, you must identify the specific chat conversation ID and the canned response ID. In a real-world scenario, you might receive the conversation ID from a webhook or event stream. For this tutorial, we assume you have the conversation_id and the canned_response_id.
If you do not have the canned response ID, you can search for it using the Canned Responses API.
from purecloudplatform.client.api import CannedresponsesApi
from purecloudplatform.client.rest import ApiException
def find_canned_response_by_name(api_client: PlatformClient, canned_response_name: str) -> str:
"""
Searches for a canned response by name and returns its ID.
Args:
api_client: The PlatformClient instance.
canned_response_name: The name of the canned response to find.
Returns:
The ID of the canned response.
Raises:
ApiException: If the API call fails.
ValueError: If no canned response is found.
"""
canned_responses_api = CannedresponsesApi(api_client)
try:
# Search for canned responses. Limit to 1 for efficiency.
response = canned_responses_api.post_im_cannedresponses_search(
body={
"query": canned_response_name,
"limit": 1
}
)
if response.results and len(response.results) > 0:
return response.results[0].id
else:
raise ValueError(f"No canned response found with name: {canned_response_name}")
except ApiException as e:
print(f"Error searching for canned response: {e}")
raise
# Example: Find a canned response named "Welcome"
# canned_response_id = find_canned_response_by_name(platform_client, "Welcome")
Step 2: Construct the Chat Message Payload
To send a message in a chat conversation, you use the POST /api/v2/conversations/chats/messages endpoint. The request body must be a ChatMessageRequest object.
Key fields in the request:
text: The content of the message. If you are using a canned response, you typically fetch the text content of the canned response and insert it here. Alternatively, if you are just sending a static string, you put that here.fromUserId: The ID of the user (agent or bot) sending the message. This is crucial for routing and display purposes.type: Usuallyuserfor agent/bot messages.
Note: Genesys Cloud does not have a specific “send canned response” API endpoint for chats. You fetch the canned response text and send it as a standard chat message. This gives you control over formatting and dynamic content insertion.
from purecloudplatform.client.api import ConversationsApi
from purecloudplatform.client.rest import ApiException
from purecloudplatform.client.model.chat_message_request import ChatMessageRequest
from purecloudplatform.client.model.chat_message_participant import ChatMessageParticipant
def send_canned_response_message(
api_client: PlatformClient,
conversation_id: str,
canned_response_text: str,
sender_user_id: str
) -> dict:
"""
Sends a chat message containing the canned response text.
Args:
api_client: The PlatformClient instance.
conversation_id: The ID of the chat conversation.
canned_response_text: The text content of the canned response.
sender_user_id: The ID of the user sending the message.
Returns:
The response from the API.
Raises:
ApiException: If the API call fails.
"""
conversations_api = ConversationsApi(api_client)
# Construct the participant object for the sender
sender = ChatMessageParticipant(
id=sender_user_id,
type="user"
)
# Construct the chat message request
message_request = ChatMessageRequest(
text=canned_response_text,
from_user_id=sender_user_id,
type="user"
)
try:
# Send the message to the conversation
response = conversations_api.post_conversations_chat_messages(
conversation_id=conversation_id,
body=message_request
)
print(f"Message sent successfully. Message ID: {response.id}")
return response
except ApiException as e:
if e.status == 404:
print(f"Conversation {conversation_id} not found.")
elif e.status == 403:
print(f"Insufficient permissions to send message in conversation {conversation_id}.")
elif e.status == 429:
print("Rate limited. Please retry after the Retry-After header duration.")
else:
print(f"Error sending message: {e}")
raise
# Example: Send the message
# conversation_id = "123e4567-e89b-12d3-a456-426614174000"
# sender_user_id = "987fcdeb-51a2-3b4c-d6e7-f89012345678"
# canned_text = "Hello! How can I help you today?"
# send_canned_response_message(platform_client, conversation_id, canned_text, sender_user_id)
Step 3: Fetch Canned Response Text and Send
In this final step, we combine the previous functions to fetch the canned response text and send it. We also add error handling for common issues like invalid IDs or network errors.
from purecloudplatform.client.api import CannedresponsesApi
def send_canned_response_via_id(
api_client: PlatformClient,
conversation_id: str,
canned_response_id: str,
sender_user_id: str
) -> dict:
"""
Fetches a canned response by ID and sends its text to a chat conversation.
Args:
api_client: The PlatformClient instance.
conversation_id: The ID of the chat conversation.
canned_response_id: The ID of the canned response.
sender_user_id: The ID of the user sending the message.
Returns:
The response from the message send API.
Raises:
ApiException: If the API call fails.
ValueError: If the canned response is not found.
"""
canned_responses_api = CannedresponsesApi(api_client)
# Step 1: Get the canned response details
try:
canned_response = canned_responses_api.get_cannedresponse(
canned_response_id=canned_response_id
)
if not canned_response or not canned_response.text:
raise ValueError(f"Canned response {canned_response_id} has no text.")
canned_text = canned_response.text
except ApiException as e:
if e.status == 404:
raise ValueError(f"Canned response {canned_response_id} not found.")
else:
raise
# Step 2: Send the message
return send_canned_response_message(
api_client=api_client,
conversation_id=conversation_id,
canned_response_text=canned_text,
sender_user_id=sender_user_id
)
Complete Working Example
The following script combines all the steps into a single, runnable example. It fetches a canned response by name, sends it to a specified chat conversation, and handles errors.
import os
import sys
from purecloudplatform.client import PlatformClient
from purecloudplatform.client.rest import ApiException
from purecloudplatform.client.api import CannedresponsesApi, ConversationsApi
from purecloudplatform.client.model.chat_message_request import ChatMessageRequest
def get_platform_client(client_id: str, client_secret: str, env_name: str = "mypurecloud.com") -> PlatformClient:
client = PlatformClient()
client.set_config(
client_id=client_id,
client_secret=client_secret,
env_name=env_name
)
try:
token = client.get_access_token()
if not token:
raise Exception("Failed to obtain access token")
return client
except ApiException as e:
print(f"Authentication failed: {e}")
sys.exit(1)
def find_canned_response_by_name(api_client: PlatformClient, canned_response_name: str) -> str:
canned_responses_api = CannedresponsesApi(api_client)
try:
response = canned_responses_api.post_im_cannedresponses_search(
body={
"query": canned_response_name,
"limit": 1
}
)
if response.results and len(response.results) > 0:
return response.results[0].id
else:
raise ValueError(f"No canned response found with name: {canned_response_name}")
except ApiException as e:
print(f"Error searching for canned response: {e}")
raise
def send_canned_response_message(
api_client: PlatformClient,
conversation_id: str,
canned_response_text: str,
sender_user_id: str
) -> dict:
conversations_api = ConversationsApi(api_client)
message_request = ChatMessageRequest(
text=canned_response_text,
from_user_id=sender_user_id,
type="user"
)
try:
response = conversations_api.post_conversations_chat_messages(
conversation_id=conversation_id,
body=message_request
)
print(f"Message sent successfully. Message ID: {response.id}")
return response
except ApiException as e:
print(f"Error sending message: {e}")
raise
def main():
# Configuration
CLIENT_ID = os.getenv("GENESYS_CLIENT_ID")
CLIENT_SECRET = os.getenv("GENESYS_CLIENT_SECRET")
CONVERSATION_ID = os.getenv("GENESYS_CONVERSATION_ID")
SENDER_USER_ID = os.getenv("GENESYS_SENDER_USER_ID")
CANNED_RESPONSE_NAME = os.getenv("GENESYS_CANNED_RESPONSE_NAME", "Welcome")
if not all([CLIENT_ID, CLIENT_SECRET, CONVERSATION_ID, SENDER_USER_ID]):
print("Missing required environment variables.")
sys.exit(1)
try:
# 1. Authenticate
platform_client = get_platform_client(CLIENT_ID, CLIENT_SECRET)
# 2. Find Canned Response
canned_response_id = find_canned_response_by_name(platform_client, CANNED_RESPONSE_NAME)
print(f"Found canned response ID: {canned_response_id}")
# 3. Get Canned Response Text
canned_responses_api = CannedresponsesApi(platform_client)
canned_response = canned_responses_api.get_cannedresponse(canned_response_id=canned_response_id)
canned_text = canned_response.text
# 4. Send Message
send_canned_response_message(
api_client=platform_client,
conversation_id=CONVERSATION_ID,
canned_response_text=canned_text,
sender_user_id=SENDER_USER_ID
)
except Exception as e:
print(f"An error occurred: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
Common Errors & Debugging
Error: 401 Unauthorized
- Cause: The OAuth token is invalid, expired, or missing.
- Fix: Ensure the
GENESYS_CLIENT_IDandGENESYS_CLIENT_SECRETare correct. Check that the client has the required scopes (conversation:chat:write). The SDK handles token refresh, but if the client credentials are wrong, the initial token fetch will fail.
Error: 403 Forbidden
- Cause: The OAuth client or user does not have permission to send messages in the specified conversation.
- Fix: Verify that the
sender_user_idis a valid user ID and that the user is associated with the conversation. Ensure the OAuth client has theconversation:chat:writescope. If using a bot user, ensure it has the necessary permissions.
Error: 404 Not Found
- Cause: The
conversation_idorcanned_response_idis invalid. - Fix: Double-check the IDs. Use the Genesys Cloud Admin UI to verify the existence of the canned response and the conversation.
Error: 429 Too Many Requests
- Cause: You have exceeded the API rate limit.
- Fix: Implement retry logic with exponential backoff. The API response includes a
Retry-Afterheader indicating the number of seconds to wait.
import time
from purecloudplatform.client.rest import ApiException
def send_with_retry(api_call_func, max_retries=3):
for attempt in range(max_retries):
try:
return api_call_func()
except ApiException as e:
if e.status == 429:
retry_after = int(e.headers.get('Retry-After', 1))
print(f"Rate limited. Retrying in {retry_after} seconds...")
time.sleep(retry_after)
else:
raise
raise Exception("Max retries exceeded")