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

# How to Handle Redirects and Exchange an Authorisation Code

export const WhatComesNext = ({children, href}) => <div className="mt-4">
    <a href={href} className="
        inline-flex items-center justify-center
        rounded-full
        bg-black text-white dark:bg-[#1f262b]
        px-5 py-2.5 text-sm font-medium
        no-underline border-0
        hover:bg-[#ffe6ea] dark:hover:bg-[#2b1f23]
        hover:text-black
        transition-colors
      ">
      {children} →
    </a>
  </div>;

This how-to explains how to handle the redirect from Pleo after **user consent** and how to exchange the returned **authorisation code** for OAuth 2.0 tokens.

It assumes you are managing the **redirect handling and token lifecycle on your backend**. For context on why this is needed, see [OAuth 2.0 Client Configuration](/docs/current/integration-design/auth/oauth/getting-set-up/oauth-client-configuration) and [PKCE and Secured Patterns](/docs/current/integration-design/auth/oauth/implementing-oauth/integration-design-auth-oauth-pkce-and-secured-patterns).

## Prerequisites

Before you begin, ensure that:

* You have registered an OAuth 2.0 client with Pleo
* You have implemented the authorisation redirect flow
* You have a backend endpoint registered as your `redirect_uri`
* You are using PKCE and have stored the original `code_verifier`
* You can make secure server-to-server HTTP requests

## Steps

### 1. Understand the Redirect

After a user grants consent on Pleo’s authorisation screen, Pleo redirects the user’s browser back to your application.

The redirect contains a short-lived **authorisation code** that must be exchanged for tokens before any API access is possible.

At this stage:

* User consent has already been granted
* No API access is possible yet
* Tokens must be obtained securely on the backend

***

### 2. Receive the Redirect

Pleo redirects the browser to your registered `redirect_uri` with query parameters.

A **successful** redirect includes:

* `code` — the authorisation code
* `state` — the original value sent in the authorisation request

A **failed** redirect includes:

* `error`
* `error_description` (optional)
* `state`

Your redirect endpoint must be able to handle both cases.

***

### 3. Validate the Redirect

Before exchanging the authorisation code, perform the following checks:

* **Verify the `state` value**\
  Ensure it matches the value you generated before redirecting the user.\
  This protects against CSRF attacks.

* **Ensure a `code` is present**\
  If no authorisation code is returned, treat the flow as failed.

<Tip>
  Never proceed with token exchange if the `state` validation fails.
</Tip>

***

### 4. Exchange the Authorisation Code for Tokens

The authorisation code must be exchanged **server-to-server** using Pleo’s token endpoint.

This request must **never** be made from a frontend or client-side application.

***

### 5. Send the Token Exchange Request

The token exchange request must include the following parameters:

| Parameter       | Description                            |
| --------------- | -------------------------------------- |
| `grant_type`    | Must be `authorization_code`           |
| `code`          | Authorisation code received from Pleo  |
| `redirect_uri`  | Must match the registered redirect URI |
| `client_id`     | Your OAuth 2.0 Client ID               |
| `client_secret` | Your OAuth 2.0 Client Secret           |
| `code_verifier` | Original PKCE code verifier            |

<Tip>
  The `code_verifier` must be the exact value used to generate the `code_challenge` during authorisation.
</Tip>

#### Example Request

```http theme={null}
POST /oauth/token HTTP/1.1
Host: auth.pleo.io
Authorization: Basic AbCdE1F2GHIjKLMnOp34QRS5TUvwXyzaBCDeF6GhI7JkLmNOPqrsTuvwXyZaBcD8EfGhIJklMnOpQrStUVWxyZA9BC==
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=Abcde1FgHIJKlMN2OpQrST
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Fcallback
&code_verifier=ab1C_DefG2gA3_bcdefGhAbCD-efGha45cdEFGHaB6C
```

***

### 6. Handle the Token Response

A successful token exchange returns:

* `access_token`
* `refresh_token`
* `expires_in`
* `token_type`
* `scope`

Your backend must:

* Store tokens securely
* Associate tokens with the correct Pleo company or entity
* Track token expiry time for future refresh operations

<Tip>
  For guidance on secure storage, see [Secure Token Storage](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-secure-token-storage).
</Tip>

***

### 7. Handle Token Exchange Errors

Token exchange can fail for several reasons:

* Invalid or expired authorisation code
* Mismatched redirect URI
* Invalid client credentials
* Incorrect or missing PKCE verifier

If the exchange fails:

* **Do not** retry with the same authorisation code
* Restart the OAuth 2.0 flow if required
* Log failures for troubleshooting

<Tip>
  Proper error handling ensures your integration can recover gracefully and inform users if reauthentication is needed.
</Tip>

***

### 8. Follow Authorisation Code Rules

* Authorisation codes are **single-use** and expire quickly
* Any used or expired code will be rejected by Pleo

<Tip>
  Always treat authorisation codes as short-lived secrets and exchange them immediately upon receipt.
</Tip>

***

### 9. Store Tokens Securely

Tokens must be stored according to security best practices:

* Store tokens only on secure backend systems
* Never expose tokens to end users
* Encrypt tokens at rest where possible

<Note>
  See [Secure Token Storage](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-secure-token-storage) for detailed guidelines and recommended patterns.
</Note>

***

### 10. Track and Manage Token Expiry

To maintain uninterrupted access:

* Track the `expires_in` value for each access token
* Schedule refresh operations **before** access tokens expire
* Ensure refresh operations follow [Centralised Token Refresh](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-centralised-token-refresh) and [Race Condition Prevention](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-race-condition-prevention) patterns

***

## Result

After completing these steps:

* Your backend has securely validated the OAuth 2.0 redirect
* Your registered OAuth 2.0 client has exchanged a **single-use authorisation code** for tokens
* Access and refresh tokens are stored securely
* Your OAuth 2.0 client is now authorised to access Pleo APIs

***

## What Comes Next?

<WhatComesNext href="/docs/current/how-tos/oauth/how-to-call-pleo-apis-using-access-tokens">
  Use your access token to make authenticated requests to Pleo APIs
</WhatComesNext>

***

<div className="text-xs uppercase" style={{ fontVariant: 'small-caps' }}>
  this how-to is part of:
</div>

<div className="mt-4 flex flex-wrap gap-2">
  <a
    href="/docs/current/guides/oauth-workflow-guide"
    className="inline-flex items-center rounded-full border border-gray-300 dark:border-gray-600 
px-3 py-1 text-xs font-medium 
bg-white dark:bg-[#1f262b] text-black dark:text-white
hover:bg-gray-100 dark:hover:bg-[#2b2f33]
transition-colors"
  >
    OAuth 2.0 Setup Workflow Guide (Manual Token Lifecycle)
  </a>
</div>

***

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

* [Token Lifecycle](/docs/current/integration-design/auth/oauth/token-lifecycle/integration-design-auth-oauth-token-overview)
* [OAuth 2.0 Client Registration](/docs/current/integration-design/auth/oauth/getting-set-up/oauth-client-registration) – Step-by-step details of required fields, credentials, and redirect URIs.
* [OAuth 2.0 Client Configuration](/docs/current/integration-design/auth/oauth/getting-set-up/oauth-client-configuration) – How to configure your client with correct endpoints, PKCE, and authentication methods.
* [PKCE and Secured Patterns](/docs/current/integration-design/auth/oauth/implementing-oauth/integration-design-auth-oauth-pkce-and-secured-patterns) – Security requirements for public clients.

***
