Recording API start/stop endpoints returning 403 on active conversations

Hit a weird wall this morning while trying to implement manual recording controls in our Android app. We’ve been using the Genesys Cloud Web Messaging SDK (com.genesiscloud.sdk:web-messaging) for a while, but now we need to toggle call recordings on and off based on user consent flags stored locally.

I’ve got the OAuth token handled correctly via the PlatformClient instance. I can fetch conversation details just fine. The issue is strictly with the recording lifecycle endpoints. I’m trying to hit /api/v2/recordings/recordingsessionevents to initiate a recording for an active voice conversation.

Here’s the curl equivalent of what the SDK is sending under the hood:

curl -X POST "https://api.mypurecloud.com/api/v2/recordings/recordingsessionevents" \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer <valid_token>" \
 -d '{
 "type": "start",
 "conversationId": "5f8a7b2c-1234-5678-90ab-cdef12345678",
 "reason": "compliance_consent"
 }'

The response is a hard 403 Forbidden. The error body is minimal:

{
 "message": "User does not have permission to perform this action.",
 "code": "forbidden",
 "status": 403
}

This is confusing because the user making the request has the recording:read and recording:write scopes in the OAuth client. I’ve double-checked the role assignments in the Genesys Cloud admin UI. The agent role includes the Recording permission set.

I also tried using the SDK method RecordingApi.startRecording(conversationId, reason) which wraps this same endpoint. Same 403.

I noticed in the docs there’s a mention about conversation:write permissions, but I assumed that was for modifying the conversation metadata, not the recording state. Does starting a recording require the calling user to be part of the conversation, or can a backend service with the right scopes trigger it? The token is associated with a service account, not the agent currently on the call.

Any pointers on what permission set I’m missing? Or is this endpoint strictly for agents in-session?