How to programmatically configure Web Messaging deployment colors and launcher position
What You Will Build
- One sentence: The code creates or updates a Genesys Cloud CX Web Messaging deployment with specific hex color codes and a defined launcher button position.
- One sentence: This uses the Genesys Cloud CX PureCloud Platform Client V2 SDK and the Deployments API.
- One sentence: The programming language covered is Python.
Prerequisites
- OAuth client type: Public or Confidential client with the
webmessaging:deployments:writescope. - SDK version:
genesys-cloud-sdk-purecloud-platform-client-v2>= 150.0.0. - Language/runtime requirements: Python 3.9+.
- External dependencies:
genesys-cloud-sdk-purecloud-platform-client-v2,python-dotenv(for secure credential management).
Authentication Setup
Genesys Cloud CX APIs require OAuth 2.0 Bearer tokens. For server-to-server interactions (like configuration scripts), the Client Credentials flow is the standard. You must install the SDK and set up environment variables for your Client ID and Secret.
Install the dependency:
pip install genesys-cloud-sdk-purecloud-platform-client-v2 python-dotenv
Create a .env file in your project root:
GENESYS_CLOUD_CLIENT_ID=your_client_id_here
GENESYS_CLOUD_CLIENT_SECRET=your_client_secret_here
GENESYS_CLOUD_REGION=eus05 # or us-east-1, eu-west-1, etc.
Initialize the SDK client in your Python script. The SDK handles token acquisition and refreshing automatically.
import os
from dotenv import load_dotenv
from purecloud_platform_client_v2 import Configuration, ApiClient, WebMessagingApi
load_dotenv()
def get_web_messaging_api_client():
"""
Initializes and returns the WebMessagingApi client.
"""
config = Configuration()
config.host = f"https://{os.getenv('GENESYS_CLOUD_REGION')}.mypurecloud.com/api/v2"
config.client_id = os.getenv('GENESYS_CLOUD_CLIENT_ID')
config.client_secret = os.getenv('GENESYS_CLOUD_CLIENT_SECRET')
api_client = ApiClient(configuration=config)
return WebMessagingApi(api_client)
web_messaging_api = get_web_messaging_api_client()
Implementation
Step 1: Retrieve existing deployments or create a new one
Before updating colors, you must know the Deployment ID. If you are building a fresh integration, you may need to create the deployment first. If one already exists, you must fetch it to get its ID and current state, as updates are partial (PATCH) or full (PUT) operations depending on the specific API version behavior. The WebMessagingApi uses put_web_messaging_deployment to upsert a deployment.
First, let us define the configuration payload. The Web Messaging deployment configuration is nested deeply. The critical objects are launcher and widget.
from purecloud_platform_client_v2.models import (
WebMessagingDeployment,
WebMessagingDeploymentProperties,
WebMessagingLauncherConfig,
WebMessagingWidgetConfig,
WebMessagingThemeConfig
)
def build_deployment_config(deployment_id: str, name: str, language: str = "en-US"):
"""
Constructs the WebMessagingDeployment object with custom colors and position.
"""
# 1. Define the Launcher Configuration
# This controls the floating button that opens the chat.
launcher_config = WebMessagingLauncherConfig(
# Position: 'bottom-right', 'bottom-left', 'top-right', 'top-left'
position="bottom-left",
# Offset from the edge in pixels
horizontal_offset=20,
vertical_offset=20,
# Show the launcher button
show=True,
# Custom icon URL (optional). If null, uses default Genesys icon.
icon=None
)
# 2. Define the Theme Configuration
# This controls colors for both the launcher and the widget header/body.
theme_config = WebMessagingThemeConfig(
# Primary color (launcher background, header background)
primary_color="#FF5733",
# Secondary color (text on primary background, often white or black)
secondary_color="#FFFFFF",
# Button text color
button_text_color="#FFFFFF",
# Widget background color
widget_background_color="#F4F4F4",
# Widget text color
widget_text_color="#333333",
# Header background color (can override primary)
header_background_color="#FF5733",
# Header text color
header_text_color="#FFFFFF"
)
# 3. Define the Widget Configuration
# This controls the chat window itself.
widget_config = WebMessagingWidgetConfig(
# Title displayed in the chat window header
title="Customer Support",
# Welcome message shown when chat opens
welcome_message="Hello! How can we help you today?",
# Auto-open the widget on page load (optional)
auto_open=False,
# Theme applied to the widget
theme=theme_config
)
# 4. Assemble the Deployment Properties
properties = WebMessagingDeploymentProperties(
launcher=launcher_config,
widget=widget_config,
# Ensure the deployment is active
active=True,
# Language for the interface
language=language
)
# 5. Create the Deployment Object
deployment = WebMessagingDeployment(
id=deployment_id,
name=name,
properties=properties
)
return deployment
Step 2: Execute the Update via API
The put_web_messaging_deployment method is used to create or update a deployment. If the id provided does not exist, Genesys Cloud creates a new one. If it exists, it updates the existing one with the provided properties.
OAuth Scope Required: webmessaging:deployments:write
def update_deployment(deployment: WebMessagingDeployment):
"""
Sends the deployment configuration to Genesys Cloud.
"""
try:
# The API endpoint is /api/v2/webmessaging/deployments/{deploymentId}
result = web_messaging_api.put_web_messaging_deployment(
deployment_id=deployment.id,
body=deployment
)
print(f"Deployment '{result.name}' updated successfully with ID: {result.id}")
return result
except Exception as e:
# Handle API errors
print(f"Error updating deployment: {e}")
if hasattr(e, 'status'):
print(f"HTTP Status: {e.status}")
if hasattr(e, 'reason'):
print(f"Reason: {e.reason}")
if hasattr(e, 'body'):
print(f"Response Body: {e.body}")
raise e
Step 3: Handling Idempotency and Existing IDs
In production, you rarely hardcode an ID. You typically fetch the deployment by name or check if it exists. Since there is no direct “get by name” endpoint for deployments, you usually list all deployments and find the one you want, or you manage the ID in your own database.
Here is how to list deployments to find the correct ID:
def get_deployment_by_name(name: str):
"""
Lists all web messaging deployments and returns the one matching the name.
"""
try:
# GET /api/v2/webmessaging/deployments
# Scope: webmessaging:deployments:read
result = web_messaging_api.get_web_messaging_deployments()
if result.entities:
for deployment in result.entities:
if deployment.name == name:
return deployment
return None
except Exception as e:
print(f"Error listing deployments: {e}")
return None
Complete Working Example
This script combines authentication, ID resolution, configuration building, and the API call. It is designed to be idempotent: if the deployment exists, it updates it; if not, it creates it.
import os
import sys
from dotenv import load_dotenv
from purecloud_platform_client_v2 import Configuration, ApiClient, WebMessagingApi
from purecloud_platform_client_v2.models import (
WebMessagingDeployment,
WebMessagingDeploymentProperties,
WebMessagingLauncherConfig,
WebMessagingWidgetConfig,
WebMessagingThemeConfig
)
load_dotenv()
def initialize_client():
config = Configuration()
region = os.getenv('GENESYS_CLOUD_REGION', 'eus05')
config.host = f"https://{region}.mypurecloud.com/api/v2"
config.client_id = os.getenv('GENESYS_CLOUD_CLIENT_ID')
config.client_secret = os.getenv('GENESYS_CLOUD_CLIENT_SECRET')
if not config.client_id or not config.client_secret:
raise ValueError("GENESYS_CLOUD_CLIENT_ID and GENESYS_CLOUD_CLIENT_SECRET must be set in .env")
api_client = ApiClient(configuration=config)
return WebMessagingApi(api_client)
def create_custom_deployment(api_client: WebMessagingApi, deployment_name: str):
# Step 1: Check if deployment exists
existing_deployment = None
try:
list_result = api_client.get_web_messaging_deployments()
if list_result.entities:
for dep in list_result.entities:
if dep.name == deployment_name:
existing_deployment = dep
break
except Exception as e:
print(f"Warning: Could not list deployments. Assuming new creation. Error: {e}")
deployment_id = existing_deployment.id if existing_deployment else None
# If creating new, Genesys generates the ID. We do not need to provide it in the request body for creation,
# but the SDK model requires it for updates. The SDK handles this distinction in put_ methods usually,
# but for clarity, we pass None for ID if new, and the SDK constructs the POST request.
# Note: The purecloud_platform_client_v2 SDK put_ method typically handles POST vs PUT based on ID presence.
# Step 2: Define Custom Styling
theme_config = WebMessagingThemeConfig(
primary_color="#0056b3", # Deep Blue
secondary_color="#ffffff", # White
button_text_color="#ffffff",
widget_background_color="#f8f9fa",
widget_text_color="#212529",
header_background_color="#0056b3",
header_text_color="#ffffff"
)
launcher_config = WebMessagingLauncherConfig(
position="bottom-right", # Changed to bottom-right for this example
horizontal_offset=20,
vertical_offset=20,
show=True
)
widget_config = WebMessagingWidgetConfig(
title="Tech Support Chat",
welcome_message="Hi there! An agent will be with you shortly.",
auto_open=False,
theme=theme_config
)
properties = WebMessagingDeploymentProperties(
launcher=launcher_config,
widget=widget_config,
active=True,
language="en-US"
)
# Step 3: Build Deployment Object
if deployment_id:
# Update existing
deployment = WebMessagingDeployment(
id=deployment_id,
name=deployment_name,
properties=properties
)
else:
# Create new
deployment = WebMessagingDeployment(
name=deployment_name,
properties=properties
)
# Step 4: Execute API Call
try:
if deployment_id:
print(f"Updating existing deployment: {deployment_id}")
result = api_client.put_web_messaging_deployment(deployment_id=deployment_id, body=deployment)
else:
print("Creating new deployment...")
# Note: For creation, the SDK might route to POST /api/v2/webmessaging/deployments
# The put_ method in this SDK often handles both. If it strictly requires ID for PUT,
# use post_web_messaging_deployment for creation.
# Checking SDK docs: post_web_messaging_deployment is for creation.
result = api_client.post_web_messaging_deployment(body=deployment)
print(f"Success! Deployment ID: {result.id}")
print(f"Launcher Position: {result.properties.launcher.position}")
print(f"Primary Color: {result.properties.widget.theme.primary_color}")
return result
except Exception as e:
print(f"Failed to configure deployment: {e}")
if hasattr(e, 'body'):
print(f"API Error Details: {e.body}")
sys.exit(1)
if __name__ == "__main__":
client = initialize_client()
create_custom_deployment(client, "My Custom Styled Chat")
Common Errors & Debugging
Error: 401 Unauthorized
- What causes it: The Client ID or Client Secret in your
.envfile is incorrect, or the client has not been authorized in the Genesys Cloud Admin Console under Admin > Security > OAuth clients. - How to fix it: Verify the credentials match the client created in Genesys Cloud. Ensure the client status is “Active”.
- Code showing the fix: Check the
initialize_clientfunction for empty variables.
Error: 403 Forbidden
- What causes it: The OAuth client does not have the required scope
webmessaging:deployments:write. - How to fix it: Go to Admin > Security > OAuth clients, select your client, and add the scope
webmessaging:deployments:writeunder the “Scopes” tab. Save and re-run. - Code showing the fix: No code change required. This is an admin configuration fix.
Error: 400 Bad Request - Invalid Hex Color
- What causes it: The
primary_coloror other color fields contain an invalid hex string (e.g., missing the#or containing non-hex characters). - How to fix it: Ensure all color strings start with
#and are followed by 3 or 6 valid hexadecimal digits (0-9, A-F). - Code showing the fix:
# Incorrect theme_config = WebMessagingThemeConfig(primary_color="FF5733") # Correct theme_config = WebMessagingThemeConfig(primary_color="#FF5733")
Error: 429 Too Many Requests
- What causes it: You are calling the API too frequently. Genesys Cloud enforces rate limits.
- How to fix it: Implement exponential backoff in your retry logic. The SDK does not automatically retry 429s by default in all configurations, so you should wrap the call in a retry loop.
- Code showing the fix:
import time def retry_with_backoff(func, *args, max_retries=3, **kwargs): for attempt in range(max_retries): try: return func(*args, **kwargs) except Exception as e: if hasattr(e, 'status') and e.status == 429: wait_time = 2 ** attempt print(f"Rate limited. Waiting {wait_time} seconds...") time.sleep(wait_time) else: raise e raise Exception("Max retries exceeded")