CI/CD pipeline token generation failing with 401

Setting up a Jenkins job to deploy Architect changes via the Genesys Cloud API. Need a long-lived token for the pipeline since interactive login isn’t an option. Tried hitting the OAuth endpoint with the client credentials flow but keep getting a 401 Unauthorized response. The client ID and secret are definitely correct, copied them straight from the developer portal. The request body looks right according to the docs but something is off with the header or the payload structure. Here is the cURL command I am using:

curl -X POST 'https://api.mypurecloud.com/oauth/token' \
 -H 'Content-Type: application/x-www-form-urlencoded' \
 -d 'grant_type=client_credentials&client_id=MY_CLIENT_ID&client_secret=MY_CLIENT_SECRET'

The response just says invalid_client. I’ve tried URL encoding the secret but that didn’t help. Also tried adding an Authorization header with basic auth encoding of the client ID and secret but that returns a 400 Bad Request saying the grant type is invalid. What is the exact format required for this endpoint in a non-browser context? The docs are vague on the header requirements for machine-to-machine auth.