Work out which layer is actually failing first
A Workday integration or API client fails authentication for one of three separable reasons: the integration system user (ISU) account itself is blocked, its security group doesn't reach the domains the call needs, or the API client credential (its ID, secret, or refresh token) is wrong or expired. The error text points at one of these, but the same message can have more than one real cause underneath it. This guide assumes the ISU and API client already exist — setting up a Workday integration system user and API client covers creating them in the right order; this is what to check once that setup stops working.
invalid_client
The token endpoint couldn't match the client ID and secret you sent to a registered API client. The usual cause is mechanical: a truncated copy-paste of the secret, a client ID from a different API client (an interactive client's ID used where an integrations client's ID belongs), or credentials copied from a different tenant. If you've lost the secret, generate a new one from the client's record rather than guessing at the old one — Workday only displays a secret once, at creation.
invalid_grant
This means the token endpoint accepted the client ID and secret but rejected the grant itself —
almost always the refresh token. Workday documents refresh tokens as tied to the specific account
that authorized them: if the ISU's username changes, or the ISU is deactivated, the refresh token
issued under it stops working, even though nothing about the API client changed. A refresh token
regenerated for a different client ID than the one in the request fails the same way. When a
previously working integration starts throwing invalid_grant with no change on your
side, check the ISU's own state before touching the client: a changed password, a security group
change, or a deactivated account is the more common cause than a corrupted token value.
If the client uses Non-Expiring Refresh Tokens, the refresh token itself has no
expiry — an invalid_grant on that kind of client points even more strongly at the ISU
or at a token that was regenerated (and the old one invalidated) rather than at natural expiry.
The ISU's own account: password expiry and UI sessions
An ISU is a Workday user account, and by default it's subject to the tenant's password expiration policy exactly like a person's account — until you add it to the System Users Exempt from Password Expiration field on the Maintain Password Rules task. Without that, the ISU's password eventually expires on its own schedule, and every call using it starts failing for a reason that has nothing to do with the API client, the refresh token, or the security group.
Do Not Allow UI Sessions should be selected on the ISU, which removes its ability to sign in through a browser at all — this doesn't cause the failures above, but if it's ever unchecked while diagnosing something else, put it back before you move on, since an ISU exists to answer API calls, not to hold an interactive session.
Security group membership and domain permissions, both — and activation
Three separate things have to be true for the ISU to reach a given call, and a 403, or a functional 401-shaped failure that isn't really about the token, usually traces to one of them:
- The ISU must be a member of an integration system security group. Membership changes take effect immediately.
- That group must have the right permission on the domain the call needs — Report/Task Permissions (View for reads, Modify for writes) for REST calls, or Integration Permissions (Get for reads, Put for writes) for SOAP. Workday's own REST API security reference is explicit that REST calls need Report/Task Permissions whether the caller is an ISU or a person; Integration Permissions apply to SOAP only, so a group with only Get and Put still fails a REST call.
- Any change to a domain security policy — adding the group, or changing its permission level — stays pending until someone runs Activate Pending Security Policy Changes. Unlike a group membership change, a policy edit has no effect at all until that task runs. "The security is definitely set up right" and a 403 anyway is, more often than not, this step skipped.
Register API Client for Integrations vs. Register API Client
Workday has two separate client-registration tasks, and using the wrong one produces exactly the
authentication errors above with no obvious reason why. Register API Client for
Integrations is for a service that runs unattended: it supports
Non-Expiring Refresh Tokens and a Scope (Functional Areas) setting
that should cover only the functional areas the integration actually calls, not every area by
default. The plain Register API Client task is built for an interactive flow with a
real person completing a browser authorization step — a grant type meant for a user-facing app, not
a background job. Registering a service account under the interactive task, or vice versa, is an avoidable source of invalid_client and invalid_grant once the
client is actually put to use.
A client's scope has a related consequence: functional areas outside what was granted at registration aren't something you can fix by requesting a new token — the client itself has to be reconfigured, and, for a domain permission change on top of that, activated.
The wrong tenant or endpoint in the token request
The token request goes to a URL shaped like https://{host or gateway}/ccx/oauth2/{tenant}/token
— both the host and the tenant name are specific to your tenant, not a generic Workday address. A
request built against a different tenant's name, or against credentials copied from one tenant into
another (a common mistake right after a Sandbox refresh), fails authentication even though the
client ID and secret are individually valid, because they were never valid together with that
tenant.
POST https://<host or gateway>/ccx/oauth2/<tenant>/token
Authorization Basic <base64 of the client id and client secret>
Content-Type application/x-www-form-urlencoded
grant_type refresh_token
refresh_token <the refresh token value>If you've recently changed which tenant you're pointing at — moved from Sandbox to Production, or picked up a refreshed tenant — confirm the tenant name in the URL before re-checking the client or the ISU; it's the fastest thing to get wrong and the easiest to overlook once the credentials themselves look right.
Prove it with the same request that's failing, isolated
Once you've made a change, re-run the exact failing request in isolation — the token exchange by itself, then a single small read — rather than restarting the full integration and hoping. A 200 on the token exchange isolates the client and the ISU from everything downstream; a 200 on the read after that confirms the security group and activation are both in place. For the ordered setup this guide assumes is already done, see setting up a Workday integration system user and API client. If the credential in question drives a Workday Extend orchestration rather than an external client, see Orchestrate errors and what they mean for the separate credential-type failure that shows up there instead.
Sources checked
- Reference: REST API Error Messages
- Request a New Access Token with a Refresh Token
- Concept: Workday REST API Security
- Register API Client for Data Lake (Refresh Token Grant)
- Security Policy Configuration and Activation
- Advanced Security Group Types
- Make Adaptive Planning API Requests with Workday Credentials (token endpoint format)