JavaScript SDK: Muting agent microphone via API during active conversation

Building a custom softphone overlay for our agents. We need a programmatic way to toggle the microphone mute state on the current conversation without triggering the UI mute button. The goal is to keep the call active and the audio channel open, but stop sending audio from the agent side.

We’re using the Genesys Cloud JavaScript SDK (@genesyscloud/purecloud-platform-client-v2). I’ve tried calling conversationApi.getConversationParticipants to find the agent participant ID, then updating the participant via conversationApi.postConversationParticipant. The payload looks like this:

{
 "id": "agent-participant-id",
 "muted": true,
 "hold": false
}

The API call succeeds with a 200 OK. The participant object in the response shows "muted": true. However, the agent’s microphone remains unmuted in the actual call. The customer can still hear the agent. The UI doesn’t update to reflect the muted state either.

I checked the conversationApi.postConversation endpoint as well. Tried sending a "muted": true flag on the conversation level. No luck. The call continues as normal.

Is there a specific property I’m missing on the participant object? Or is there a different endpoint for controlling local media streams? The SDK docs for ConversationParticipant are sparse on media control fields.

Here’s the relevant from our service:

const updateParticipant = async (conversationId, participantId) => {
 const body = { id: participantId, muted: true };
 try {
 const result = await conversationApi.postConversationParticipant(conversationId, body);
 console.log('Participant updated:', result.body);
 } catch (error) {
 console.error('Failed to mute:', error);
 }
};

The console logs the success, but the audio keeps flowing. We’ve verified the participant ID is correct by logging the full conversation details. The ID matches the agent.

Any ideas on how to actually mute the mic via API? Or is this client-side only and we need to use the WebRTC API directly? That seems messy. We’d prefer to stay within the SDK.