Setting wrap-up code via /api/v2/conversations/{id} after interaction ended

GET /api/v2/conversations/voice/{conversationId}/wrapup returns 409 Conflict.

We are trying to set the wrap-up code programmatically from our custom C# agent desktop app using the Embeddable Client App SDK. The flow is straightforward. We detect when the call ends, wait for the interaction state to change to ENDED, and then attempt to apply the wrap-up code.

The issue is timing. If we send the PUT request immediately after the conversation:ended event fires, we get a 409. The response body says "message":"The conversation is not in a state that allows this action.".

Here is the C# code we are using to make the request:

var client = new RestClient("https://mycompany.mypurecloud.com");
var request = new RestRequest($"/api/v2/conversations/voice/{conversationId}/wrapup", Method.Put);
request.AddHeader("Authorization", $"Bearer {accessToken}");
request.AddHeader("Content-Type", "application/json");

var body = new {
 code = new { id = "wrapup-code-id-123" },
 durationMs = 0
};

request.AddJsonBody(body);
var response = await client.ExecuteAsync(request);

I have checked the interaction state via the API just before the PUT. It shows state: "ENDED". The docs say you can set wrap-up on ended conversations. But it seems like there is a race condition with the backend finalizing the interaction record.

If I add a hardcoded Thread.Sleep(5000) before the request, it works. But that feels wrong. We can’t just sleep in the UI thread.

Is there a specific event in the WebSocket stream that indicates the conversation is ready for wrap-up modification? Or is there a retry strategy that is standard for this endpoint? The 409 doesn’t give much detail other than the generic state error.