PATCH /api/v2/conversations/voice/{id} failing to apply wrap-up code after call disconnect

I’m trying to push a wrap-up code to Genesys Cloud right after a voice interaction drops. The flow works fine during the active session, but once the participant state switches to disconnected, the API keeps rejecting the payload. I’ve been using the Embeddable Client App SDK to catch the conversation.participant.state change, then firing off a request to /api/v2/conversations/voice/{conversationId}.

It’s weird how the terminal state locks everything down. The docs say you can update participant data post-call, so I’m sending a PATCH with the code nested under the participant array. Here’s the JSON structure I’m pushing:
{
“participants”: [
{
“id”: “agent-participant-uuid”,
“wrapupCode”: “customer_canceled”,
“wrapUpCodeDescription”: “Caller changed their mind”
}
]
}
The response always comes back as a 409 Conflict. The error payload mentions that the conversation is already in a terminal state and refuses any participant modifications. I checked the routing queue settings and the wrap-up code definitely exists in the system. I’ve also tried switching to a PUT request just to see if the method matters, but it throws a 405 instead.

I’m wondering if the timing window is the issue. The SDK fires the disconnect event almost instantly, but maybe the backend can’t process the update if the disposition flags aren’t fully committed yet. We’ve added a 3-second delay in the callback, which sometimes works, but it feels like a race condition waiting to break. Is there a specific header I’m missing to force a late disposition update? Or does the API actually require a separate endpoint for post-interaction wrap-ups that isn’t documented in the standard conversation patch section?

The token scopes look fine but the 409 keeps popping up every time the line goes dead.