POST /api/v2/conversations/messaging/{id} returns 405 when trying to close session

What’s the correct approach to programmatically close a Web Messaging session from the backend?

Problem

The supervisor dashboard keeps showing stale chat windows when agents transfer to a queue and the guest disconnects unexpectedly. We need a clean way to terminate the conversation server-side so the queue analytics don’t count it as a dropped interaction. The admin UI handles the close button fine, but the backend automation isn’t cooperating. We’ve got a background job running in PST that checks for idle sessions, and it needs to force the state change.

Code

Trying to hit the conversations endpoint with a DELETE request. Here is what we’ve put together so far.

const response = await fetch(`https://{{mydomain}}.mygen.com/api/v2/conversations/messaging/${conversationId}`, {
 method: 'DELETE',
 headers: {
 'Authorization': `Bearer ${accessToken}`,
 'Content-Type': 'application/json'
 }
});

Error

Getting a 405 Method Not Allowed straight away. Swapped to PATCH with {"state": "closed"} and it threw a 400 Bad Request. The payload validation complains about missing participant identifiers and invalid transition targets. The token refresh is fine, OAuth isn’t the issue here.

Question

Is there a specific endpoint for terminating a guest session from the platform side, or should we be calling the Web Messaging SDK REST proxy instead? We’ve checked the routing settings and everything looks standard. The guest SDK isn’t sending the disconnect event fast enough, so the backend has to step in. It’s supposed to just end the session cleanly without leaving orphaned analytics records.

The documentation keeps pointing back to the client-side destroy method.

You’re hitting a 405 because the messaging API doesn’t expose a direct “close” method on the conversation resource like it does for voice or chat. The endpoint /api/v2/conversations/messaging/{id} is primarily for sending messages or updating attributes, not for terminating the session state. To actually end the conversation from the backend, you need to interact with the participant status.

The cleanest way to handle this is to set the participant status to “closed” for both the agent and the guest. If the guest has already disconnected, their status might already be “closed”, but the agent side might still be “active” or “queued”, keeping the conversation alive in the system. You’ll need to update the agent’s participant status using the PUT /api/v2/conversations/messaging/{conversationId}/participants/{participantId} endpoint.

Here’s how you structure the payload:

{
 "status": "closed",
 "wrapUpCode": {
 "id": "your-wrap-up-code-id"
 }
}

Make sure you have the conversation:view and conversation:write scopes on your OAuth token. If you’re using the Python SDK, it looks like this:

from platformclientv2 import ConversationApi, ConversationParticipant

conversation_api = ConversationApi()
participant_body = ConversationParticipant(status="closed")
# Ensure you have the correct participant ID for the agent
conversation_api.post_conversations_messaging_conversationid_participants_participantid(
 conversation_id="your-conversation-id",
 participant_id="agent-participant-id",
 body=participant_body
)

This forces the conversation into a closed state immediately. It won’t trigger the usual guest-initiated close events, but it will stop the timer and update the analytics correctly. Just be careful not to do this while the agent is still typing, as it might cut off their wrap-up notes.