How to programmatically close a Web Messaging session from the backend
What You Will Build
- You will build a backend service that programmatically terminates an active Genesys Cloud Web Messaging conversation.
- This tutorial uses the Genesys Cloud Platform API v2 (
/api/v2/conversations/messaging/) and the PythongenesyscloudSDK. - The implementation is written in Python 3.9+ using the
asyncioframework for high-concurrency handling.
Prerequisites
- OAuth Client Type: Machine-to-Machine (M2M) or Public Client with appropriate scopes.
- Required Scopes:
conversation:message:writeis mandatory to update conversation status.conversation:readis required if you need to fetch conversation details before closing. - SDK Version:
genesyscloudPython SDK version 140.0.0 or higher. - Runtime: Python 3.9 or higher.
- Dependencies:
genesyscloudpydantic(for data validation, optional but recommended)
Install the SDK via pip:
pip install genesyscloud
Authentication Setup
Genesys Cloud uses OAuth 2.0 for authentication. For backend services, the Machine-to-Machine (M2M) flow is the standard. This flow exchanges a client ID and client secret for an access token.
The genesyscloud SDK handles token caching and automatic refresh if you configure the PlatformClient correctly. You must provide your client_id, client_secret, and environment (e.g., mypurecloud.com or usw2.pure.cloud).
import os
from purecloudplatformclientv2 import PlatformClient
def get_platform_client() -> PlatformClient:
"""
Initialize and return the Genesys Cloud Platform Client.
"""
client_id = os.getenv("GENESYS_CLIENT_ID")
client_secret = os.getenv("GENESYS_CLIENT_SECRET")
environment = os.getenv("GENESYS_ENVIRONMENT", "mypurecloud.com")
if not client_id or not client_secret:
raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET must be set.")
pc = PlatformClient()
pc.set_environment(environment)
pc.set_client_credentials(client_id, client_secret)
# Enable automatic token refresh
pc.enable_auto_refresh()
return pc
Implementation
Step 1: Retrieve the Conversation ID
To close a session, you need the unique conversationId. In a typical Web Messaging integration, the frontend generates a temporary session ID, but the backend must map this to the Genesys Cloud conversationId if it is not passed directly.
If your frontend sends the conversationId directly (recommended for backend-initiated actions), you can skip retrieval. If you only have the sessionKey (the temporary ID used by the widget), you must query the conversation API.
However, the most robust backend pattern is to store the mapping between your internal user/session ID and the Genesys conversationId when the conversation starts. This tutorial assumes you have the conversationId.
If you do not have it, you can list recent conversations for a specific user or queue. This is expensive and should be avoided in production. Instead, ensure your frontend passes the conversationId to your backend via a secure HTTP header or body payload upon session start.
Step 2: Construct the Close Payload
To close a Web Messaging conversation, you must perform a PATCH request to the conversation endpoint. The genesyscloud SDK provides the ConversationMessagingApi class.
The key parameter is status. For Web Messaging, the valid statuses are active, closed, and abandoned. To close the session cleanly, set status to closed.
You must also provide the closeReason if your Genesys Cloud organization requires it. This is configured in the Messaging settings. If not configured, you can omit it, but it is best practice to include a reason for analytics.
The request body requires a ConversationUpdate object.
from purecloudplatformclientv2 import (
ConversationMessagingApi,
ConversationUpdate,
ConversationStatus
)
def prepare_close_payload(conversation_id: str, close_reason: str = "Agent initiated close") -> dict:
"""
Prepare the payload for closing a conversation.
"""
# Create the ConversationUpdate object
update_body = ConversationUpdate(
status="closed", # Set status to closed
close_reason=close_reason # Optional but recommended
)
return {
"conversation_id": conversation_id,
"body": update_body
}
Step 3: Execute the Close Request
Use the patch_conversations_messaging_conversation method. This method sends the PATCH request to update the conversation status.
You must handle potential errors:
404 Not Found: The conversation ID is invalid or does not exist.409 Conflict: The conversation is already closed or in a state that prevents closing.403 Forbidden: The OAuth token lacks theconversation:message:writescope.429 Too Many Requests: Rate limiting has been triggered.
import logging
from purecloudplatformclientv2.rest import ApiException
logger = logging.getLogger(__name__)
async def close_web_messaging_session(pc: PlatformClient, conversation_id: str) -> bool:
"""
Programmatically close a Web Messaging conversation.
Args:
pc: The configured PlatformClient instance.
conversation_id: The unique ID of the conversation to close.
Returns:
True if the conversation was successfully closed, False otherwise.
"""
api_instance = ConversationMessagingApi(pc)
try:
# Prepare the update body
update_body = ConversationUpdate(
status="closed",
close_reason="Backend system close"
)
# Execute the patch request
# The SDK method name is patch_conversations_messaging_conversation
api_instance.patch_conversations_messaging_conversation(
conversation_id=conversation_id,
body=update_body
)
logger.info(f"Successfully closed conversation {conversation_id}")
return True
except ApiException as e:
logger.error(f"API Exception when closing conversation {conversation_id}: {e.status} - {e.reason}")
if e.status == 404:
logger.warning(f"Conversation {conversation_id} not found.")
elif e.status == 409:
logger.warning(f"Conversation {conversation_id} is already closed or in an invalid state.")
elif e.status == 403:
logger.error(f"Permission denied. Check OAuth scopes for conversation:message:write.")
elif e