---
updatedAt: 2026-10-02T14:02:29.000Z
agentTools:
  projectIndex: https://apidoc.factorialhr.com/llms.txt
---

# Company Token

A Company Token provides company-wide access to Factorial data. All actions are performed on behalf of the company, not a specific user.<br />

# Create the OAuth Application

A Factorial admin creates and manages OAuth applications in **Settings → Advanced configuration → OAuth applications**.

> **➡️**<Anchor target="_blank" href="https://app.factorialhr.com/settings/oauth-applications">**Open OAuth applications in Factorial**</Anchor>

1. In Factorial, open **Settings**.
2. Under **Advanced configuration**, select **OAuth applications**.
3. Select **Create OAuth app**.
4. Enter the **application name**, one **redirect URI** per line, and the **scopes** the integration needs. To test with Postman, use one of these redirect URIs:
   * Postman in browser: `https://oauth.pstmn.io/v1/browser-callback`

   * Postman desktop: `https://oauth.pstmn.io/v1/callback`
   > If you have doubts about which scopes to apply, you can contact <Anchor target="_blank" href="https://portal.support.factorialhr.com/servicedesk/customer/portal/5/group/7/create/19">Factorial support</Anchor>.
5. Choose the client type:
   * **Confidential client with secret** if the application can store a client secret securely on a server.
   * **Public client without secret** for browser, desktop, or mobile applications that cannot keep a secret.
6. Select **Save**.

After saving, the OAuth applications page shows the application name, client ID, scopes, and redirect URIs.

<Image src="https://files.readme.io/646a758f8a4f793b3b8b3d56db935b69befd5e3497683b89b85243f5b1829228-Screenshot_2026-09-29_at_16.17.23.png" alt="Factorial Settings page with the OAuth applications card under Advanced configuration" align="center" border={true} />

<Image src="https://files.readme.io/c241df27518ca54c92a7978bf4ac668d47c619bbf4f42b05c69d648a7aab0d6f-Screenshot_2026-09-29_at_16.19.46.png" alt="Empty OAuth applications page with a Create OAuth app button" align="center" border={true} />

<Image src="https://files.readme.io/7b190d12e247e2897457cdbf63c2484dc054a425b2c26ded8b3f3f2c4b5d8b2d-Screenshot_2026-09-29_at_16.21.57.png" alt="Create OAuth app dialog with application name, redirect URIs, and scopes" align="center" width="600px" border={true} />

<Image src="https://files.readme.io/64a465b2e217598eb66a513badf55c9da8809cf1e98ff96c972cc9dc4406a128-Screenshot_2026-09-29_at_16.22.11.png" alt="OAuth applications page listing an application with client ID, confidentiality, scopes, and redirect URI" align="center" border={true} />

## Choose the client type

* **Confidential clients** run on a trusted backend and can keep a client secret private. They authenticate with that secret when exchanging an authorization code for tokens.
* **Non-confidential (public) clients** run in environments where a secret cannot be protected, such as browser SPAs, mobile apps, or desktop apps. A client secret would be extractable, so it must not be relied on for authentication.

<Callout icon="🔐" theme="info">
  ### Public clients should use Authorization Code + PKCE

  1. Generate a random `code_verifier` locally.
  2. Derive a `code_challenge` from it and send that with the authorization request.
  3. Keep the verifier only in the client.
  4. Send the original verifier when exchanging the returned code for tokens.
</Callout>

## Save Client ID and Client Secret

1. The **Client ID** is always visible in the OAuth applications list.
2. A **client secret** is created only for a **Confidential client with secret**. Copy it when it is shown and store it securely.
3. Verify the redirect URIs and scopes are saved correctly.

<Callout icon="⚠️" theme="warn">
  ### **Save and rotate the client secret**

  If the secret is lost or exposed, open the application in **OAuth applications** and use **Rotate client secret**, then update the secret in your integration.
</Callout>

<br />

## Start the authorization request

The OAuth applications page does not start authorization for you. After creating the application, your integration must send the **company administrator** to the Factorial ID authorization endpoint. For a company-owned flow, use the application's client ID and registered redirect URI, and add `resource_owner_type=company`:

```
https://id.factorialhr.com/oauth/authorize?client_id=<CLIENT_ID>&redirect_uri=<URL_ENCODED_REDIRECT_URI>&response_type=code&scope=<URL_ENCODED_SCOPES>&state=<RANDOM_STATE>&resource_owner_type=company
```

For demo, use `https://id.eu2.demo.factorial.dev/oauth/authorize` with the same parameters.

> **Public clients (PKCE):** also add `&code_challenge=<CODE_CHALLENGE>&code_challenge_method=S256`, where `code_challenge` is derived from the `code_verifier` your client generated and kept locally.

1. The administrator signs in to Factorial, reviews the requested scopes, and authorizes the application.

<Image src="https://files.readme.io/5c468bbbabb02cd3cbcd3ab6fce28a8cc700fa6e608a4d6f35692affad4216ca-oauth-consent-screen.png" alt="Factorial OAuth consent screen showing the requested application access" align="center" width="450px" caption="The Factorial OAuth consent screen." border={true} />

2. Factorial then redirects to the registered redirect URI with the authorization code.

![](https://files.readme.io/7038009be31da24285b166886bebd62d8a5c312060490f2c195436e257ab0a5c-image.png)

3. The URL of that page contains your Authorization Code. For example:

![](https://files.readme.io/b6dfd07e989016313897a53347117854105a4b169e66965ab7749a4265581c75-image.png)

```
https://oauth.pstmn.io/v1/browser-callback?code=elX2bzbV85mS90PU8319-mqxLcl-1MgSmuQlas33gw
```

In this example, the code is: `elX2bzbV85mS90PU8319-mqxLcl-1MgSmuQlas33gw`. If you sent a `state` value, check that the one returned matches it.

<br />

## Exchange Code for Access Token

Use Postman to request the token.

1. In Postman, go to **My Collection → Get data → Authorization**.
2. Set the **Auth Type** to `OAuth 2.0`.

![](https://files.readme.io/b4e6f80a47d476aa8415b308aa42670beb17ff7e25fb826f0a92149b10427644-image.png)

3. Fill in the **Configure New Token** section with the following Factorial ID values:

| Field                | Production                                     | Demo                                                |
| -------------------- | ---------------------------------------------- | --------------------------------------------------- |
| **Auth URL**         | `https://id.factorialhr.com/oauth/authorize`   | `https://id.eu2.demo.factorial.dev/oauth/authorize` |
| **Access Token URL** | `https://id.factorialhr.com/api/oauth/token`   | `https://id.eu2.demo.factorial.dev/api/oauth/token` |
| **Client ID**        | Your Client ID from the application            | Your Client ID from the application                 |
| **Client Secret**    | Your Client Secret (confidential clients only) | Your Client Secret (confidential clients only)      |

> For a **Public client without secret**, set **Grant Type** to `Authorization Code (With PKCE)` and leave **Client Secret** empty. Postman generates the `code_verifier` and `code_challenge` for you.

4. Scroll down to **Auth Request** and add a query parameter:
   * **Key:** `code`
   * **Value:** Your Authorization Code from the previous step

![](https://files.readme.io/8c6cda768b186f3004759963707bdd738afc1e20a3521fab44348df2670e790d-image.png)

5. Click the orange **"Get new access token"** button.

![](https://files.readme.io/02fa067893f6409a9e6035fc0661836758e2af3a10a0bef5d4dc273c9df7aa41-image.png)

6. In the pop-up window, sign in to Factorial if needed, review the requested scopes, and click **"Authorize"**.
7. After authorization, a pop-up in Postman will return your **Access Token**.

![](https://files.readme.io/18a12aec335b752ce1167a28b22496e9f00b581f06472193bbff0f844ecb54b8-image.png)

<Callout icon="📘" theme="info">
  ### Existing integrations

  Existing integrations can keep their current endpoints while they are migrated to the Factorial ID endpoints.
</Callout>

## Exchange the code without Postman

Send a `POST` request to the Factorial ID token endpoint.

**Confidential client**

```bash
curl -X POST 'https://id.factorialhr.com/api/oauth/token' \
  -d 'client_id=<CLIENT_ID>' \
  -d 'client_secret=<CLIENT_SECRET>' \
  -d 'code=<AUTHORIZATION_CODE>' \
  -d 'redirect_uri=<REDIRECT_URI>' \
  -d 'grant_type=authorization_code'
```

**Public client (PKCE)**: do not send a client secret; send the original `code_verifier` instead.

```bash
curl -X POST 'https://id.factorialhr.com/api/oauth/token' \
  -d 'client_id=<CLIENT_ID>' \
  -d 'code=<AUTHORIZATION_CODE>' \
  -d 'redirect_uri=<REDIRECT_URI>' \
  -d 'code_verifier=<CODE_VERIFIER>' \
  -d 'grant_type=authorization_code'
```

For demo, use `https://id.eu2.demo.factorial.dev/api/oauth/token`.

<Callout icon="✅" theme="okay">
  ### **Success!** You now have a Company Token.
</Callout>

## Video walkthrough

<video controls preload="metadata" width="100%">
  <source src="https://files.readme.io/066e4a7566f94595d28c4e09e4f1eff9334831f21c10cf3aefdcbd362c23d0f1-oauth-applications-demo.mp4" type="video/mp4" />
</video>

<br />

<Callout icon="⏰" theme="default">
  ### **Company Token Expiry:** Company access tokens expire after **1 hour**. Save the `refresh_token` to request new access tokens without re-authorizing.
</Callout>

# Refreshing Access Token

Company access tokens are valid for one hour. After this period has expired, request a new access token with a `POST` request to the Factorial ID token endpoint, providing the refresh token that came with the previous access token.

<Callout icon="🚧" theme="warn">
  ### **Note**

  Non-admin users can perform this action as long as they have the refresh token provided at time of first authentication.
</Callout>

<Callout icon="❗️" theme="error">
  ### **Refresh-token lifetime**

  Store the refresh token securely and use it to obtain a new access token. If refresh fails because the token or grant is no longer valid, start the authorization flow again.
</Callout>

| Action                   | Production endpoint                           | Demo endpoint                                        |
| ------------------------ | --------------------------------------------- | ---------------------------------------------------- |
| **Refresh access token** | `https://id.factorialhr.com/api/oauth/token`  | `https://id.eu2.demo.factorial.dev/api/oauth/token`  |
| **Revoke token**         | `https://id.factorialhr.com/api/oauth/revoke` | `https://id.eu2.demo.factorial.dev/api/oauth/revoke` |

```bash
curl -X POST 'https://id.factorialhr.com/api/oauth/token' -d 'client_id=<YOUR_CLIENT_ID>&client_secret=<YOUR_CLIENT_SECRET>&refresh_token=<REFRESH_TOKEN>&grant_type=refresh_token'
```

> **Public clients:** omit `client_secret`.