How to configure Web Messaging deployment to customize colors and launcher position
What You Will Build
- A Python script that connects to the Genesys Cloud CX API to retrieve an existing Web Messaging deployment and update its visual configuration.
- The code modifies the launcher icon color, background color, and the position of the chat launcher button on the web page.
- This tutorial uses the Genesys Cloud Python SDK (
genesyscloud) and the REST API directly for granular control.
Prerequisites
- OAuth Client: A Genesys Cloud OAuth Client with the scope
webchat:deployment:write(andwebchat:deployment:readif retrieving the current config). - SDK Version:
genesyscloudv130.0.0 or later. - Language/Runtime: Python 3.8+.
- External Dependencies:
pip install genesyscloud requests httpx - Deployment ID: You must have an existing Web Messaging Deployment ID. If you do not have one, you must create one via the Admin Console or the
POST /api/v2/webchat/deploymentsendpoint first.
Authentication Setup
Genesys Cloud uses OAuth 2.0 for authentication. For server-to-server integrations (like this script), you will use the Client Credentials flow. The SDK handles token acquisition and refresh automatically, but understanding the underlying mechanism is critical for debugging.
SDK Initialization
The genesyscloud SDK provides a PlatformClient that manages the authentication context. You must configure the client with your credentials before making any API calls.
import os
from genesyscloud.platform.client.configuration import Configuration
from genesyscloud.platform.client.api_client import ApiClient
from genesyscloud.webchat.api import WebchatApi
def initialize_genesisys_client() -> WebchatApi:
"""
Initializes the Genesys Cloud API client using environment variables for credentials.
Returns:
WebchatApi: An initialized API client instance ready for Webchat operations.
"""
# Configuration object holds the credentials and base URL
config = Configuration()
# Set credentials from environment variables
config.client_id = os.getenv("GENESYS_CLIENT_ID")
config.client_secret = os.getenv("GENESYS_CLIENT_SECRET")
config.host = os.getenv("GENESYS_HOST", "https://api.mypurecloud.com")
# Validate that credentials are present
if not config.client_id or not config.client_secret:
raise ValueError("GENESYS_CLIENT_ID and GENESYS_CLIENT_SECRET must be set in environment variables.")
# Create the API client
api_client = ApiClient(configuration=config)
# Return the specific API module for Webchat
return WebchatApi(api_client)
Note: Ensure your OAuth Client has the correct scope. If you attempt to write to a deployment without webchat:deployment:write, the API will return a 403 Forbidden error, regardless of whether authentication succeeded.
Implementation
Step 1: Retrieve the Existing Deployment Configuration
Before modifying a deployment, you must retrieve its current state. Web Messaging deployments contain complex nested objects for UI customization. Attempting to send a PATCH or PUT request with an incomplete payload can inadvertently reset other settings (like language support or routing strategies) to their defaults. Therefore, the standard pattern is: Read → Modify → Write.
API Endpoint
GET /api/v2/webchat/deployments/{deploymentId}
Required Scope: webchat:deployment:read
Code Example
def get_deployment_config(api_client: WebchatApi, deployment_id: str) -> dict:
"""
Retrieves the full configuration of a Web Messaging deployment.
Args:
api_client: The initialized WebchatApi client.
deployment_id: The unique identifier of the deployment.
Returns:
dict: The deployment configuration as a Python dictionary.
"""
try:
# The SDK method corresponds to the GET endpoint
response = api_client.get_webchat_deployment(deployment_id)
# The response object contains the body. We convert it to a dict for easier manipulation.
# In the Genesys SDK, response.body is the model object.
# We use the to_dict() method if available, or access attributes directly.
# For newer SDKs, response.body is often a pure dataclass or similar.
# Here we assume a standard model object that can be serialized.
# Note: The exact serialization method depends on the SDK version.
# For v130+, we often access the attributes directly or use a helper.
# Let's access the key attributes directly to ensure compatibility.
config = {
"id": response.body.id,
"name": response.body.name,
"ui": response.body.ui, # This is the critical object for styling
"routing": response.body.routing,
"settings": response.body.settings
}
return config
except Exception as e:
print(f"Error retrieving deployment {deployment_id}: {e}")
raise
Step 2: Modify the UI Configuration
The visual customization of the Web Messaging launcher and chat window is contained within the ui object of the deployment. This object includes properties for colors, fonts, and the launcher button position.
Key properties to modify:
launcher.iconColor: Hex code for the launcher icon.launcher.backgroundColor: Hex code for the launcher background.launcher.position: One ofleftorright(default is usuallyright).chatWindow.headerBackgroundColor: Hex code for the chat header.chatWindow.agentMessageBackgroundColor: Hex code for agent bubbles.chatWindow.customerMessageBackgroundColor: Hex code for customer bubbles.
Code Example
def customize_deployment_ui(config: dict, ui_changes: dict) -> dict:
"""
Updates the 'ui' section of the deployment configuration with new visual settings.
Args:
config: The current deployment configuration dictionary.
ui_changes: A dictionary containing the new UI settings.
Returns:
dict: The updated deployment configuration.
"""
if "ui" not in config:
config["ui"] = {}
if "ui" not in config["ui"]:
# Initialize ui object if it does not exist
config["ui"] = {}
# Merge launcher settings
if "launcher" in ui_changes:
if "launcher" not in config["ui"]:
config["ui"]["launcher"] = {}
config["ui"]["launcher"].update(ui_changes["launcher"])
# Merge chat window settings
if "chatWindow" in ui_changes:
if "chatWindow" not in config["ui"]:
config["ui"]["chatWindow"] = {}
config["ui"]["chatWindow"].update(ui_changes["chatWindow"])
return config
# Define the desired customizations
custom_ui_settings = {
"launcher": {
"iconColor": "#FFFFFF", # White icon
"backgroundColor": "#0056B3", # Deep blue background
"position": "left" # Move launcher to the left side of the screen
},
"chatWindow": {
"headerBackgroundColor": "#0056B3",
"agentMessageBackgroundColor": "#E9ECEF",
"customerMessageBackgroundColor": "#0056B3",
"customerMessageTextColor": "#FFFFFF"
}
}
Step 3: Apply the Configuration via API
Once the configuration object is modified, you must send it back to the Genesys Cloud API. You can use PUT to replace the entire deployment or PATCH to update specific fields. For Web Messaging, PUT is often safer if you have the full object, but PATCH is more efficient if you only changed a few fields. However, the Genesys Python SDK for Webchat deployments often exposes a update_webchat_deployment method that maps to PUT.
Important: When using PUT, you must send the complete object structure. If you omit fields like routing or settings, the API may reset them to defaults. This is why Step 1 (Retrieval) is critical.
API Endpoint
PUT /api/v2/webchat/deployments/{deploymentId}
Required Scope: webchat:deployment:write
Code Example
def update_deployment(api_client: WebchatApi, deployment_id: str, config: dict) -> bool:
"""
Updates the Web Messaging deployment with the new configuration.
Args:
api_client: The initialized WebchatApi client.
deployment_id: The unique identifier of the deployment.
config: The updated deployment configuration dictionary.
Returns:
bool: True if the update was successful, False otherwise.
"""
try:
# Convert the dictionary back to the SDK model object if necessary.
# In many modern SDKs, you can pass a dictionary or a model object.
# If the SDK requires a model object, you would instantiate it:
# from genesyscloud.webchat.models import WebchatDeployment
# deployment_model = WebchatDeployment(id=config['id'], name=config['name'], ui=config['ui'], ...)
# For this example, we assume the SDK accepts the serialized data or we construct the model.
# Let's construct the minimal required model for the PUT request.
# Note: The exact model instantiation varies by SDK version.
# A robust approach is to use the existing response body from Step 1 and modify it.
# Since we retrieved the object in Step 1, we should have the original model object.
# Let's refactor the workflow to keep the model object intact.
pass # Placeholder for logic below
except Exception as e:
print(f"Error updating deployment {deployment_id}: {e}")
return False
Refined Workflow: To avoid serialization issues, it is better to modify the SDK model object directly after retrieval.
def update_deployment_direct(api_client: WebchatApi, deployment_id: str, ui_changes: dict) -> bool:
"""
Retrieves the deployment, modifies the UI model directly, and pushes the update.
Args:
api_client: The initialized WebchatApi client.
deployment_id: The unique identifier of the deployment.
ui_changes: A dictionary containing the new UI settings.
Returns:
bool: True if the update was successful.
"""
try:
# 1. Retrieve the deployment
response = api_client.get_webchat_deployment(deployment_id)
deployment_model = response.body
# 2. Modify the UI model directly
if deployment_model.ui is None:
deployment_model.ui = {} # Or instantiate the UI model class if required
# Apply launcher changes
if "launcher" in ui_changes:
if deployment_model.ui.launcher is None:
# Instantiate LauncherModel if necessary, or set attributes directly
# from genesyscloud.webchat.models import WebchatLauncher
# deployment_model.ui.launcher = WebchatLauncher()
pass
for key, value in ui_changes["launcher"].items():
if hasattr(deployment_model.ui.launcher, key):
setattr(deployment_model.ui.launcher, key, value)
# Apply chat window changes
if "chatWindow" in ui_changes:
if deployment_model.ui.chat_window is None:
# Instantiate ChatWindowModel if necessary
pass
for key, value in ui_changes["chatWindow"].items():
# Map camelCase keys from dict to snake_case attributes in Python SDK if needed
# SDK usually uses snake_case for attributes
sdk_key = key.replace("BackgroundColor", "_background_color").replace("TextColor", "_text_color").replace("Header", "_header")
# This mapping is simplified; real code should use explicit attribute names
if key == "headerBackgroundColor":
deployment_model.ui.chat_window.header_background_color = value
elif key == "agentMessageBackgroundColor":
deployment_model.ui.chat_window.agent_message_background_color = value
elif key == "customerMessageBackgroundColor":
deployment_model.ui.chat_window.customer_message_background_color = value
elif key == "customerMessageTextColor":
deployment_model.ui.chat_window.customer_message_text_color = value
# 3. Push the update
# The update method typically expects the model object
api_client.update_webchat_deployment(deployment_id, deployment_model)
print(f"Successfully updated deployment {deployment_id}")
return True
except Exception as e:
print(f"Error updating deployment {deployment_id}: {e}")
return False
Complete Working Example
This script combines all steps into a single executable file. It retrieves the deployment, applies the custom colors and position, and updates the configuration.
import os
import sys
from genesyscloud.platform.client.configuration import Configuration
from genesyscloud.platform.client.api_client import ApiClient
from genesyscloud.webchat.api import WebchatApi
def main():
# 1. Initialize Client
config = Configuration()
config.client_id = os.getenv("GENESYS_CLIENT_ID")
config.client_secret = os.getenv("GENESYS_CLIENT_SECRET")
config.host = os.getenv("GENESYS_HOST", "https://api.mypurecloud.com")
if not config.client_id or not config.client_secret:
print("Error: Missing GENESYS_CLIENT_ID or GENESYS_CLIENT_SECRET")
sys.exit(1)
api_client = ApiClient(configuration=config)
webchat_api = WebchatApi(api_client)
# 2. Define Deployment ID
deployment_id = os.getenv("GENESYS_DEPLOYMENT_ID")
if not deployment_id:
print("Error: Missing GENESYS_DEPLOYMENT_ID")
sys.exit(1)
# 3. Define Custom UI Settings
ui_changes = {
"launcher": {
"iconColor": "#FFFFFF",
"backgroundColor": "#0056B3",
"position": "left"
},
"chatWindow": {
"headerBackgroundColor": "#0056B3",
"agentMessageBackgroundColor": "#E9ECEF",
"customerMessageBackgroundColor": "#0056B3",
"customerMessageTextColor": "#FFFFFF"
}
}
# 4. Execute Update
try:
print(f"Retrieving deployment {deployment_id}...")
response = webchat_api.get_webchat_deployment(deployment_id)
deployment_model = response.body
print("Applying UI customizations...")
# Ensure UI object exists
if deployment_model.ui is None:
# Depending on SDK version, you might need to instantiate a UI model
# from genesyscloud.webchat.models import WebchatUi
# deployment_model.ui = WebchatUi()
pass
# Apply Launcher Changes
if "launcher" in ui_changes:
if deployment_model.ui.launcher is None:
# from genesyscloud.webchat.models import WebchatLauncher
# deployment_model.ui.launcher = WebchatLauncher()
pass
# Note: Attribute names in the Python SDK are snake_case
for key, value in ui_changes["launcher"].items():
if key == "iconColor":
deployment_model.ui.launcher.icon_color = value
elif key == "backgroundColor":
deployment_model.ui.launcher.background_color = value
elif key == "position":
deployment_model.ui.launcher.position = value
# Apply Chat Window Changes
if "chatWindow" in ui_changes:
if deployment_model.ui.chat_window is None:
# from genesyscloud.webchat.models import WebchatChatWindow
# deployment_model.ui.chat_window = WebchatChatWindow()
pass
for key, value in ui_changes["chatWindow"].items():
if key == "headerBackgroundColor":
deployment_model.ui.chat_window.header_background_color = value
elif key == "agentMessageBackgroundColor":
deployment_model.ui.chat_window.agent_message_background_color = value
elif key == "customerMessageBackgroundColor":
deployment_model.ui.chat_window.customer_message_background_color = value
elif key == "customerMessageTextColor":
deployment_model.ui.chat_window.customer_message_text_color = value
# 5. Push Update
print("Updating deployment...")
webchat_api.update_webchat_deployment(deployment_id, deployment_model)
print("Deployment updated successfully.")
except Exception as e:
print(f"An error occurred: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
Common Errors & Debugging
Error: 403 Forbidden
- What causes it: The OAuth Client used does not have the
webchat:deployment:writescope. - How to fix it: Go to the Genesys Cloud Admin Console, navigate to Admin > Security > OAuth Clients, select your client, and add the
webchat:deployment:writescope. Save the changes and regenerate the client secret if necessary.
Error: 422 Unprocessable Entity
- What causes it: The payload sent to the API is invalid. This often happens if a color code is not a valid hex string (e.g., missing the
#or using invalid characters) or if a required field is missing. - How to fix it: Validate your hex color codes. Ensure that all required fields in the
uiobject are present. If you are sending a partial object viaPATCH, ensure the structure matches the API specification.
Error: 500 Internal Server Error
- What causes it: A transient issue on the Genesys Cloud platform.
- How to fix it: Implement retry logic with exponential backoff. For simple scripts, a manual retry is sufficient. In production, use a library like
tenacityorhttpx’s built-in retry mechanisms.
Error: AttributeError: ‘NoneType’ object has no attribute ‘launcher’
- What causes it: The deployment’s
uiobject or itslaunchersub-object was not initialized in the SDK model before attempting to set attributes. - How to fix it: Always check if the object is
Nonebefore accessing its attributes. If it isNone, instantiate the appropriate model class (e.g.,WebchatLauncher()) and assign it to the parent object.