> ## 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 RecommendedCallout = ({title, children, icon = "⭐"}) => <div style={{
  backgroundColor: 'var(--recommended-bg)',
  borderLeft: '4px solid #f8f1ac',
  borderRadius: '10px',
  padding: '18px 22px',
  marginBottom: '20px',
  boxShadow: '1px 1px 3px rgba(0,0,0,0.06)'
}}>
    <div style={{
  display: 'flex',
  alignItems: 'flex-start',
  gap: '14px'
}}>
      <span style={{
  fontSize: '22px',
  lineHeight: '1',
  flexShrink: 0
}}>
        {icon}
      </span>
      <div>
        {title && <div style={{
  fontSize: '16px',
  fontWeight: 600,
  color: 'var(--recommended-title)',
  marginBottom: '6px'
}}>
            {title}
          </div>}
        <div style={{
  fontSize: '14px',
  lineHeight: 1.65
}}>
          {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.

<Note>
  Registering an OAuth 2.0 client creates **authentication credentials** only. It does **not** create or publish a Marketplace app.
</Note>

## 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)

***
