Python requests OAuth2 client_credentials returning 401 on CXone

Just noticed that my Python script for fetching a CXone access token is failing with a 401 Unauthorized error. I have been using this pattern for other endpoints, but the token endpoint seems to reject the request despite valid credentials.

Here is the simplified code:

import requests

url = "https://platform.dev1.cimplicity.com/oauth2/token"
headers = {
 "Content-Type": "application/x-www-form-urlencoded",
 "Accept": "application/json"
}
data = {
 "grant_type": "client_credentials",
 "client_id": "my_client_id",
 "client_secret": "my_secret"
}

response = requests.post(url, headers=headers, data=data)
print(response.status_code)
print(response.text)

The response body is:

{
 "error": "invalid_client",
 "error_description": "Client authentication failed"
}

I have double-checked the client_id and client_secret in the CXone admin console. The environment is dev1. Is there a specific header requirement for the token endpoint that differs from standard REST calls? Or could this be related to the client secret encoding?