CXone Client Credentials Grant returning 401 in .NET

I am setting up a background service in .NET 8 to fetch tokens from the CXone API using the client_credentials grant. The goal is to have a headless process that can query report data every hour without needing an interactive login flow.

I’ve configured the OAuth client in the CXone admin console with the client_credentials grant type enabled. I’ve also assigned the necessary scopes to the client.

When I run the code, I get a 401 Unauthorized response from the token endpoint. The error message is generic: “invalid_client”. I’ve double-checked the client ID and secret, and they match what’s in the console. I’ve also tried encoding them in Basic Auth header and passing them as form parameters, but both methods fail.

Here is the relevant part of the code:

var client = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
 new KeyValuePair<string, string>("grant_type", "client_credentials"),
 new KeyValuePair<string, string>("client_id", _clientId),
 new KeyValuePair<string, string>("client_secret", _clientSecret)
});

var response = await client.PostAsync("https://api.mynicecx.com/oauth/token", content);

if (!response.IsSuccessStatusCode)
{
 var errorBody = await response.Content.ReadAsStringAsync();
 Console.WriteLine($"Error: {response.StatusCode} - {errorBody}");
}

The output is:
Error: Unauthorized - {"error":"invalid_client"}

I’ve also tried adding the Authorization: Basic <base64> header, but that didn’t change the outcome. The endpoint seems correct based on the docs. Is there something specific about the CXone token endpoint that requires a different format? Or maybe a specific scope that must be included in the request body for client credentials to work? I’m stuck on this one.