Web Messaging: Can't close guest session via Conversations API

Just noticed that we can’t seem to terminate a web messaging session from the backend. I’m building a cleanup script to handle idle sessions, but the standard POST /api/v2/conversations/{conversationId}/participants/{participantId}/remove endpoint isn’t working like it does for voice or chat.

I’m passing the conversation ID and the participant ID (the guest’s ID, not the agent’s), with the right scopes (conversation:write), but it just returns a 400 Bad Request with “Participant not found in conversation.”

Here’s the payload I’m sending:

{
 "reason": "timeout"
}

The conversation is definitely active, and I can see the participant in the GET response. Is there a different endpoint for web messaging specifically? Or do I need to call the Guest API instead?

Also tried DELETE /api/v2/conversations/{conversationId}/participants/{participantId} but that gives a 405 Method Not Allowed. Feels like there’s a specific flag or action I’m missing for web chat channels.

I’d recommend looking at at the specific endpoint for web messaging participants. The generic remove endpoint you’re hitting is often reserved for internal participant management or requires different payload structures for external channels like webchat. For web messaging, you typically need to use the disconnect or delete action depending on whether you want to end the session gracefully or just drop the participant.

The issue is usually that you’re missing the reason field in the body, or you’re using the wrong HTTP method. For webchat, a simple DELETE on the participant resource often works, but if you want to ensure the session state updates correctly on the guest side, a POST with a specific body is safer.

Try this curl command instead:

curl -X POST "https://api.mynicecxone.com/api/v2/conversations/{conversationId}/participants/{participantId}/disconnect" \
 -H "Authorization: Bearer <YOUR_TOKEN>" \
 -H "Content-Type: application/json" \
 -d '{
 "reason": "idle_timeout"
 }'

If that still throws a 400, check if the participant status is already offline. The API won’t let you disconnect someone who’s already gone. You can verify the status by calling GET /api/v2/conversations/{conversationId}/participants/{participantId} first.

Also, make sure your OAuth token has the conversation:write scope, not just read. I’ve seen cases where the token was generated with limited scopes and it silently failed or returned a misleading error code.

If you’re using Python, the platformClient SDK method is ConversationsApi.post_conversations_conversation_id_participants_participant_id_disconnect. It’s a bit verbose but it handles the header formatting for you.

Don’t forget to handle the 409 Conflict if the session is already closed. It’s common in cleanup scripts. Just ignore it and move to the next ID.

This looks like a scope mismatch rather than an endpoint issue. the suggestion above about disconnect actions is partially correct, but the real blocker is usually insufficient permissions for terminating guest participants in web messaging channels. you need webchat:write alongside conversation:write.

  1. Verify your token includes both conversation:write and webchat:write.
  2. Use the remove participant endpoint, not disconnect. disconnect is for agents.
  3. Ensure the participant ID is the guest ID, not the bot or system ID.
curl -X POST "https://api.mypurecloud.com/api/v2/conversations/${conversationId}/participants/${guestParticipantId}/remove" \
 -H "Authorization: Bearer YOUR_TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
 "action": "remove",
 "reason": "idle_cleanup"
 }'

if you still get 400, check the conversation status. it must be active or queued. terminated conversations can’t be modified. also, ensure the participant hasn’t already left. the API will reject removal of non-existent participants.

we’ve seen this fail silently in Terraform modules when the state doesn’t reflect the actual conversation lifecycle. always validate the conversation status before attempting removal.

I’d suggest checking out at the payload structure again. i tried the remove endpoint earlier today and it kept failing until i realized web messaging needs a specific action field in the body, not just an empty post.

also, make sure you’re using the webchat:write scope. conversation:write isn’t enough for terminating guest sessions in this channel. here’s the curl that finally worked for me:

curl -X POST "https://api.mypurecloud.com/api/v2/conversations/{conversationId}/participants/{participantId}/remove" \
 -H "Authorization: Bearer {token}" \
 -H "Content-Type: application/json" \
 -d '{"action": "disconnect"}'

if you just send an empty body, it throws a 400. the disconnect action tells the platform to cleanly tear down the websocket session. i had to add this to my react native cleanup logic because otherwise the guest stays “active” in the dashboard for ages. annoying stuff.

It depends, but generally… the remove endpoint works fine if you strip the extra payload garbage. i’ve seen this break when migrating from Five9, but GC just wants a clean POST. check the docs here: https://developer.genesys.cloud/help/api/conversations/#remove-participant. works every time.