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.

Workday error

"401 Unauthorized"

Workday's own REST API reference gives this one two distinct meanings. Plain 401 Unauthorized means valid credentials weren't supplied at all — check that the Authorization header is actually present and well-formed on the request that's failing, not just on the ones you tested by hand. A separate message, Invalid Access Token, means the bearer token itself isn't valid or has expired; request a fresh access token from the token endpoint rather than reusing an old one.

An access token issued by Workday is short-lived by design. If a scheduled job caches a token and calls it hours later, this is the expected result — the fix is to request a new access token before each run, or when the previous one is close to expiring, not to treat a fresh token as something to conserve.

Workday error

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.

Workday error

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