Sending Structured Messages (Quick Replies, Cards) via the Open Messaging API
What You Will Build
You will build a Python script that sends interactive rich media messages, including quick reply buttons and carousel cards, to a user via the Genesys Cloud Open Messaging API. This tutorial uses the Genesys Cloud Python SDK (genesyscloud) to construct and transmit complex MessagingEvent payloads. The code covers authentication, message construction, and error handling for 4xx and 5xx responses.
Prerequisites
- OAuth Client Type: A Genesys Cloud OAuth client with the
messaging:sendscope. - SDK Version:
genesyscloudSDK version 10.0.0 or later. - Runtime: Python 3.8+.
- Dependencies:
pip install genesyscloud - Environment Variables:
GENESYS_CLOUD_REGION: e.g.,us-east-1GENESYS_CLOUD_CLIENT_ID: Your OAuth client ID.GENESYS_CLOUD_CLIENT_SECRET: Your OAuth client secret.GENESYS_CLOUD_ORGANIZATION_ID: Your organization ID.
Authentication Setup
The Genesys Cloud API requires OAuth 2.0 Client Credentials grant flow. The SDK handles token acquisition and refresh automatically if configured correctly. You must initialize the PlatformClient with the correct region and credentials.
import os
from purecloudplatformclientv2 import PlatformClient
from purecloudplatformclientv2.api import MessagingApi
def get_messaging_api() -> MessagingApi:
"""
Initializes and returns an authenticated MessagingApi instance.
"""
# 1. Initialize the Platform Client
platform = PlatformClient()
# 2. Configure OAuth
client_id = os.environ.get("GENESYS_CLOUD_CLIENT_ID")
client_secret = os.environ.get("GENESYS_CLOUD_CLIENT_SECRET")
region = os.environ.get("GENESYS_CLOUD_REGION", "us-east-1")
if not client_id or not client_secret:
raise ValueError("GENESYS_CLOUD_CLIENT_ID and GENESYS_CLOUD_CLIENT_SECRET must be set.")
# Configure the OAuth client
platform.oauth_client.set_client_id(client_id)
platform.oauth_client.set_client_secret(client_secret)
platform.oauth_client.set_region(region)
# 3. Return the Messaging API client
return MessagingApi(platform.api_client)
Scope Requirement: The OAuth client must have the messaging:send scope. Without this scope, the API will return a 403 Forbidden error.
Implementation
Step 1: Constructing a Quick Reply Message
Quick replies allow users to respond with a single tap. In the Open Messaging API, these are represented as Button objects within a Template or directly as Message components. We will construct a simple message with two quick reply options.
The core object is MessagingEvent. For sending a message, the type must be send. The content object contains the actual message payload.
from purecloudplatformclientv2.models import (
MessagingEvent,
Message,
Button,
Template,
ExternalConversationReference
)
def build_quick_reply_event(user_id: str, channel_id: str) -> MessagingEvent:
"""
Builds a MessagingEvent containing a text message with quick reply buttons.
"""
# 1. Define the buttons
button_yes = Button(
type="button",
text="Yes",
value="yes_confirmed"
)
button_no = Button(
type="button",
text="No",
value="no_declined"
)
# 2. Define the main message text
text_message = Message(
type="text",
text="Do you want to schedule a follow-up call?"
)
# 3. Construct the template
# Note: Some channels require templates to be pre-approved.
# For raw API usage, we often structure this as a composite message.
template = Template(
type="template",
template_type="quick_reply",
content=[text_message],
buttons=[button_yes, button_no]
)
# 4. Define the external conversation reference
# This links the message to a specific user on a specific channel
ext_ref = ExternalConversationReference(
id=user_id,
channel_id=channel_id,
provider_id="messenger" # Example provider
)
# 5. Construct the final event
event = MessagingEvent(
type="send",
content=template,
external_conversation_reference=ext_ref
)
return event
Key Parameters:
type: Must besendfor outgoing messages.external_conversation_reference: Identifies the recipient. Theidis typically the user’s ID on the provider platform (e.g., Facebook Page Scoped ID), andchannel_idis the Genesys Cloud channel ID.buttons: A list ofButtonobjects. Thevaluefield is what Genesys Cloud receives when the user clicks the button.
Step 2: Constructing a Carousel Card Message
Carousel cards allow you to send multiple cards (images, titles, descriptions, buttons) that the user can scroll through horizontally. This is supported on channels like Facebook Messenger and Webchat.
from purecloudplatformclientv2.models import (
Card,
Image,
Button,
Template,
Message,
ExternalConversationReference,
MessagingEvent
)
def build_carousel_event(user_id: str, channel_id: str) -> MessagingEvent:
"""
Builds a MessagingEvent containing a carousel of product cards.
"""
# 1. Create the first card
card_1_image = Image(
url="https://example.com/images/product1.jpg"
)
card_1_button = Button(
type="button",
text="View Product",
url="https://example.com/product1"
)
card_1 = Card(
type="card",
title="Product One",
subtitle="High-quality widget",
image=card_1_image,
buttons=[card_1_button]
)
# 2. Create the second card
card_2_image = Image(
url="https://example.com/images/product2.jpg"
)
card_2_button = Button(
type="button",
text="View Product",
url="https://example.com/product2"
)
card_2 = Card(
type="card",
title="Product Two",
subtitle="Durable gadget",
image=card_2_image,
buttons=[card_2_button]
)
# 3. Construct the template
template = Template(
type="template",
template_type="carousel",
cards=[card_1, card_2]
)
# 4. Define the external conversation reference
ext_ref = ExternalConversationReference(
id=user_id,
channel_id=channel_id,
provider_id="messenger"
)
# 5. Construct the final event
event = MessagingEvent(
type="send",
content=template,
external_conversation_reference=ext_ref
)
return event
Key Parameters:
template_type: Set tocarousel.cards: A list ofCardobjects. Each card can have animage,title,subtitle, andbuttons.Button.type: For URLs, useurlbuttons. For postbacks, usebuttonwith avalue.
Step 3: Sending the Message via API
Now that we have the MessagingEvent object, we send it using the post_messaging_messaging_events method. This method accepts a list of events, allowing for batch sending.
def send_message(api: MessagingApi, event: MessagingEvent) -> dict:
"""
Sends a single messaging event and returns the response.
Handles common HTTP errors.
"""
try:
# The API expects a list of events
response = api.post_messaging_messaging_events(body=[event])
# Check for success
if response and response.body and len(response.body) > 0:
result = response.body[0]
print(f"Message sent successfully. Event ID: {result.id}")
return result
else:
print("No response body returned.")
return None
except Exception as e:
# Handle API exceptions
print(f"Error sending message: {e}")
raise
Complete Working Example
This script combines authentication, message construction, and sending. It demonstrates sending a quick reply message.
import os
from purecloudplatformclientv2 import PlatformClient
from purecloudplatformclientv2.api import MessagingApi
from purecloudplatformclientv2.models import (
MessagingEvent,
Message,
Button,
Template,
ExternalConversationReference
)
def get_messaging_api() -> MessagingApi:
"""
Initializes and returns an authenticated MessagingApi instance.
"""
platform = PlatformClient()
client_id = os.environ.get("GENESYS_CLOUD_CLIENT_ID")
client_secret = os.environ.get("GENESYS_CLOUD_CLIENT_SECRET")
region = os.environ.get("GENESYS_CLOUD_REGION", "us-east-1")
if not client_id or not client_secret:
raise ValueError("GENESYS_CLOUD_CLIENT_ID and GENESYS_CLOUD_CLIENT_SECRET must be set.")
platform.oauth_client.set_client_id(client_id)
platform.oauth_client.set_client_secret(client_secret)
platform.oauth_client.set_region(region)
return MessagingApi(platform.api_client)
def build_quick_reply_event(user_id: str, channel_id: str) -> MessagingEvent:
"""
Builds a MessagingEvent containing a text message with quick reply buttons.
"""
button_yes = Button(
type="button",
text="Yes",
value="yes_confirmed"
)
button_no = Button(
type="button",
text="No",
value="no_declined"
)
text_message = Message(
type="text",
text="Do you want to schedule a follow-up call?"
)
template = Template(
type="template",
template_type="quick_reply",
content=[text_message],
buttons=[button_yes, button_no]
)
ext_ref = ExternalConversationReference(
id=user_id,
channel_id=channel_id,
provider_id="messenger"
)
event = MessagingEvent(
type="send",
content=template,
external_conversation_reference=ext_ref
)
return event
def main():
# 1. Initialize API
api = get_messaging_api()
# 2. Define recipient
user_id = "123456789012345" # Replace with actual user ID
channel_id = "987654321098765" # Replace with actual channel ID
# 3. Build message
event = build_quick_reply_event(user_id, channel_id)
# 4. Send message
try:
response = api.post_messaging_messaging_events(body=[event])
if response.body:
for item in response.body:
if item.id:
print(f"Success: Event ID {item.id} sent.")
elif item.error:
print(f"Error: {item.error.code} - {item.error.message}")
else:
print("No response received.")
except Exception as e:
print(f"Failed to send message: {e}")
if __name__ == "__main__":
main()
Common Errors & Debugging
Error: 403 Forbidden
Cause: The OAuth client does not have the messaging:send scope.
Fix:
- Log in to the Genesys Cloud Admin portal.
- Navigate to Admin > Security > OAuth Clients.
- Select your client.
- Under Scopes, add
messaging:send. - Save the client.
- Regenerate the token or restart your application to acquire a new token with the updated scope.
Error: 400 Bad Request - Invalid Template
Cause: The template_type or structure does not match the channel’s requirements. For example, Facebook Messenger requires pre-approved templates for certain types, or the button count exceeds the limit (e.g., max 3 buttons for quick replies on some channels).
Fix:
- Check the
template_typevalue. Ensure it matches the supported types for your provider (quick_reply,carousel,generic). - Verify button limits. Facebook Messenger allows up to 3 quick reply buttons.
- Ensure image URLs are valid and accessible.
Error: 429 Too Many Requests
Cause: You have exceeded the rate limit for the messaging API.
Fix:
Implement exponential backoff in your sending logic.
import time
def send_with_retry(api: MessagingApi, event: MessagingEvent, max_retries=3):
for attempt in range(max_retries):
try:
response = api.post_messaging_messaging_events(body=[event])
return response
except Exception as e:
if "429" in str(e) and attempt < max_retries - 1:
wait_time = 2 ** attempt
print(f"Rate limited. Waiting {wait_time} seconds...")
time.sleep(wait_time)
else:
raise
Error: 404 Not Found - Conversation Not Found
Cause: The external_conversation_reference points to a user or channel that does not exist or is not connected in Genesys Cloud.
Fix:
- Verify the
user_idis correct for the provider. - Ensure the
channel_idis active and configured in Genesys Cloud. - Check that the user has initiated a conversation with the bot/channel if required by the provider (e.g., Facebook Messenger 24-hour window).