> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parable.work/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth 2.0

> Connect Parable to Workday using OAuth 2.0

export const platform_1 = "Workday"

export const limit_0 = "varies by tenant configuration; monitor X-RateLimit headers"

export const platform_0 = "Workday"

<Tabs>
  <Tab title="Setup">
    <Card title="What You'll Need" icon="key">
      | Credential        | What it is                                                                       |
      | ----------------- | -------------------------------------------------------------------------------- |
      | **Client ID**     | OAuth 2.0 client ID from **Register API Client for Integrations**                |
      | **Client Secret** | OAuth 2.0 client secret (shown once at registration)                             |
      | **Tenant Name**   | Workday tenant identifier (subdomain in `{tenant}.workday.com`)                  |
      | **Base URL**      | *(Optional)* Workday **services** host override (see **Tenant URLs** setup step) |
    </Card>

    ## Overview

    Connect Parable to Workday via **OAuth 2.0 client credentials** for REST API access to staffing, organization, payroll, absence, and time tracking data.

    <Info>
      For **RaaS custom reports** (pre-encoded report token + report URL), use [**Workday HRIS RaaS**](/connectors/workday-raas/custom-report/setup) instead.
    </Info>

    <Info>
      **Workday does not use OAuth scope strings** (unlike Salesforce `api` or Google `https://www.googleapis.com/auth/...`). Access is controlled by two layers you configure in Workday:

      1. **Functional areas** on the API client (labeled **Scope (Functional Areas)** on the registration form)
      2. **Domain security policies** on the Integration System User's security group (GET/View permissions)

      Parable sends a client-credentials token request with **no `scope` parameter**. If either layer is missing, token exchange or API calls fail with `403 Forbidden` or empty field sets.
    </Info>

    <CardGroup cols={2}>
      <Card title="Staffing & Organizations" icon="users">
        Workers, positions, job requisitions, org hierarchy, org chart
      </Card>

      <Card title="Payroll, Absence & Time" icon="clock">
        Payroll inputs, payment elections, pay slips, absence balances, time off, time blocks
      </Card>
    </CardGroup>

    ## Prerequisites

    <Info>
      **Setup access in Workday.** These steps require **Integration System Administrator** or **Security Administrator** privileges, or a colleague who can create API clients and edit domain security on your behalf.
    </Info>

    * **OAuth 2.0 enabled** on the tenant (**Edit Tenant Setup - Security**; confirm OAuth 2.0 clients are allowed)
    * Permission to run **Register API Client for Integrations**
    * Permission to create Integration System Users and Integration System Security Groups
    * Permission to edit **Domain Security Policy Permissions** and run **Activate Pending Security Policy Changes**

    ## Setup Guide

    Complete Workday security setup **before** registering the API client. Workday evaluates API access from the Integration System User's domain policies, not from the admin who registered the client.

    <Steps>
      <Step title="Create Integration System User">
        1. Search: **Create Integration System User**
        2. Create a dedicated user (for example `ISU_Parable_Integration`)
        3. Set a strong password and note the username
        4. Enable **Do Not Allow UI Sessions** when available

        This ISU is the **authorization context** for every API call Parable makes. The API client authenticates with client ID and secret; the ISU's security group determines what data is returned.
      </Step>

      <Step title="Create Integration System Security Group">
        1. Search: **Create Security Group**
        2. Type: **Integration System Security Group**
        3. Name: `Parable Integration Security Group`
        4. Add your Integration System User as the only member
        5. Save the group
      </Step>

      <Step title="Grant Domain Security Permissions">
        Search: **Domain Security Policy Permissions** (or **Domain Security for Functional Area**).

        For each domain below, add your **Integration System Security Group** with **Get** or **View** access only. Do **not** grant Put, Post, or Modify.

        <Warning>
          Domain names vary by tenant and Workday release. Filter by functional area in Workday and search for the keywords below if the exact label differs.
        </Warning>

        **Staffing**

        | Domain (search keywords)                                     | Used for                                       |
        | ------------------------------------------------------------ | ---------------------------------------------- |
        | Worker Data: Public Worker Reports                           | Worker identity and public profile fields      |
        | Worker Data: Current Staffing Information                    | Job, employment, and manager fields on workers |
        | Worker Data: All Positions                                   | Positions tap                                  |
        | Recruiting / Job Requisitions *(if separate in your tenant)* | Job requisitions tap                           |

        **Organizations and Roles**

        | Domain (search keywords) | Used for                                    |
        | ------------------------ | ------------------------------------------- |
        | Organization and Roles   | Organizations and supervisory organizations |
        | Supervisory Organization | Org members and org chart child endpoints   |

        **Payroll**

        | Domain (search keywords)    | Used for                                    |
        | --------------------------- | ------------------------------------------- |
        | Payroll Input               | Payroll inputs tap                          |
        | Payment Election            | Payment elections tap                       |
        | Worker Pay Data / Pay Slips | Worker pay slips tap (traversed per worker) |

        **Absence Management**

        | Domain (search keywords)                        | Used for                          |
        | ----------------------------------------------- | --------------------------------- |
        | Absence / Time Off Balances                     | Absence balances tap              |
        | Leave of Absence                                | Worker leaves of absence tap      |
        | Time Off                                        | Time off details tap              |
        | Eligible Absence Types *(if listed separately)* | Worker eligible absence types tap |

        **Time Tracking**

        | Domain (search keywords)           | Used for               |
        | ---------------------------------- | ---------------------- |
        | Time Tracking / Worker Time Blocks | Worker time blocks tap |
      </Step>

      <Step title="Activate Security Changes">
        1. Search: **Activate Pending Security Policy Changes**
        2. Review and submit

        Domain permission edits are not live until activated. Skipping this step is a common cause of `403 Forbidden` after credentials look correct.
      </Step>

      <Step title="Register API Client">
        1. Search: **Register API Client for Integrations**
        2. Fill in:

        | Field                        | Value                                                                                 |
        | ---------------------------- | ------------------------------------------------------------------------------------- |
        | Client Name                  | `Parable Integration`                                                                 |
        | Client Grant Type            | **Client Credentials**                                                                |
        | Access Token Type            | **Bearer**                                                                            |
        | Integration System User      | The ISU from Step 1                                                                   |
        | Grant Administrative Consent | **Checked** *(recommended; grants tenant-wide consent for selected functional areas)* |

        3. On **Scope (Functional Areas)**, enable **all** of the following. Partial selection causes 403 errors when Parable calls payroll, absence, or time endpoints.

        | Functional area (Scope)                              | Parable data                                                                  |
        | ---------------------------------------------------- | ----------------------------------------------------------------------------- |
        | **Staffing**                                         | Workers, positions, job requisitions                                          |
        | **Organizations and Roles**                          | Organizations, supervisory organizations, org members, org chart              |
        | **Payroll**                                          | Payroll inputs, payment elections, worker pay slips                           |
        | **Absence Management** *(or **Time Off and Leave**)* | Absence balances, leaves of absence, eligible absence types, time off details |
        | **Time Tracking**                                    | Worker time blocks                                                            |

        <Info>
          Scope labels vary by tenant (for example **Time Off and Leave** instead of **Absence Management**). Some tenants also offer **Include Workday Owned Scope** for core domains outside standard functional areas; enable it only if Workday support recommends it for your tenant.
        </Info>

        <Info>
          Parable uses **client credentials only**. You do **not** need **Manage Refresh Tokens for Integrations** or a refresh token for this connector.
        </Info>

        4. Submit the form and copy the **Client ID** and **Client Secret** immediately.

        <Warning>
          The Client Secret is shown only once. If you lose it, use **Generate New API Client Secret** on the client (this invalidates the old secret).
        </Warning>
      </Step>

      <Step title="Confirm ISU Is Linked">
        If the ISU was not set during registration:

        1. Search: **Edit API Client for Integrations**
        2. Open `Parable Integration`
        3. Set **Integration System User** to your ISU
        4. Confirm **Client Grant Type** is **Client Credentials**
      </Step>

      <Step title="Tenant URLs">
        Workday REST and OAuth URLs use the **services** host, not the UI login host (`*.workday.com`).

        | Environment           | Example services host                                                         | Token endpoint                  |
        | --------------------- | ----------------------------------------------------------------------------- | ------------------------------- |
        | Sandbox (common)      | `https://wd5-impl-services1.workday.com`                                      | `.../ccx/oauth2/{tenant}/token` |
        | Sandbox (WD501-style) | `https://services1.wd501.myworkday.com`                                       | same path pattern               |
        | Production            | `https://{tenant}-services1.workday.com` or `https://services1.myworkday.com` | same path pattern               |

        Example workers probe:

        ```
        https://wd5-impl-services1.workday.com/ccx/api/staffing/v7/YOUR_TENANT/workers
        ```

        Replace `YOUR_TENANT` with your tenant name. Parable defaults to `https://{tenant}-services1.workday.com` when **Base URL** is blank. If the connection test returns `404 Not Found`, confirm the services host with your Workday administrator and enter it as **Base URL**.
      </Step>

      <Step title="Enter Values in Parable">
        1. In Parable, open the **Workday** connector (REST API, not RaaS)
        2. Enter **Tenant Name**, **Client ID**, and **Client Secret**
        3. Enter **Base URL** only if your services host differs from Parable's default
        4. Click **Save & test connection**

        Parable validates credentials by obtaining an OAuth token and calling `GET /workers?limit=1`. A successful test confirms authentication and Staffing API access. Sync runs across all connector data once Workday functional areas and domain permissions above are in place.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Reference">
    ## OAuth Flow

    This integration uses **OAuth 2.0 Client Credentials** flow for server-to-server authentication.

    ### How It Works

    1. Your app sends **Client ID** and **Client Secret** to the token endpoint
    2. {platform_0} returns a short-lived **access token** (typically 1 hour)
    3. Use the access token in API requests
    4. When expired, request a new token (automatic in Parable)

    ### Token Request

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://YOUR_SERVICES_HOST/ccx/oauth2/YOUR_TENANT/token" \
        -H "Content-Type: application/x-www-form-urlencoded" \
        -d "grant_type=client_credentials" \
        -d "client_id=YOUR_CLIENT_ID" \
        -d "client_secret=YOUR_CLIENT_SECRET"
      ```

      ```python Python theme={null}
      import requests

      response = requests.post(
          "https://YOUR_SERVICES_HOST/ccx/oauth2/YOUR_TENANT/token",
          data={
              "grant_type": "client_credentials",
              "client_id": "YOUR_CLIENT_ID",
              "client_secret": "YOUR_CLIENT_SECRET"
          }
      )

      access_token = response.json()["access_token"]
      print(f"Access Token: {access_token}")
      ```
    </CodeGroup>

    ### Using the Access Token

    ```http theme={null}
    Authorization: Bearer {access_token}
    ```

    <Info>
      Parable automatically handles token refresh, so you don't need to manage token expiration manually.
    </Info>

    Parable does **not** send a `scope` query parameter on the token request. Required access is enforced by the API client's functional areas and the ISU domain policies configured in Workday.

    ## Parable Tap to Workday API Mapping

    Grant the functional areas and domain permissions above for **all** rows below. Child endpoints are fetched from parent worker or organization IDs.

    | Parable data                    | REST endpoint                                 | API version          | Functional area (Scope) |
    | ------------------------------- | --------------------------------------------- | -------------------- | ----------------------- |
    | `workers`                       | `/workers`                                    | staffing/v7          | Staffing                |
    | `positions`                     | `/positions`                                  | staffing/v7          | Staffing                |
    | `job_requisitions`              | `/jobRequisitions`                            | staffing/v7          | Staffing                |
    | `organizations`                 | `/organizations`                              | staffing/v7          | Organizations and Roles |
    | `supervisory_organizations`     | `/supervisoryOrganizations`                   | staffing/v7          | Organizations and Roles |
    | `org_members`                   | `/supervisoryOrganizations/{org_id}/members`  | staffing/v7          | Organizations and Roles |
    | `org_chart`                     | `/supervisoryOrganizations/{org_id}/orgChart` | staffing/v7          | Organizations and Roles |
    | `payroll_inputs`                | `/payrollInputs`                              | payroll/v2           | Payroll                 |
    | `payment_elections`             | `/paymentElections`                           | payroll/v2           | Payroll                 |
    | `worker_pay_slips`              | `/workers/{worker_id}/paySlips`               | payroll/v2           | Payroll                 |
    | `absence_balances`              | `/balances`                                   | absenceManagement/v2 | Absence Management      |
    | `worker_leaves_of_absence`      | `/workers/{worker_id}/leavesOfAbsence`        | absenceManagement/v2 | Absence Management      |
    | `worker_eligible_absence_types` | `/workers/{worker_id}/eligibleAbsenceTypes`   | absenceManagement/v2 | Absence Management      |
    | `time_off_details`              | `/workers/{worker_id}/timeOffDetails`         | absenceManagement/v2 | Absence Management      |
    | `worker_time_blocks`            | `/workerTimeBlocks`                           | timeTracking/v5      | Time Tracking           |

    <Info>
      Organization endpoints live under the **staffing/v7** REST path but require the **Organizations and Roles** functional area (Scope) on the API client.
    </Info>

    ## Verify Your Setup

    <CodeGroup>
      ```bash Get Access Token (Client Credentials) theme={null}
      curl -X POST "https://YOUR_SERVICES_HOST/ccx/oauth2/YOUR_TENANT/token" \
        -H "Content-Type: application/x-www-form-urlencoded" \
        -d "grant_type=client_credentials" \
        -d "client_id=YOUR_CLIENT_ID" \
        -d "client_secret=YOUR_CLIENT_SECRET"
      ```

      ```bash Test Staffing API Access theme={null}
      curl -H "Authorization: Bearer <ACCESS_TOKEN>" \
        "https://YOUR_SERVICES_HOST/ccx/api/staffing/v7/YOUR_TENANT/workers?limit=1"
      ```

      ```bash Test Payroll API Access theme={null}
      curl -H "Authorization: Bearer <ACCESS_TOKEN>" \
        "https://YOUR_SERVICES_HOST/ccx/api/payroll/v2/YOUR_TENANT/payrollInputs?limit=1"
      ```
    </CodeGroup>

    <Check>
      **Success!** If you received a `200 OK` response with valid data, your credentials are configured correctly. You can now proceed to configure this connector in Parable.
    </Check>

    <Tip>
      **Rate Limits:** {platform_1} enforces rate limits of **{limit_0}**.

      Parable handles rate limiting automatically with exponential backoff, but initial syncs of large datasets may take longer due to these limits.
    </Tip>

    ## Troubleshooting

    | Error                              | Meaning                                      | Solution                                                                            |
    | ---------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------- |
    | `invalid_client`                   | Wrong client credentials                     | Verify Client ID and Secret; confirm **Client Credentials** grant type              |
    | `invalid_grant`                    | Client misconfigured                         | Confirm ISU is linked on the API client; confirm OAuth 2.0 is enabled on the tenant |
    | `403 Forbidden`                    | Missing functional area or domain permission | Enable all functional areas; grant GET on domains; activate security changes        |
    | `404 Not Found`                    | Wrong services host or tenant                | Verify tenant name and **Base URL** services host                                   |
    | Fields missing or null in API JSON | Domain security gap                          | Grant GET on the domain that owns that field (not an API bug)                       |

    <Accordion title="Common Issues">
      ### "User not authorized for this operation"

      The Integration System User's security group lacks domain GET permission for the endpoint you called. Revisit **Domain Security Policy Permissions**, add the group to the matching domain, and run **Activate Pending Security Policy Changes**.

      ### Token exchange succeeds but payroll or absence calls fail

      The API client is missing a **Scope (Functional Area)**. Edit the client and enable Payroll, Absence Management, and Time Tracking in addition to Staffing and Organizations and Roles.

      ### Connection test passes but a specific endpoint fails in sync

      Parable's connection test probes Staffing (`/workers`) only. A failure on payroll, absence, or time data means the matching Workday functional area or domain permission is still missing.

      ### Confusion about refresh tokens

      Some Workday guides describe **Manage Refresh Tokens for Integrations**. Parable uses the **client credentials** grant with client ID and secret only; no refresh token setup is required.
    </Accordion>

    ## Additional Resources

    <CardGroup cols={2}>
      <Card title="Workday REST API" icon="book" href="https://doc.workday.com/admin-guide/en-us/integration-administration/api-administration/rest-api/index.html">
        Official API documentation (Workday sign-in required)
      </Card>

      <Card title="Workday HRIS RaaS" icon="file-lines" href="/connectors/workday-raas/custom-report/setup">
        Custom report connector (separate auth)
      </Card>
    </CardGroup>
  </Tab>
</Tabs>
