OAuth2 client credentials auth failing with Python requests

How do I call https://api.mypurecloud.com/oauth/token via requests.post without getting a 401? The dashboard sync job keeps dropping on token rotation. Passing client_id and client_secret in the Authorization header doesn’t work since it’s expecting application/x-www-form-urlencoded.

  • Python 3.11 runtime
  • requests v2.31.0
  • grant_type=client_credentials
    The endpoint just spits out {"error":"invalid_request"} and cuts the TCP stream. Weird behavior. Need the exact data dict layout. requests.post(token_url, data=auth_payload) just blocks the main thread.

You don’t need to manually encode the header. The requests library handles application/x-www-form-urlencoded automatically when you pass a dict to the data parameter. Here is how I handle token rotation in our proxy scripts.

import requests

url = "https://api.mypurecloud.com/oauth/token"
payload = {
 "grant_type": "client_credentials",
 "client_id": os.getenv("GENESYS_CLIENT_ID"),
 "client_secret": os.getenv("GENESYS_CLIENT_SECRET"),
 "scope": "admin:interaction:read" 
}

headers = {
 "Accept": "application/json",
 "Content-Type": "application/x-www-form-urlencoded"
}

response = requests.post(url, data=payload, headers=headers)

if response.status_code == 200:
 access_token = response.json().get("access_token")
 print("Token acquired")
else:
 print(f"Auth failed: {response.status_code} {response.text}")

Make sure your client credentials are stored in environment variables. Hardcoding them in the script is a bad practice. The scope needs to match what your downstream API calls require. If you get a 401, check that the client secret hasn’t expired. I usually set a TTL of 35 minutes for the cached token to avoid race conditions during the last minute of validity.