Trying to programmatically set a wrap-up code on an interaction immediately after the agent hangs up. The goal is to automate the closing process for a specific campaign so agents don’t have to manually select the code in the UI.
I’m using the CXone Conversations API. Here is the flow I’ve built in :
- Detect
interaction:ended event.
- Call
GetRESTProxy to fetch the interaction details using the interaction ID from the event payload.
- Extract the
routing.queueId and routing.wrapupCode from the response.
- Attempt to POST to
/api/v2/conversations/interactions/{interactionId}/wrapup.
The JSON payload I’m sending looks like this:
{
"wrapupCode": {
"id": "abc-123-def-456",
"label": "Data Collection Complete"
}
}
The id comes from a predefined list in the script context. I’ve verified the ID is valid by checking the Queue details endpoint.
The issue is the response. I’m getting a 409 Conflict error. The error body says:
{
"message": "The interaction is not in a state that allows wrap-up."
}
I’ve tried adding a delay action for 2 seconds before the REST call, thinking the state transition might take a moment. Didn’t help. Also tried waiting for 5 seconds. Still getting the 409.
I checked the interaction status in the UI right after the call ends, and it shows as “Wrapping Up”. The API docs say the interaction must be in the wrapping-up state. It seems to be in that state visually, but the API rejects it.
Is there a specific status value I should check before making the POST request? Or is there a different endpoint I should be hitting?
I’ve looked at the UpdateInteraction endpoint, but that seems to be for changing routing details, not the wrap-up code itself. I want to avoid using the internal SetWrapUpCode action because I need this logic to run outside of the standard flow for some legacy integrations.
Any ideas on what state the interaction actually needs to be in for the API to accept the wrap-up code?
The 409 Conflict usually means you’re trying to write to a resource that’s still in a transitional state. When the interaction:ended event fires, the conversation isn’t actually closed on the server side yet. The platform is still finalizing the wrap-up logic, and if you hit the API before that process completes, the server rejects the request because it thinks another process (the agent’s UI or the system’s auto-wrap) is already handling it.
You need to introduce a delay or, better yet, wait for the specific conversation:wrapup event if you’re using the SDK. If you’re sticking with REST calls via GetRESTProxy, you have to poll or wait. But there’s a simpler fix in the SDK flow. Instead of guessing when it’s safe, listen for the state change.
Here’s how I handle it in my custom desktop app using the Embeddable Client App SDK. I don’t call the API immediately on ended. I wait for the interaction to reach the WRAPPED state.
const platformClient = require('@genesyscloud/genesyscloud-sdk').platformClient;
const conversationsApi = new platformClient.ConversationsApi();
// Inside your event handler
function handleInteractionEnded(event) {
const interactionId = event.data.id;
// Don't fire immediately. Wait a beat, or better, listen for wrapup.
// For REST proxy, a 2-3 second timeout is often the minimum safe window.
setTimeout(() => {
updateWrapUpCode(interactionId);
}, 2500);
}
async function updateWrapUpCode(interactionId) {
try {
const wrapupCode = {
code: "AutomatedClose", // Must match your org's wrapup code definition
name: "Automated Close",
description: "Set via API"
};
// Use the Conversations API to update the interaction
await conversationsApi.postConversationsInteractionWrapup(interactionId, wrapupCode);
console.log("Wrapup set successfully");
} catch (error) {
if (error.status === 409) {
console.warn("Conflict: Interaction likely already wrapped. Skipping.");
} else {
console.error("Failed to set wrapup:", error);
}
}
}
Make sure your access token has the interaction:write scope, or this will fail with 401 before it even hits the conflict check.