The Pleo API supports two authentication methods: OAuth and API Keys (coming soon). For partners developing integrations that will be made available for all Pleo customers, OAuth is the preferred method as this provides the best customer experience. However, API keys are still an option where utilizing OAuth is not possible.

For customers building bespoke integrations to access their own Pleo data, API keys should be used.


Pleo has taken a standard approach to OAuth so you can find further documentation here.


Authorization Endpoint —or—
Token Endpoint —or—
Grant TypeAuthorization Code (with PKCE)
Client Credentialsclient_id and client_secret that you received after completing the client registration.
Redirect URIAn OAuth client attribute. This is where the user is taken to after completing the OAuth flow. Must match exactly with the redirect_uri that you supplied during client registration.
ScopeFor testing, test:test and any similar value will work.
PKCERequired, S256 only. Verifier must conform to the RFC (43–128 characters, only alphanumeric characters and -\_.~)
Client AuthenticationAuthorization: Basic BASE64({client_id}:{client_secret})

Getting started

In order to begin building your OAuth solution, you will need be provided client credentials. You can request this completing the form here.

Client credentials for the staging environment will be provided within 1-3 business days via a secure channel.

Initiating the Authorization Request

The first step in the flow is obtaining an authorization code. The flow will need to be initiated from your application in a browser.
  • <client_id>: provided to you during app creation
  • <redirect_uri>: must match the value you provided during app creation
  • <scope>: the list of scopes you have access to will be determined during the app creation process. Multiple scopes can be passed as a space-separated list, for example: scope=export:read export:write
  • <response_type>: always code
  • <state>: a string value. Should be request-specific. Will be returned back by the server on future requests. This is optional.
  • code_challenge_method: must be S256
  • code_challenge: must be a base64uri encoded sha256 hash of a code_verifier, a secret random string (43–128 characters, only alphanumeric characters and -\_.~)), that the client will need to present later during authorization code exchange. You MUST NOT expose code_verifier during authorization request.

The user will then be prompted to login:


After which the user will be redirected by to the url specified in the original request containing the following in the query params:

  • code: the authorization which will be used to to obtain access and refresh tokens; expires after 10 minutes
  • state: this should match what was passed in the initial request

Getting Tokens

The authorization code obtained above is a temporary code that can be exchanged for an access and refresh token with the following request:


  • Client authentication is performed using Authorization: Basic BASE64({client_id}:{client_secret}) header
  • redirect_uri must be the same as the one used to generate the authorization code
  • code_verifier from the initial request must included to verify you application originally sent the request

A successful response will look like:

  "access_token": "THE_ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": ACCESS_TOKEN_LIFETIME, // 10 mins.
  "refresh_token": "REFRESH_TOKEN", // optional
  "scope": "scope1 scope2"

Store the access_token and refresh_token securely.

The expires_in field describes the lifetime of the access token, in seconds since the moment it has been issued. After specified time, it will no longer be accepted by the resource servers, and a new access token should be obtained by making a request to the token endpoint. Your application can do this by making a request to a token endpoint using the refresh token grant, as described in the next section.

A response may not contain a refresh token. In this case, after the access token expires, the only way to obtain a new access token is to go through the authorization process again.

Refresh Tokens

Once you have a refresh token, this can be used to continue obtain new short-lived access tokens:



You must present your client_id and client_secret using Basic HTTP authentication.

As successful response will include a new access_token and a new refresh_token, which you will need to stored in replacement of the previously used refresh token:

  "access_token": "THE_ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": ACCESS_TOKEN_MILLI_LIFETIME, // 10 mins.
  "refresh_token": "REFRESH_TOKEN",
  "scope": "scope1+scope2..."

Token Introspection

The token introspection endpoint to return information about a token. Client authentication is performed using Authorization: Basic BASE64({client_id}:{client_secret}) header. Note that clients can only introspect tokens generated with their own client.


    "token": "{token}"

A successful request will return the following response

	"active": true,
	"sub": "RESOURCE_ID",
	"token_type": "at+JWT",
	"client_id": "CLIENT_ID",
	"aud": "",
	"iss": "pleo.production",
	"jti": "TOKEN_ID"