Recording API start/stop endpoints returning 401 with valid token

Trying to control call recordings programmatically via the CXone REST API. The goal is to start a recording on demand and stop it after a specific condition is met in the script.

I’m using the REST Proxy action in to make the calls. The endpoints are:

  • POST /api/v2/recording/recordingcontrols/start
  • POST /api/v2/recording/recordingcontrols/stop

The Authorization header is set to Bearer <token> where the token is retrieved from a previous action. The token works fine for other calls like fetching participant data. But these recording endpoints always return a 401 Unauthorized. The response body is empty.

Here is the JSON payload for the start request:

{
 "conferenceId": "conf-123",
 "recordingName": "test_rec"
}

I’ve checked the OAuth client permissions. It has recording:write and recording:read. The division scope is correct. The token is not expired. Other recording-related calls, like listing recordings, work fine with the same token.

Tried adding the Content-Type: application/json header. Tried different token scopes. Tried using the long-lived token instead of the short-lived one. All result in 401.

Is there a specific permission or header missing for the recording controls endpoints? The documentation doesn’t mention any special requirements beyond standard OAuth. The call ID and conference ID are valid. The call is active.

Any ideas why the recording controls endpoints are rejecting the token while other endpoints accept it?

You’re hitting a scope mismatch. The token you’re grabbing in usually only has the scopes needed for basic user actions or analytics, not recording control. You need a token with the recording:control scope.

Since you’re doing this in the easiest fix is to use the “Get Credentials” action to generate a new access token specifically for this task. Set the grant type to client_credentials and make sure the client ID and secret are for an app that has the recording:control scope enabled in the developer console.

Then pass that new token to your REST proxy. Here’s how the payload for the start endpoint should look. Note that you need the recordingId which you get from the conversation object, not just the conversation ID.

{
 "recordingId": "<your-recording-id>",
 "action": "start"
}

If you’re still getting 401s, check the developer console for the client app you’re using. Go to the Scopes tab and verify recording:control is checked. It’s easy to miss because there are a dozen recording scopes and they look similar.

Also, if you’re trying to stop it, the endpoint is the same but the action changes to stop. Just make sure you’re not trying to stop a recording that hasn’t started yet or is already finished. The API is strict about that.