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

# OAuth 2.0 Setup Workflow Guide (Manual Token Lifecycle)

export const RememberCallout = ({title, children}) => <div className="callout-box callout-remember">
    <div className="callout-row">
      <span className="callout-icon">
        <svg width="22" height="22" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M229.66,98.34,172.39,155.8c11.46,22.93-1.72,45.86-10.11,57a8,8,0,0,1-12,.83L42.34,105.76A8,8,0,0,1,43,93.85c29.65-23.92,57.4-10,57.4-10l57.27-57.46a8,8,0,0,1,11.31,0L229.66,87A8,8,0,0,1,229.66,98.34Z" opacity="0.2" /><path d="M235.32,81.37,174.63,20.69a16,16,0,0,0-22.63,0L98.37,74.49c-10.66-3.34-35-7.37-60.4,13.14a16,16,0,0,0-1.29,23.78L85,159.71,42.34,202.34a8,8,0,0,0,11.32,11.32L96.29,171l48.29,48.29A16,16,0,0,0,155.9,224c.38,0,.75,0,1.13,0a15.93,15.93,0,0,0,11.64-6.33c19.64-26.1,17.75-47.32,13.19-60L235.33,104A16,16,0,0,0,235.32,81.37ZM224,92.69h0l-57.27,57.46a8,8,0,0,0-1.49,9.22c9.46,18.93-1.8,38.59-9.34,48.62L48,100.08c12.08-9.74,23.64-12.31,32.48-12.31A40.13,40.13,0,0,1,96.81,91a8,8,0,0,0,9.25-1.51L163.32,32,224,92.68Z" /></svg>
      </span>
      <div>
        {title && <div className="callout-title">
            {title}
          </div>}
        <div className="callout-body">
          {children}
        </div>
      </div>
    </div>
  </div>;

export const RecommendedCallout = ({title, children}) => <div className="callout-box callout-recommended">
    <div className="callout-row">
      <span className="callout-icon">
        <svg width="22" height="22" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M229.06,108.79l-48.7,42,14.88,62.79a8.4,8.4,0,0,1-12.52,9.17L128,189.09,73.28,222.74a8.4,8.4,0,0,1-12.52-9.17l14.88-62.79-48.7-42A8.46,8.46,0,0,1,31.73,94L95.64,88.8l24.62-59.6a8.36,8.36,0,0,1,15.48,0l24.62,59.6L224.27,94A8.46,8.46,0,0,1,229.06,108.79Z" opacity="0.2" /><path d="M239.18,97.26A16.38,16.38,0,0,0,224.92,86l-59-4.76L143.14,26.15a16.36,16.36,0,0,0-30.27,0L90.11,81.23,31.08,86a16.46,16.46,0,0,0-9.37,28.86l45,38.83L53,211.75a16.38,16.38,0,0,0,24.5,17.82L128,198.49l50.53,31.08A16.4,16.4,0,0,0,203,211.75l-13.76-58.07,45-38.83A16.43,16.43,0,0,0,239.18,97.26Zm-15.34,5.47-48.7,42a8,8,0,0,0-2.56,7.91l14.88,62.8a.37.37,0,0,1-.17.48c-.18.14-.23.11-.38,0l-54.72-33.65a8,8,0,0,0-8.38,0L69.09,215.94c-.15.09-.19.12-.38,0a.37.37,0,0,1-.17-.48l14.88-62.8a8,8,0,0,0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16A8,8,0,0,0,103,91.86l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153,91.86a8,8,0,0,0,6.75,4.92l63.92,5.16c.15,0,.24,0,.33.29S224,102.63,223.84,102.73Z" /></svg>
      </span>
      <div>
        {title && <div className="callout-title">
            {title}
          </div>}
        <div className="callout-body">
          {children}
        </div>
      </div>
    </div>
  </div>;

<RecommendedCallout title="Recommended Workflow">
  Pleo Partners building **multi-customer integrations** must implement **OAuth 2.0** as the recommended authentication method.
</RecommendedCallout>

This workflow outlines how third-party applications integrate securely with Pleo using OAuth 2.0. Each step explains **what happens, why it matters, and the expected result**, while linking to detailed how-to guides for implementation.

By following this guide, developers and architects can understand **how the pieces fit together**, ensuring a secure and reliable integration.

## What You'll Have Built

After completing the workflow:

* An OAuth 2.0 client is registered and authorised for your integration.
* Access and refresh tokens are obtained, stored securely, and refreshed correctly.
* Your integration can interact with Pleo APIs safely, respecting scopes and user consent.
* The OAuth flow is resilient to token expiry, revocation, and race conditions.

<RememberCallout title="Remember">
  Registering an OAuth 2.0 client creates **authentication credentials** only. It does **not** create or publish a Marketplace app.
</RememberCallout>

## Who This Guide Is For

This guide is intended for developers and architects implementing OAuth 2.0 integrations with Pleo APIs. It focuses on **workflow understanding**, not step-by-step coding details, those are in the linked how-to guides.

## Scope

All instructions assume:

* An OAuth 2.0 integration with Pleo APIs
* Integration with the **Staging environment**

## OAuth 2.0 Workflow Steps

### 1. Register OAuth Client

**Purpose:**\
Registering an OAuth 2.0 client for your integration ensures it can request access to user resources securely. This step provides the credentials and configuration needed to start the OAuth flow.

**Input:**

* Integration details (name, URI, logo, terms, privacy policy)
* Redirect URIs and scope requirements

**Output:**

* A **Client ID** and **Client Secret**
* Defined redirect URIs registered with Pleo
* OAuth 2.0 client ready for user authorisation

**Integration Design / Why It Matters:**

* Client credentials authenticate your integration via its OAuth client to the Pleo authorisation server
* Redirect URIs and scopes ensure requests are valid and secure
* See: [OAuth 2.0 Client Registration & Configuration](/docs/current/integration-design/auth/oauth/getting-set-up/oauth-client-registration)

<section className="mt-4">
  <a
    href="/docs/current/how-tos/oauth/how-to-register-an-oauth-client"
    className="group flex items-center justify-between rounded-md border border-gray-200 dark:border-gray-700 px-4 py-3
bg-gray-50 dark:bg-[#1f262b] hover:bg-[#ffe6ea] dark:hover:bg-[#2b1f23]
transition-colors"
  >
    <div>
      <p className="text-sm font-medium text-gray-900 dark:text-white">
        How to Register an OAuth 2.0 Client
      </p>

      <p className="text-xs text-gray-600 dark:text-gray-400">
        Complete client registration and configure credentials for your app.
      </p>
    </div>

    <span className="ml-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300">
      →
    </span>
  </a>
</section>

***

### 2. Direct Users to Authorisation Endpoint

**Purpose:**\
Redirecting users to Pleo ensures they explicitly grant your integration permission to access their data. This step is required before any tokens are issued.

**Input:**

* The **Client ID** from the previous step
* PKCE values (`code_verifier` / `code_challenge`)

**Output:**

* Users see the Pleo consent screen and approve or deny access
* An **authorisation code** is issued upon approval

**Integration Design / Why It Matters:**

* PKCE prevents authorisation code interception
* The `state` parameter protects against CSRF attacks
* Scopes define what data your integration can access
* See:
  * [PKCE and Secured Patterns](/docs/current/integration-design/auth/oauth/implementing-oauth/integration-design-auth-oauth-pkce-and-secured-patterns)
  * [OAuth 2.0 Client Registration - Details and Technical Requirements](/docs/current/integration-design/auth/oauth/getting-set-up/oauth-client-registration)

<section className="mt-4">
  <a
    href="/docs/current/how-tos/oauth/how-to-direct-users-to-the-authorisation-endpoint"
    className="group flex items-center justify-between rounded-md border border-gray-200 dark:border-gray-700 px-4 py-3
bg-gray-50 dark:bg-[#1f262b] hover:bg-[#ffe6ea] dark:hover:bg-[#2b1f23]
transition-colors"
  >
    <div>
      <p className="text-sm font-medium text-gray-900 dark:text-white">
        How to Direct Users to the Authorisation Endpoint
      </p>

      <p className="text-xs text-gray-600 dark:text-gray-400">
        Send users to Pleo for secure consent and obtain an authorisation code.
      </p>
    </div>

    <span className="ml-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300">
      →
    </span>
  </a>
</section>

***

### 3. Handle Redirect & Exchange Authorisation Code

**Purpose:**\
Exchange the short-lived authorisation code for access and refresh tokens securely. This step moves credentials from user consent to usable tokens for API access.

**Input:**

* **Authorisation code** returned from Pleo
* Stored **code\_verifier** (for PKCE)

**Output:**

* Access and refresh tokens issued and stored securely on your backend

**Integration Design / Why It Matters:**

* Token exchange must be server-to-server to keep secrets safe
* PKCE verification ensures the code wasn’t intercepted
* See: [PKCE and Secured Patterns](/docs/current/integration-design/auth/oauth/implementing-oauth/integration-design-auth-oauth-pkce-and-secured-patterns)

<section className="mt-4">
  <a
    href="/docs/current/how-tos/oauth/how-to-handle-redirects-and-exchange-authorisation-code"
    className="group flex items-center justify-between rounded-md border border-gray-200 dark:border-gray-700 px-4 py-3
bg-gray-50 dark:bg-[#1f262b] hover:bg-[#ffe6ea] dark:hover:bg-[#2b1f23]
transition-colors"
  >
    <div>
      <p className="text-sm font-medium text-gray-900 dark:text-white">
        How to Handle Redirects & Exchange Authorisation Code
      </p>

      <p className="text-xs text-gray-600 dark:text-gray-400">
        Exchange the authorisation code for access and refresh tokens securely.
      </p>
    </div>

    <span className="ml-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300">
      →
    </span>
  </a>
</section>

***

### 4. Use Access Token to Call APIs

**Purpose:**\
Access tokens authenticate your integration when interacting with Pleo APIs, eliminating the need for user credentials on each request.

**Input:**

* Access token obtained in the previous step

**Output:**

* API endpoints respond with requested data or action confirmation (JSON payloads, status codes)

**Integration Design / Why It Matters:**

* Always send tokens in the `Authorization` header over HTTPS
* Ensure required scopes match endpoint permissions
* Token misuse or exposure could compromise security
* See: [Token Lifecycle Overview](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-token-overview)

<section className="mt-4">
  <a
    href="/docs/current/how-tos/oauth/how-to-call-pleo-apis-using-access-tokens"
    className="group flex items-center justify-between rounded-md border border-gray-200 dark:border-gray-700 px-4 py-3
bg-gray-50 dark:bg-[#1f262b] hover:bg-[#ffe6ea] dark:hover:bg-[#2b1f23]
transition-colors"
  >
    <div>
      <p className="text-sm font-medium text-gray-900 dark:text-white">
        How to Call Pleo APIs Using Access Token
      </p>

      <p className="text-xs text-gray-600 dark:text-gray-400">
        Authenticate requests and interact with Pleo APIs using the access token.
      </p>
    </div>

    <span className="ml-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300">
      →
    </span>
  </a>
</section>

***

### 5. Refresh Tokens Centrally

**Purpose:**\
Access tokens expire quickly. Using refresh tokens allows your integration to maintain access without requiring user intervention.

**Input:**

* Stored refresh token from the previous step
* Client credentials

**Output:**

* New access and refresh tokens
* Updated expiry timestamps

**Integration Design / Why It Matters:**

* Refresh logic should be centralised to avoid race conditions
* Tokens must be stored securely and rotated properly
* See:
  * [Race Condition Prevention](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-race-condition-prevention)
  * [Centralised Token Refresh](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-centralised-token-refresh)

<section className="mt-4">
  <a
    href="/docs/current/how-tos/oauth/how-to-refresh-tokens"
    className="group flex items-center justify-between rounded-md border border-gray-200 dark:border-gray-700 px-4 py-3
bg-gray-50 dark:bg-[#1f262b] hover:bg-[#ffe6ea] dark:hover:bg-[#2b1f23]
transition-colors"
  >
    <div>
      <p className="text-sm font-medium text-gray-900 dark:text-white">
        How to Refresh Tokens
      </p>

      <p className="text-xs text-gray-600 dark:text-gray-400">
        Maintain access by refreshing tokens safely and securely.
      </p>
    </div>

    <span className="ml-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300">
      →
    </span>
  </a>
</section>

***

### 6. Handle Token Expiry or Revocation

**Purpose:**\
Refresh tokens can expire or be revoked. Detecting and handling these events ensures your integration fails safely and can guide users to reauthenticate.

**Input:**

* API errors or failed refresh attempts indicating invalid or revoked tokens

**Output:**

* Integration stops API calls using invalid tokens
* Users are prompted to reauthenticate
* Newly issued tokens replace invalid ones

**Integration Design / Why It Matters:**

* Clear recovery flow prevents broken sessions
* Logging failures aids troubleshooting
* See: [Handling Refresh Token Expiry or Revocation](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-refresh-token-expiry-revocation)

<section className="mt-4">
  <a
    href="/docs/current/how-tos/oauth/how-to-handle-token-expiry-or-revocation"
    className="group flex items-center justify-between rounded-md border border-gray-200 dark:border-gray-700 px-4 py-3
bg-gray-50 dark:bg-[#1f262b] hover:bg-[#ffe6ea] dark:hover:bg-[#2b1f23]
transition-colors"
  >
    <div>
      <p className="text-sm font-medium text-gray-900 dark:text-white">
        How to Handle Token Expiry or Revocation
      </p>

      <p className="text-xs text-gray-600 dark:text-gray-400">
        Recover safely when refresh tokens expire or access is revoked.
      </p>
    </div>

    <span className="ml-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300">
      →
    </span>
  </a>
</section>

***

## What Comes Next?

Once Staging access is confirmed and your integration can successfully call Pleo APIs using OAuth 2.0, you can continue with:

* **Export Expenses Workflow Guide** (coming soon)

***

## FAQs

<Accordion title="What is the difference between an integration, application, and OAuth 2.0 client?">
  These terms describe different parts of how OAuth 2.0 works in the Pleo platform.

  The difference between an **integration**, **application**, and **OAuth 2.0 client** is explained in the [OAuth 2.0 Concepts and Terminology](/docs/current/authentication/oauth/oauth-overview#concepts-and-terminology) section.
</Accordion>

***

## Related Reading

* [OAuth 2.0 Overview](/docs/current/integration-design/auth/oauth/integration-design-auth-oauth-overview)

***
