How to Disconnect a Specific Participant from a Conference Call Using the Genesys Cloud Conversations API
What You Will Build
- A script that identifies a specific participant within an active conference conversation and forcibly disconnects them using the Genesys Cloud API.
- This tutorial uses the Genesys Cloud Platform Client SDK (Python) and direct REST API calls via
requests. - The implementation covers Python, with concepts applicable to JavaScript/TypeScript and Java environments.
Prerequisites
- OAuth Client Type: Service Account or JWT Client.
- Required Scopes:
conversation:participant:write,conversation:read. - SDK Version: Genesys Cloud Python SDK
@genesyscloud/genesyscloud-python(v2.x+). - Runtime: Python 3.8+.
- Dependencies:
genesys-cloud,requests,python-dotenv.
Authentication Setup
Genesys Cloud APIs require OAuth 2.0 authentication. For server-side integrations, a Service Account or JWT client is recommended. The following example demonstrates initializing the Genesys Cloud Platform Client using environment variables.
import os
from dotenv import load_dotenv
from purecloudplatformclientv2 import Configuration, ApiClient
# Load environment variables from .env file
load_dotenv()
def get_platform_client():
"""
Initializes and returns the Genesys Cloud Platform Client.
"""
# Configuration for the API client
configuration = Configuration(
host=os.getenv("GENESYS_CLOUD_BASE_URL", "https://api.mypurecloud.com"),
client_id=os.getenv("GENESYS_CLOUD_CLIENT_ID"),
client_secret=os.getenv("GENESYS_CLOUD_CLIENT_SECRET")
)
# Create the API client instance
api_client = ApiClient(configuration)
return api_client
Ensure your .env file contains:
GENESYS_CLOUD_CLIENT_ID=your_client_id
GENESYS_CLOUD_CLIENT_SECRET=your_client_secret
GENESYS_CLOUD_BASE_URL=https://api.mypurecloud.com
Implementation
Step 1: Retrieve the Conversation Details
Before disconnecting a participant, you must identify the specific participantId associated with the user you wish to remove. The conversation ID is typically known from your application context (e.g., passed via a webhook or stored in your database).
The GET /api/v2/conversations/{conversationId} endpoint returns the full conversation object, including the participants array. Each participant object contains a unique id and metadata such as name and externalId.
from purecloudplatformclientv2 import ConversationApi, ApiException
from typing import Optional
def get_conversation_participants(api_client: ApiClient, conversation_id: str) -> Optional[dict]:
"""
Fetches the conversation details and returns the participants list.
Args:
api_client: The initialized Genesys Cloud API client.
conversation_id: The UUID of the active conversation.
Returns:
A dictionary containing the participants list or None if an error occurs.
"""
conversation_api = ConversationApi(api_client)
try:
# Fetch the full conversation object
conversation = conversation_api.get_conversation(conversation_id)
if not conversation or not conversation.participants:
print(f"No participants found in conversation {conversation_id}")
return None
return {
"conversation_id": conversation_id,
"participants": conversation.participants
}
except ApiException as e:
if e.status == 404:
print(f"Conversation {conversation_id} not found.")
elif e.status == 401 or e.status == 403:
print(f"Authentication or permission error: {e.reason}")
else:
print(f"API Error: {e.status} - {e.reason}")
return None
Step 2: Identify the Target Participant
In a conference call, multiple participants may share the same name or have no name at all. You must match against a reliable identifier. The externalId is often the most robust field if you set it during participant creation. If externalId is not available, match against name and type (e.g., agent, user, external).
The following function iterates through the participants and returns the participantId for the target user.
def find_target_participant(participants_data: dict, target_identifier: str, identifier_type: str = "external_id") -> Optional[str]:
"""
Finds the participant ID based on a specific identifier.
Args:
participants_data: The data returned from get_conversation_participants.
target_identifier: The value to match (e.g., 'user_123', 'John Doe').
identifier_type: 'external_id' or 'name'.
Returns:
The participantId string or None if not found.
"""
participants = participants_data.get("participants", [])
for participant in participants:
if identifier_type == "external_id":
if participant.external_id == target_identifier:
return participant.id
elif identifier_type == "name":
if participant.name == target_identifier:
return participant.id
return None
Step 3: Disconnect the Participant
To disconnect a participant, you must send a POST request to /api/v2/conversations/{conversationId}/participants/{participantId}/disconnect. This endpoint requires the participantId and the conversationId.
The request body is typically empty for a standard disconnect, but you can include a reason code in some contexts. The primary action is the HTTP POST to the disconnect endpoint.
from purecloudplatformclientv2 import ConversationParticipantApi
def disconnect_participant(api_client: ApiClient, conversation_id: str, participant_id: str) -> bool:
"""
Disconnects a specific participant from a conversation.
Args:
api_client: The initialized Genesys Cloud API client.
conversation_id: The UUID of the conversation.
participant_id: The UUID of the participant to disconnect.
Returns:
True if successful, False otherwise.
"""
conversation_participant_api = ConversationParticipantApi(api_client)
try:
# The disconnect method in the SDK maps to POST /api/v2/conversations/{conversationId}/participants/{participantId}/disconnect
# It does not require a request body for basic disconnection.
conversation_participant_api.post_conversation_participant_disconnect(
conversation_id=conversation_id,
participant_id=participant_id
)
print(f"Successfully disconnected participant {participant_id} from conversation {conversation_id}")
return True
except ApiException as e:
if e.status == 404:
print(f"Participant {participant_id} or Conversation {conversation_id} not found.")
elif e.status == 409:
print(f"Conflict: Participant may already be disconnected or in a terminal state.")
elif e.status == 429:
print(f"Rate limit exceeded. Retry later.")
else:
print(f"API Error during disconnect: {e.status} - {e.reason}")
return False
Complete Working Example
The following script combines all steps into a single executable module. It loads credentials, fetches the conversation, identifies the participant by externalId, and disconnects them.
import os
from dotenv import load_dotenv
from purecloudplatformclientv2 import Configuration, ApiClient, ConversationApi, ConversationParticipantApi, ApiException
from typing import Optional
# Load environment variables
load_dotenv()
def get_platform_client() -> ApiClient:
"""Initializes the Genesys Cloud API Client."""
configuration = Configuration(
host=os.getenv("GENESYS_CLOUD_BASE_URL", "https://api.mypurecloud.com"),
client_id=os.getenv("GENESYS_CLOUD_CLIENT_ID"),
client_secret=os.getenv("GENESYS_CLOUD_CLIENT_SECRET")
)
return ApiClient(configuration)
def get_conversation_participants(api_client: ApiClient, conversation_id: str) -> Optional[list]:
"""Fetches participants from a conversation."""
conversation_api = ConversationApi(api_client)
try:
conversation = conversation_api.get_conversation(conversation_id)
return conversation.participants if conversation else []
except ApiException as e:
print(f"Error fetching conversation: {e.status} - {e.reason}")
return None
def find_participant_id(participants: list, target_external_id: str) -> Optional[str]:
"""Finds participant ID by externalId."""
for participant in participants:
if participant.external_id == target_external_id:
return participant.id
return None
def disconnect_participant(api_client: ApiClient, conversation_id: str, participant_id: str) -> bool:
"""Disconnects a participant from a conversation."""
conversation_participant_api = ConversationParticipantApi(api_client)
try:
conversation_participant_api.post_conversation_participant_disconnect(
conversation_id=conversation_id,
participant_id=participant_id
)
print(f"Participant {participant_id} disconnected successfully.")
return True
except ApiException as e:
print(f"Error disconnecting participant: {e.status} - {e.reason}")
return False
def main():
# Configuration
CONVERSATION_ID = os.getenv("TARGET_CONVERSATION_ID")
TARGET_EXTERNAL_ID = os.getenv("TARGET_PARTICIPANT_EXTERNAL_ID")
if not CONVERSATION_ID or not TARGET_EXTERNAL_ID:
print("Please set TARGET_CONVERSATION_ID and TARGET_PARTICIPANT_EXTERNAL_ID in .env")
return
# Initialize Client
api_client = get_platform_client()
# Step 1: Get Participants
print(f"Fetching participants for conversation {CONVERSATION_ID}...")
participants = get_conversation_participants(api_client, CONVERSATION_ID)
if not participants:
print("Failed to retrieve participants.")
return
# Step 2: Find Target Participant
print(f"Searching for participant with externalId: {TARGET_EXTERNAL_ID}")
participant_id = find_participant_id(participants, TARGET_EXTERNAL_ID)
if not participant_id:
print(f"Participant with externalId '{TARGET_EXTERNAL_ID}' not found in conversation.")
return
# Step 3: Disconnect
print(f"Disconnecting participant {participant_id}...")
success = disconnect_participant(api_client, CONVERSATION_ID, participant_id)
if success:
print("Operation completed successfully.")
else:
print("Operation failed.")
if __name__ == "__main__":
main()
Common Errors & Debugging
Error: 404 Not Found
- Cause: The
conversationIddoes not exist, or theparticipantIdis invalid. - Fix: Verify the
conversationIdis active. Check if the participant has already been disconnected by another process. - Code Check: Ensure you are using the correct
conversationIdfrom the Genesys Cloud platform.
Error: 403 Forbidden
- Cause: The OAuth token lacks the
conversation:participant:writescope. - Fix: Update your OAuth client permissions in the Genesys Cloud Admin Console.
- Code Check: Verify the
Configurationobject uses a client with the correct scopes.
Error: 409 Conflict
- Cause: The participant is already in a
terminatedordisconnectedstate. - Fix: Check the
statefield of the participant object before attempting disconnect. - Code Check:
if participant.state == "terminated": print("Participant already disconnected.") return
Error: 429 Too Many Requests
- Cause: Rate limiting due to high API call volume.
- Fix: Implement exponential backoff retry logic.
- Code Check: Use a library like
tenacityfor retries.from tenacity import retry, wait_exponential, stop_after_attempt @retry(wait=wait_exponential(multiplier=1, min=2, max=10), stop=stop_after_attempt(3)) def disconnect_participant_with_retry(api_client, conversation_id, participant_id): # ... disconnect logic ...