POST /api/v2/conversations/cobrowse returns 409 Conflict

Trying to kick off a cobrowse session via the API. The docs say POST /api/v2/conversations/cobrowse with the userId and sessionId.

POST /api/v2/conversations/cobrowse
{
 "userId": "12345",
 "sessionId": "abc-123"
}

Getting a 409 Conflict. Body says conversation already exists. I checked the active conversations endpoint, nothing is running. Is there a stale session lock I need to clear first? Or is the SDK handling the handshake differently than raw HTTP?

The 409 Conflict usually isn’t a stale lock. It’s the platform trying to prevent duplicate session creation for the same user context. The API is strict about the sessionId parameter. If you reuse an ID that was previously used, even if the old session is gone, Genesys might flag it as a conflict if it’s still in its internal cache for a few minutes.

You need to generate a unique sessionId for every request. Do not hardcode it. Also, check if you are missing the type field in your payload. The endpoint expects more than just userId and sessionId.

Here is the correct payload structure I use in my integration tests:

POST /api/v2/conversations/cobrowse
{
 "userId": "agent-user-id-here",
 "sessionId": "unique-uuid-v4-generated-now",
 "type": "web",
 "data": {
 "url": "https://example.com/checkout"
 }
}

If you are still getting 409 after ensuring the sessionId is fresh and unique, check the GET /api/v2/conversations/cobrowse endpoint. Sometimes a session is marked as “ended” in the summary view but still active in the cobrowse service for a short retention period.

Also, verify your OAuth scope. You need cobrowse:read and cobrowse:write. If the token lacks write, it can sometimes throw misleading errors, though usually it’s a 403. But 409 is definitely a resource conflict.

Try clearing your browser cache on the agent side too. The cobrowse client might be holding onto a stale session token. I’ve seen this happen when agents refresh the page mid-session. The API thinks the session is still alive because the client hasn’t sent the proper close signal.

If the issue persists, check the server logs for the specific conversation ID. The error response should include a conversationId. Use that to query GET /api/v2/conversations/{conversationId}. That will tell you the actual state. It might be pending or active even if it looks dead to you.

the earlier post’s got the right idea with the sessionId uniqueness, but there’s another gotcha I’ve run into with the JS SDK that often trips people up. The 409 usually means the platform thinks the conversation is still active on the server side, even if your local state says otherwise.

Check your auth headers first. If you’re reusing an expired token or missing the application/json content type, the platform might throw a conflict instead of a bad request. Also, make sure you’re actually waiting for the previous cobrowse session to fully terminate before kicking off a new one. The API doesn’t clean up instantly.

Here’s how I handle the cleanup in Node.js before starting a new session:

const { ConversationApi } = require('purecloud-platform-client-v2');

async function cleanupAndStart(userId, newSessionId) {
 const conversationApi = new ConversationApi();
 
 // List active cobrowse conversations for this user
 const active = await conversationApi.postConversationsCobrowseList({
 body: { userIds: [userId] }
 });

 if (active.entities && active.entities.length > 0) {
 console.log('Active session found, disconnecting first...');
 const convId = active.entities[0].id;
 await conversationApi.postConversationsIdDisconnect(convId, {
 body: { participantId: 'user' } // Disconnect the user side
 });
 }

 // Now start fresh
 return await conversationApi.postConversationsCobrowse({
 body: {
 userId: userId,
 sessionId: newSessionId, // Ensure this is truly unique, e.g., UUID v4
 duration: 300
 }
 });
}

Double-check that sessionId is a fresh UUID every time. Reusing one is the fastest way to get that 409.