POST /oauth/token returns 401 when requesting long-lived CI/CD token

Why does this config cause a 401 Unauthorized on POST /oauth/token? I am building a Newman collection for America/Toronto CI/CD runs. Need a long-lived token, not short-lived. Using grant_type=client_credentials with correct client_id and client_secret. Response: {"error":"invalid_client","error_description":"Client authentication failed"}. Code: curl -X POST https://api.mypurecloud.com/oauth/token -d 'grant_type=client_credentials&client_id=xxx&client_secret=yyy'. What is wrong?

Check your client secret encoding and the request body structure. the 401 with invalid_client usually means the auth header is malformed or the secret contains special characters that get mangled in curl.

i see you are using client_credentials. for ci/cd, ensure you are using the base64 encoded client_id and client_secret in the Authorization header, not in the body. the api expects Basic auth for the client credentials.

here is the correct python snippet using requests to avoid curl encoding issues:

import requests
import base64

client_id = "your_client_id"
client_secret = "your_client_secret"
base64_credentials = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()

headers = {
 "Authorization": f"Basic {base64_credentials}",
 "Content-Type": "application/x-www-form-urlencoded"
}

data = {
 "grant_type": "client_credentials",
 "scope": "analytics:call-center:read" # add required scopes
}

response = requests.post("https://api.mypurecloud.com/oauth/token", headers=headers, data=data)
print(response.json())

if you stick with curl, use -u for basic auth:

curl -X POST https://api.mypurecloud.com/oauth/token \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -u "client_id:client_secret" \
 -d "grant_type=client_credentials&scope=analytics:call-center:read"

also verify the client secret in the developer portal. if you recently rotated it, the old one will fail with this exact error. the token lifetime for client_credentials is fixed by platform policy, usually 1 hour. you cannot extend this via api parameters. you must implement a refresh mechanism in your ci/cd pipeline. do not try to hack the scope to get longer life, it will just return 403.

Have you tried bypassing the client_credentials grant entirely? For CI/CD pipelines, especially those triggering Architect Data Actions or bulk API calls, managing token rotation via a service account is often cleaner than wrestling with Basic Auth encoding in curl. The invalid_client error usually implies a mismatch in the client secret or the environment endpoint. Instead of debugging header encoding, consider using the Genesys Cloud SDK’s built-in authentication helper which handles the base64 encoding and token caching automatically. This avoids the manual header construction that often fails in shell scripts.

  • Initialize the PureCloudPlatformClientV2 SDK in your Python/Node script.
  • Use platformClient.auth.login() with your clientId and clientSecret.
  • Verify the environment (mypurecloud.com vs api.mypurecloud.com) matches your org.
  • Reuse the authenticated client instance for subsequent API calls to avoid repeated 401s.

This approach is more robust for automated flows than raw curl requests, which are prone to whitespace and encoding issues in secrets.

Make sure you isolate the token endpoint latency under load. client_credentials flows choke if the auth server hits rate limits during parallel CI jobs.

curl -X POST https://api.mypurecloud.com/oauth/token \
 -H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -d 'grant_type=client_credentials&scope=analytics:report:read'

Verify the base64 encoding matches your environment’s line-ending expectations.

This is typically caused by the client secret containing special characters that break URL encoding, so you must use the Authorization header with Basic auth instead of the body. The docs state “client credentials must be base64 encoded in the header” so try this: curl -X POST https://api.mypurecloud.com/oauth/token -H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=client_credentials'.