--- title: "OAuth integration guide" description: "Integrate with our OAuth service to make API requests on your customer's behalf" url: "https://docs.adyen.com/partners/oauth/integration" source_url: "https://docs.adyen.com/partners/oauth/integration.md" canonical: "https://docs.adyen.com/partners/oauth/integration" last_modified: "2023-11-07T16:23:00+01:00" language: "en" --- # OAuth integration guide Integrate with our OAuth service to make API requests on your customer's behalf With an OAuth integration, you can request access to a selection of your customer's account resources. When your customer authorizes your access request, you get a token that you can use to authorize API requests on their behalf. ## Integration steps 1. [Register your client](#step-1-register-your-client) 2. [Request access](#step-2-request-access) 3. [Get your access and refresh tokens](#step-3-get-your-access-and-refresh-tokens) 4. [Use your access token](#step-4-use-your-access-token) 5. [Refresh your access token](#step-5-refresh-your-access-token) ## Requirements To integrate with Adyen's OAuth service, you need to have: * An account with the **OAuth apps manage** [user role](/account/user-roles). * On our test environment, merchant accounts created since November 2023 have this role enabled by default. If your account was created before, reach out to support. * On our live environment, only partner accounts have the **OAuth apps manage** role. We advise you first integrate in our test environment, especially when your integration involves the [online payments scope](/partners/oauth/scopes#make-online-payments). ## Step 1: Register your client An OAuth client is your application or website which accesses your customer's account resources on their behalf. To register your OAuth client: 1. Log in to your [Partner Portal](https://ca-test.adyen.com/). 2. Go to **Developer** > **OAuth apps**. 3. Select **Create OAuth app**. 4. Enter your application name, URL, and description and select **Continue**. 5. Enter your **Redirect URL**, select the [scope of access](/partners/oauth/scopes) and select **Continue**. * After your customer authorizes your application, we redirect them to your **Redirect URL**. 6. Copy the **Client secret** and store it securely. We do not store this value for you to access later. At the moment it is not possible to extend the scopes after the OAuth app has been created. Your customer can also not select or deselect requested scopes. The authorization can only be granted with all requested scopes. ## Step 2: Request access ### Step 2.1: Construct the access grant URL To request access to your customer's account resources, you need to redirect them to an Adyen page where they authenticate and grant you access. Create the URL that points to this location, using the following reference: | Parameter | Required | Description | | ------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | *ADYEN\_ENVIRONMENT\_URL* | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The base URL of the relevant Adyen environment: - For test environment, set to `ca-test.adyen.com`. - For live environment, set to `ca-live.adyen.com`. | | *CLIENT\_ID* | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The client ID of your OAuth client. | | `code_challenge_method` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The [code challenge](#code-challenge) method. Set to `S256`. | | `code_challenge` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | Your unique code verifier for this authorization. See [code challenge](#code-challenge). | | `response_type` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The type of response. Set to `code`. | | `redirect_uri` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The URL where your customer is redirected after successful authorization. Must match the Redirect URL set for your OAuth client. | | `state` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | A random string to protect against [Cross Site Request Forgery](https://owasp.org/www-community/attacks/csrf). | | `scope` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | A list of space separated [scope identifiers](/partners/oauth/scopes) you request access for. Must match the scopes set for your OAuth client. | ```bash https://{ADYEN_ENVIRONMENT_URL}/ca/ca/oauth/connect.shtml?client_id={CLIENT_ID} &code_challenge_method={CODE_CHALLENGE_METHOD} &code_challenge={CODE_CHALLENGE} &response_type={RESPONSE_TYPE} &redirect_uri={REDIRECT_URI} &state={STATE} &scope={SCOPE} ``` ### Code challenge During the OAuth flow, we use [Proof Key for Code Exchange](https://datatracker.ietf.org/doc/html/rfc7636) (PKCE) to add a layer of security on top of the client secret. PKCE works as follows: 1. For every [access request](#step-2-request-access), you create and supply a unique `code_challenge`, also known as a PKCE secret. 2. When you [exchange the authorization code for the access token](#step-3-get-your-access-and-refresh-tokens), you supply the associated `code_verifier`. If the authorization code is intercepted, it cannot be used without the PKCE secret. 1. To create your `code_verifier`, generate a random string with the following properties: * The string has a minimum length of 43 characters and a maximum length of 128 characters. * Allowed characters are \[A-Z] / \[a-z] / \[0-9] / "-" / "." / "\_" / "\~". 2. To create your `code_challenge`, create a [base64url](https://datatracker.ietf.org/doc/html/rfc4648#section-5)-encoded SHA256 hash of the `code_verifier`. #### Example 1. To create your `code_verifier`, generate a random URL-safe string: `dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk`. 2. To create your `code_challenge`, base64 URL-encode the SHA256 hash of the `code_verifier`: `E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM`. ### Handle the redirect Whether the authorization was [successful](#successful-authorization) or [failed](#failed-authorization), your customer is redirected to your `redirect_uri`. #### Successful authorization After successful authorization, your customer is redirected to: ```bash https://{REDIRECT_URI}?code={CODE}&state={STATE} ``` | Parameter name | Description | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | *REDIRECT\_URI* | The URI that you have set when [requesting access](#step-2-request-access). | | *CODE* | The short-lived authorization code. [Exchange this code](#step-3-get-your-access-and-refresh-tokens) for an access token. | | *STATE* | The same string as you provided for `state` [in the access request](#step-2-request-access). Used to protect against Cross Site Request Forgery. | In the next step, you will use the *CODE* to request access and refresh tokens. #### Failed authorization After failed authorization, your customer is redirected to: ```bash https://{REDIRECT_URI}?error={ERROR} ``` | Parameter name | Description | | --------------- | ---------------------------------------------------------------------------------------- | | *REDIRECT\_URI* | The URI that you have set when [requesting access](#step-2-request-access). | | *ERROR* | The relevant [OAuth error code](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1). | ### Step 2.2: Redirect your customer Add a button labeled **Connect with Adyen** to your application for your customers to initiate the access delegation. When your customer clicks the button, redirect them to the URL you constructed in [the previous step](/partners/oauth/integration#step-2-1-construct-the-access-grant-url), which points to an Adyen login screen where your customer authenticates and authorizes your request. ```html Connect with Adyen ``` Then, style the button: ```css .adyen-connect { display: inline-block; padding: 10px 12px 8px; background-color: #0ABF53; color: #FFFFFF; cursor: pointer; font-family: Fakt, "Helvetica Neue", Arial, sans-serif; font-weight: bold; font-size: 15px; text-decoration: none; border: 1px solid #0ABF53; box-sizing: border-box; border-radius: 6px; transition: all .2s } .adyen-connect:hover { background-color: #0BD25B; border-color: #0BD25B; } .adyen-connect:active { background-color: #09AF4C; border-color: #09AF4C; } .adyen-connect::before { padding: 0 8px; margin-right: 8px; content: ""; background-repeat: no-repeat; background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2215%22%20height%3D%2215%22%20viewBox%3D%220%200%2015%2015%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Cpath%20d%3D%22M11.748%20-0.0195312H0.212988V3.72347H7.72699C8.18999%203.72347%208.56999%204.11347%208.56999%204.58547V11.2285H6.96699C6.85501%2011.2273%206.74437%2011.2041%206.64139%2011.1601C6.5384%2011.1161%206.44509%2011.0523%206.3668%2010.9722C6.2885%2010.8922%206.22676%2010.7975%206.1851%2010.6935C6.14343%2010.5896%206.12267%2010.4784%206.12399%2010.3665V5.60447H2.94599C2.55467%205.60812%202.16791%205.68897%201.8079%205.84238C1.44788%205.9958%201.12168%206.21875%200.848001%206.49847C0.574318%206.77819%200.358532%207.10918%200.213013%207.47246C0.0674935%207.83573%20-0.00489811%208.22416%20-1.23367e-05%208.61547V11.9695C-1.23367e-05%2013.6375%201.31599%2014.9805%202.94599%2014.9805H14.694V2.98247C14.6989%202.59159%2014.6264%202.2036%2014.4808%201.84083C14.3352%201.47807%2014.1192%201.14767%2013.8454%200.868669C13.5716%200.589665%2013.2454%200.367556%2012.8854%200.215124C12.5254%200.062691%2012.1389%20-0.0170568%2011.748%20-0.0195312Z%22%20fill%3D%22white%22%2F%3E%0A%3C%2Fsvg%3E%0A"); } ``` ## Step 3: Get your access and refresh tokens Make a POST request to the `/token` endpoint to exchange your authorization code for: * A short-lived (24 hours by default) access token, to make API requests on behalf of your customer. * A one-time-use refresh token, to [get a new access token](#step-5-refresh-your-access-token) after your previous expired. To get your access and refresh tokens, make an HTTP `POST` request to: ```shell curl --request POST 'https://{ADYEN_OAUTH_BASE_URL}/v1/token' \ --header 'Authorization: Basic {BASIC_AUTH_HEADER}' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'code={CODE}' \ --data-urlencode 'code_verifier={CODE_VERIFIER}' \ --data-urlencode 'redirect_uri={REDIRECT_URI}' ``` All the parameters in the request body are `x-www-form-urlencoded`. | Parameter name | Required | Description | | ------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | *ADYEN\_OAUTH\_BASE\_URL* | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The base URL of the Adyen OAuth API: - For test environment, set to `oauth-test.adyen.com`. - For live environment, set to `oauth-live.adyen.com`. | | *BASIC\_AUTH\_HEADER* | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | A combination of [your OAuth client](/partners/oauth/integration#step-1-register-your-client) ID and secret. To create your basic access authentication value:1) Concatenate your client ID, a colon `:` and your client secret. 2) Base64 encode the result of the previous step. | | `grant_type` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The type of grant. Set to `authorization_code`. | | `code` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The authorization code [returned after successful authorization](#handle-the-redirect). | | `code_verifier` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The [`code_verifier` that you created](#code-challenge) for this authorization. | | `redirect_uri` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The URL where your customer is redirected after successful authorization. Must match the Redirect URL set for your OAuth client. | ### Handle the response The response body depends on whether your request was [successful](#get-access-refresh-tokens-successful-response) or [unsuccessful](#get-access-refresh-tokens-unsuccessful-response). #### Successful response | Parameter name | Description | | --------------- | --------------------------------------------------------------------------------------------------------------------- | | `token_type` | The token type. This value is set to `bearer`. | | `expires_in` | The time in seconds after which the access token expires. By default, this value is set to `86400` (24 hours). | | `access_token` | The access token, used to [authenticate API requests](#step-4-use-your-access-token) on behalf of your merchant. | | `refresh_token` | The refresh token, used to [get a new access token](#step-5-refresh-your-access-token) once the previous has expired. | | `scope` | The scope of access that the `access_token` provides. | | `accounts` | The merchant accounts that the `access_token` provides access to. | #### Unsuccessful response | Parameter name | Description | | ------------------- | ------------------------------------------------------------------------------------ | | `error` | The relevant [OAuth error code](https://www.rfc-editor.org/rfc/rfc6749#section-5.2). | | `error_description` | A description of the error. | ## Step 4: Use your access token Authorize API requests with your access token as bearer token: ```bash curl --request {HTTP-METHOD} '{RESOURCE_API}' \ --header 'Authorization: Bearer {ACCESS_TOKEN}' ``` ## Step 5: Refresh your access token Your access token is valid until the expiry period has elapsed. Find the expiry period in the [response of the `/token` request](#get-access-refresh-tokens-successful-response). Your refresh token expires only upon its usage. A short grace period is provided to allow for retries in the event of network errors or similar issues. To get a new access token, make an HTTP `POST` request to: ```bash curl --request POST 'https://{ADYEN_BASE_URL}/v1/token' \ --header 'Authorization: Basic {BASIC_AUTH_HEADER}' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type={GRANT_TYPE}' \ --data-urlencode 'refresh_token={REFRESH_TOKEN}' \ ``` All the parameters in the request body are `x-www-form-urlencoded`. | Parameter name | Required | Description | | --------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | *ADYEN\_BASE\_URL* | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The base URL of the Adyen OAuth API: - For test environment, set to `oauth-test.adyen.com`. - For live environment, set to `oauth-live.adyen.com`. | | *BASIC\_AUTH\_HEADER* | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | A combination of [your OAuth client](/partners/oauth/integration#step-1-register-your-client) ID and secret. To create your basic access authentication value:1) Concatenate your client ID, a colon `:`, and your client secret. 2) Base64 encode the result of the previous step. | | `grant_type` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The type of grant. Set to `refresh_token`. | | `refresh_token` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | Your refresh token. | When you successfully refresh your access token: * Your previous `access_token` immediately expires. This ensures there is no more than one valid `access_token` per authorization at a given point in time. * Your previous `refresh_token` expires shortly. This lets you retry the operation if the response was lost, for example during network issues. ### Successful response | Parameter name | Description | | --------------- | -------------------------------------------------------------------------------------------------------------- | | `token_type` | The token type. This value is set to `bearer`. | | `expires_in` | The time in seconds after which the access token expires. By default, this value is set to `86400` (24 hours). | | `access_token` | The access token, used to authenticate API requests on behalf of your merchant. | | `refresh_token` | The refresh token, used to get a new access tokens once the previous has expired. | The scope of access and merchant accounts that the `access_token` provides access to remains unchanged from when you [got your access and refresh tokens](#step-3-get-your-access-and-refresh-tokens). ### Unsuccessful response | Parameter name | Description | | ------------------- | ------------------------------------------------------------------------------------ | | `error` | The relevant [OAuth error code](https://www.rfc-editor.org/rfc/rfc6749#section-5.2). | | `error_description` | A description of the error. | ## Go live When you are ready to go live, make sure to: 1. Register an OAuth client in your [live Partner Portal](https://ca-live.adyen.com/). 2. Change all instances of the OAuth client ID, client secret, and client URI to reflect the OAuth client in your live account. 3. Change all API endpoints from test to live.