Integration onboarding authentication

This page is applicable only to venues integrated via self-service integration onboarding or Wolt-led integration onboarding. Venues using legacy credentials (basic authentication or API key) are not supported.

Overview

For venues integrated through self-service integration onboarding or Wolt-led integration onboarding, the OAuth 2.0 authorization code flow is used to enable merchants (resource owners) to grant integration partners controlled access to their Wolt venues (resources).

Integration partners can then retrieve access and refresh tokens:

  • Access tokens are used to call Wolt APIs.
  • Refresh tokens are used to get new access and refresh tokens.

This flow ensures that integration partners can perform actions such as:

  • Updating menus and inventory.
  • Managing orders.
  • Updating venue details, such as operating hours or availability.

Merchants retain full control over their data throughout this process. They can withdraw their consent at any time, which immediately revokes the integration partner's access to the venue, maintaining the security and privacy of the merchant's data.

Access and refresh tokens

When integrating with Wolt APIs using OAuth 2.0, two types of tokens are issued: access token and refresh token.

Access token

The access token is a short-lived credential used to authenticate API requests. It grants access to the Wolt APIs for the specific venue or resource to which it was issued. The access token must be included in the Authorization header as a Bearer token when making calls to Wolt API. Typically, the authorization code is only used for the initial exchange, and thereafter you should rely exclusively on the refresh token.

Access tokens are valid for one hour. Expired token can no longer be used to make API requests.

Refresh token

The refresh token is a long-lived credential used to obtain a new access token when the current access token expires.

Refresh tokens are valid for 30 days. However, the refresh token is single-use. Each request to exchange the refresh token for a new access token also returns a new refresh token. The returned refresh token must be cached and used in the next request to exchange refresh token for a new access token.

Exchange authorization code for access and refresh tokens

When you get a authorization code from self-service integration onboarding or Wolt-led integration onboarding you need to exchange it for access and refresh tokens.

The authorization code is single-use and valid for 1 hour. After that period, it expires and can no longer be used to obtain tokens. If the code expires, you will need to initiate the integration onboarding again after active integration is reset to receive a new authorization code.

Request flow

Overview of the flow to exchange authorization code for access and refresh tokens
Sequence diagram of exchanging refresh token for new access token

1. Integration partner sends authorization code to Wolt auth service

Your system sends the authorization code obtained through self-service integration onboarding or Wolt-led integration onboarding, your client ID and client secret to Wolt’s auth service.

2. Wolt auth service returns access and refresh tokens

Wolt’s auth service returns an access token and a refresh token. The authorization code is invalidated and can no longer be used.

3. Integration partner stores the tokens

Your system must store the refresh token returned in the response for later use. The refresh token is used to exchange it for new tokens when the current access token expires. You should avoid requesting new access token each time, and instead use the same access token as long as it's valid.

Base URL

Example request

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "{{client_id}}:{{client_secret}}" \
-d "grant_type=authorization_code" \
-d "redirect_uri={{redirect_uri}}" \
-d "code={{code}}"

Headers

Header nameTypeDescription

Authorization

Required

Authorization header using basic auth. Must be Base64 encoding of client_id and client_secret joined by a single colon :.

Example: client_id:client_secret -> Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQK

Content-TypeRequiredMust be Content-Type: application/x-www-form-urlencoded.

Request fields

Field nameTypeDescription

code

Required

The authorization code you want to exchange.

Example: ory_ac_7DeVLbm9aw1PH44LU_99B2jF_TidS_k1QHmPNozqpqk

grant_typeRequiredMust be set to authorization_code.

redirect_uri

Required

The redirect URL that was used to generate the authorization code. The value depends on the integration onboarding method you used:

Example: https://www.partner-site.com/callback

Example response

{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImVmMmY2MGE5LTI0NzItNDZjMC1iYWQyLTQ2NzNiZTMwYTFjMCIsInR5cCI6IkpXVCJ9.eyJhdWQiOltdLCJjbGllbnRfaWQiOiIxNGM5ZDFhMy04N2UzLTQ4NGMtODg5MS01MGJlMTJkNGU5ZDkiLCJleHAiOjE3MTAzNDQ4ODIsImV4dCI6e30sImlhdCI6MTcxMDM0MTI4MiwiaXNzIjoiaHR0cHM6Ly9pbnRlZ3JhdGlvbnMtYXV0aGVudGljYXRpb24tc2VydmljZS5kZXZlbG9wbWVudC5kZXYud29sdGFwaS5jb20vIiwianRpIjoiZWU1N2ExZjItNTEyOC00ZDg4LThjNDAtNzExZmNiM2E4NmQzIiwibmJmIjoxNzEwMzQxMjgyLCJzY3AiOlsib2ZmbGluZSJdLCJzdWIiOiI2NWYxYmM4ZDhjOTk4ZTU2M2UzNDlmODEifQ.jGOWuVB5gsKzC7_R0GeiN40vxrqJHWXRyNMpnXpsIs-ajzf-G6TDqeMZTJHy6Z_68Y-zWDQ9UsiBqy9aoUG5Bvci-bDf12Rfs7ZOeBEO3E3j3EBFY0y_mYDyMIP2HCAZNIYD8Oxp9wOj3WLvAh8hkhA9xW5JldYqoz9o7x72fDKftOZgVnhf2EyMGq7Dg4miuOHtsCrk2UmdEtoo0vlfh4TtkQ9v-N8lutqHtAq4z4cCxN-dBVpfWGGsDtL-r_3Bj4HsyNI7vqnjxx4OW-COEBvBoYPZpE833lpgpoP3EqD0VcJmdNy5irCxSPQsZKsst6Eygv6yfJFlpPKzXSpQpyOOF-oFhIyn9RtPh8WEIjUXqGsWncAZGfNrVU4OL0WVH4tkd4-cIT4YiKtbx8SLrWVLif6MfOmCWwRk029TA5Y99q_9eMcMYw03Pj6ktSlNsnNlGQj2AfmZEGNYA-CgGIM3sonJE2vtkw3gz1twEFVel54cV7p6O6XLHnJ3CDE2ZmZHssg0utbrZqCacc9OtIiH6EZkewc-UtvMRFf6qveh_f2RIYegv0WYjYdHPgY1eMA_RqPzZOdqau1Nh4StjJ4xapfMu5Ejvf95PmX0OJxHgIEKWDplD316R5zrqQmmdHvrB8qt2BwQocCjsPxyZzyHE381FjptoUeRijUpk-JI",
"expires_in": 3600,
"refresh_token": "ory_rt_Vbtz4bfxjo5yG-l19DE34o1FKnFXASHuUQ7SyNkCykU.GqylnSfs7Rx0fo14kmcpUBwuvi-mXYyKWH-EIkjgRcA",
"scope": "offline",
"token_type": "bearer"
}

Response fields

Field nameDescription
access_tokenThe access token issued by Wolt. Use this token to authenticate against Wolt APIs.
expires_inThe lifetime of the access token in seconds. For example, the value 3600 denotes that the access token will expire in one hour from the time the token was generated.
refresh_tokenRefresh token which can be used to obtain new access and refresh tokens. You should cache the refresh token and use it to obtain a new access token when the current access token expires.
scopeScope of the token. The value offline indicates that the token can be used to obtain new access and refresh tokens.
token_typeIndicates how the token should be for authentication. Will be bearer, which means the token should be included in the Authorization header of the request.

Exchange refresh token for new access and refresh tokens

While you have a valid access token, avoid requesting a new one. Use the existing access token until it expires.

When your access token expires, you can use the refresh token to exchange it for a new access token. The refresh token can only be used once. Each time you exchange the refresh token for a new access token, a new refresh token will also be returned.

It is important that you store both of the new tokens. The new refresh token is required the next time you need a new access token.

If you lose the refresh token or it expires, the venue needs to re-integrated. To avoid disruption and ensure continued access to Wolt APIs, refresh token's validity must be proactively maintained. This is done by exchanging the refresh token for a new access token before the refresh token expires.

Please note that reusing the same refresh token in multiple requests will immediately deactivate and revoke the newly issued access and refresh tokens, a measure designed to prevent a security vulnerability known as replay attacks.

Request flow

Overview of the flow to exchange refresh token for new access token
Sequence diagram of exchanging refresh token for new access token

1. Integration partner sends refresh token to Wolt auth service

Your system sends the current refresh token, your client ID and client secret to Wolt’s auth service.

2. Wolt auth service returns a new access token

Wolt’s auth service returns a new access token and a new refresh token. The previous access token and refresh token are invalidated and can no longer be used.

3. Integration partner stores the new refresh token

Your system must store the new refresh token returned in the response. This new refresh token is then used the next time you need to exchange refresh token for a new access token.

Base URL

Example request

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "{{client_id}}:{{client_secret}}" \
-d "grant_type=refresh_token" \
-d "refresh_token={{refresh_token}}"

Headers

Header nameTypeDescription

Authorization

Required

Authorization header using basic auth. Must be Base64 encoding of client_id and client_secret joined by a single colon :.

Example: client_id:client_secret -> Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQK

Content-TypeRequiredMust be Content-Type: application/x-www-form-urlencoded.

Request fields

Field nameTypeDescription
grant_typeRequiredMust be set to refresh_token.
refresh_tokenRequiredThe refresh token obtained from the previous refresh request, or from exchanging authorization code for access and refresh tokens.

Example response

{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImVmMmY2MGE5LTI0NzItNDZjMC1iYWQyLTQ2NzNiZTMwYTFjMCIsInR5cCI6IkpXVCJ9.eyJhdWQiOltdLCJjbGllbnRfaWQiOiIxNGM5ZDFhMy04N2UzLTQ4NGMtODg5MS01MGJlMTJkNGU5ZDkiLCJleHAiOjE3MTAzNDQ4ODIsImV4dCI6e30sImlhdCI6MTcxMDM0MTI4MiwiaXNzIjoiaHR0cHM6Ly9pbnRlZ3JhdGlvbnMtYXV0aGVudGljYXRpb24tc2VydmljZS5kZXZlbG9wbWVudC5kZXYud29sdGFwaS5jb20vIiwianRpIjoiZWU1N2ExZjItNTEyOC00ZDg4LThjNDAtNzExZmNiM2E4NmQzIiwibmJmIjoxNzEwMzQxMjgyLCJzY3AiOlsib2ZmbGluZSJdLCJzdWIiOiI2NWYxYmM4ZDhjOTk4ZTU2M2UzNDlmODEifQ.jGOWuVB5gsKzC7_R0GeiN40vxrqJHWXRyNMpnXpsIs-ajzf-G6TDqeMZTJHy6Z_68Y-zWDQ9UsiBqy9aoUG5Bvci-bDf12Rfs7ZOeBEO3E3j3EBFY0y_mYDyMIP2HCAZNIYD8Oxp9wOj3WLvAh8hkhA9xW5JldYqoz9o7x72fDKftOZgVnhf2EyMGq7Dg4miuOHtsCrk2UmdEtoo0vlfh4TtkQ9v-N8lutqHtAq4z4cCxN-dBVpfWGGsDtL-r_3Bj4HsyNI7vqnjxx4OW-COEBvBoYPZpE833lpgpoP3EqD0VcJmdNy5irCxSPQsZKsst6Eygv6yfJFpPKzXSpQpyOOF-oFhIyn9RtPh8WEIjUXqGsWncAZGfNrVU4OL0WVH4tkd4-cIT4YiKtbx8SLrWVLif6MfOmCWwRk029TA5Y99q_9eMcMYw03Pj6ktSlNsnNlGQj2AfmZEGNYA-CgGIM3sonJE2vtkw3gz1twEFVel54cV7p6O6XLHnJ3CDE2ZmZHssg0utbrZqCacc9OtIiH6EZkewc-UtvMRFf6qveh_f2RIYegv0WYjYdHPgY1eMA_RqPzZOdqau1Nh4StjJ4xapfMu5Ejvf95PmX0OJxHgIEKWDplD316R5zrqQmmdHvrB8qt2BwQocCjsPxyZzyHE381FjptoUeRijUpk-JI",
"expires_in": 3600,
"refresh_token": "ory_rt_Vbtz4bfxjo5yG-l19DE34o1FKnFXASHuUQ7SyNkCykU.GqylnSfs7Rx0fo14kmcpUBwuvi-mXYyKWH-EIkjgRcA",
"scope": "offline",
"token_type": "bearer"
}

Response fields

Field nameDescription
access_tokenThe access token issued by Wolt. Use this token to authenticate against Wolt APIs.
expires_inThe lifetime of the access token in seconds. For example, the value 3600 denotes that the access token will expire in one hour from the time the token was generated.
refresh_tokenRefresh token which can be used to obtain new access and refresh tokens. You should cache the refresh token and use it to obtain a new access token when the current access token expires.
scopeScope of the token. The value offline indicates that the token can be used to obtain new access and refresh tokens.
token_typeIndicates how the token should be for authentication. Will be bearer, which means the token should be included in the Authorization header of the request.

Making requests to Wolt APIs using access token

To call Wolt APIs, you need to include the access token in the Authorization request header. The format of the header should be Authorization: Bearer {{access_token}}.

curl \
-H "Authorization: Bearer {{access_token}}" \
https://pos-integration-service.development.dev.woltapi.com/orders/67445344c6473847bc204214

For details about making requests to specific Wolt APIs, refer to our API references.

Extracting the Wolt venue ID from the access token

If the partner's system needs to programmatically access the Wolt venue ID of a venue integrated through one of the integration onboarding flows, it can be found in the decoded access token.

To extract the venue ID, you must first decode the access token. The token is a JWT (JSON Web Token), which can be split into three parts: header, payload, and signature. The venue ID is located within the payload, specifically under the integration claim.

Here’s a sample structure of a decoded access token (payload):

{
"aud": [],
"client_id": "c1dbd4af-7f74-4266-a991-ee95f81c65c0",
"exp": 1715077398,
"iat": 1715073797,
"integration": {
"id": "6638c25240880a6de5848c6a",
"venue_id": "63fc7b2dd361f21d3475dbd7"
},
"iss": "https://integrations-authentication-service.development.dev.woltapi.com/",
"jti": "7c29ee83-dabf-46da-a85e-f8a9923c4529",
"nbf": 1715073797,
"scp": ["offline"],
"sub": "6638c25240880a6de5848c6a"
}

In the example above, the venue_id (63fc7b2dd361f21d3475dbd7) is found within the integration claim. This venue ID is unique to the merchant's venue and can be used in subsequent API requests to interact with that specific venue.

Resetting integration for development purposes

Resetting integration is only available in the development environment.

When testing various integration onboarding flows, integrated venues become unavailable for re-integration. To reset venue's integration send a DELETE request to reset integration endpoint.

curl -X DELETE https://developer-gateway.development.dev.woltapi.com/integrations-middleware-service/integration-onboarding/venues/{{venue_id}} \
-H "Authorization: Basic {{credentials}}"
  • venue_id: The Wolt venue ID of the venue to reset.
  • credentials: Base64 encoding of client_id and client_secret joined by a single colon :. For example client_id:client_secret -> Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQK.

Error handling

When requesting tokens, errors may occur due to various client-side issues. The token endpoint utilizes standard HTTP response codes to communicate the outcome of requests.

The following code ranges are applicable:

  • 2xx: Token request was successful.
  • 4xx: Token request failed due to a client error.
  • 5xx: Token request failed due to a temporary server error. Retry the request after a brief delay.

Best practices for token requests

Essential tips for successful token handling:

  • Ensure all required fields are present and correctly formatted to avoid errors.

  • Remember that authorization code and tokens expire and must be used or refreshed in time.

  • Store client secrets and tokens securely.

Successful response

When the token request is successful, the response will include the requested tokens:

Response example
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjY1Zj...",
"expires_in": 3600,
"refresh_token": "ory_rt_Vbtz4bfxjo5yG-l19DE34o1FKnFXA...",
"scope": "offline",
"token_type": "bearer"
}

Error response format

When an error occurs, the response follows this standard format:

Response example
{
"error": "error_code",
"error_description": "Human-readable description of what went wrong"
}

HTTP Status Codes explained:

  • 400 (Bad Request): Indicates a client error with request parameters or format
  • 401 (Unauthorized): Indicates incorrect or missing credentials
  • 405 (Method Not Allowed): Indicates wrong HTTP method (should use POST)

Common error scenarios

1. Wrong HTTP method (HTTP 405 - Method Not Allowed)

Response example
HTTP/2 405
content-type: text/plain; charset=utf-8
allow: OPTIONS, POST
Method Not Allowed

Occurs when:

  • Using GET, PUT, DELETE instead of POST method

Example request:

curl -X PUT https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token

The token endpoint only accepts POST requests. Always use POST when requesting tokens.


2. Invalid client credentials (HTTP 401 - Unauthorized)

Response example
{
"error": "invalid_client",
"error_description": "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)."
}

Occurs when:

  • Client ID or client secret is incorrect
  • Client does not exist in the system

Example request:

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "wrong_client_id:wrong_secret" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=test_code&redirect_uri=https://example.com"

3. Malformed authorization header (HTTP 400 - Bad Request)

Response example
{
"error": "invalid_request",
"error_description": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Client credentials missing or malformed in both HTTP Authorization header and HTTP POST body."
}

Occurs when:

  • Using Bearer instead of Basic authentication scheme
  • Missing Basic prefix in Base64-encoded credentials
  • Authorization header is completely missing

Common mistakes:

Wrong: Using Bearer instead of Basic

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-H "Authorization: Bearer {{base64_encoded_client_credentials}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=token_value"

Correct: Manual Basic authentication

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-H "Authorization: Basic {{base64_encoded_client_credentials}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=token_value"

Correct: Use -u flag (recommended)

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "{{client_id}}:{{client_secret}}" \
-d "grant_type=refresh_token&refresh_token=token_value"

About Base64 encoding:

To create {{base64_encoded_client_credentials}}, encode your client_id:client_secret to Base64 using: echo -n "your_client_id:your_client_secret" | base64

However, the -u flag automatically creates the correct Authorization: Basic base64(client_id:client_secret) header and is the recommended approach.


4. Missing grant_type parameter (HTTP 400 - Bad Request)

Response example
{
"error": "invalid_request",
"error_description": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Request parameter 'grant_type' is missing"
}

Occurs when:

  • The grant_type parameter is missing from the request

Example:

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "code=test&redirect_uri=https://example.com"
# ❌ Missing required "grant_type" parameter

5. Invalid grant parameters (HTTP 400 - Bad Request)

All these scenarios return the same error: "invalid_grant" but with different specific error descriptions:

5.1 Authorization code already used
Response example
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. The authorization code has already been used."
}

Occurs when:

  • Attempting to use the same authorization code twice (codes are single-use only)

How it should work:

  1. First time: Use authorization code to get access token + refresh token
  2. After that: Use refresh token to get new access token + new refresh token

Example:

# First use - succeeds
curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=auth_code_123&redirect_uri=https://example.com"
# Second use - fails with this specific error
curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=auth_code_123&redirect_uri=https://example.com"
5.2 Authorization code issues
Response example
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."
}

Occurs when:

  • Authorization code has expired (valid for 1 hour only)
  • Authorization code is malformed or doesn't exist
  • Authorization code parameter is missing from the request

Examples:

Invalid/expired code:

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=fake_code_12345&redirect_uri=https://example.com"

Missing code parameter:

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&redirect_uri=https://example.com"
# ❌ Missing required "code" parameter
5.3 Authorization code client mismatch
Response example
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. The OAuth 2.0 Client ID from this request does not match the one from the authorize request."
}

Occurs when:

  • Authorization code was obtained for Client A but used with Client B's credentials
  • Different client credentials are used than the ones that obtained the code

Example scenario:

  • Authorization code obtained using client_a_id:client_a_secret
  • Token request made using client_b_id:client_b_secret with that same code
  • Result: This specific error even though both clients are valid
5.4 Wrong redirect URI
Response example
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. The 'redirect_uri' from this request does not match the one from the authorize request."
}

Occurs when:

  • The redirect_uri parameter doesn't exactly match the one used during authorization

Example:

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=valid_code&redirect_uri=https://test-example.com"
# ❌ This fails if the original was https://example.com
5.5 Refresh token issues

Invalid refresh token:

Response example
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. The refresh token is malformed or not valid."
}

Expired refresh token:

Response example
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. The refresh token expired."
}

Occurs when:

  • Refresh token is invalid or malformed
  • Refresh token has expired (after 30 days)

Examples:

Invalid refresh token:

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=invalid_refresh_token"

Missing refresh token parameter:

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token"
# ❌ Missing required "refresh_token" parameter
5.6 Wrong parameter combinations
Response example
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."
}

Occurs when:

  • Mixing parameters from different grant types

Example:

curl -X POST https://integrations-authentication-service.development.dev.woltapi.com/oauth2/token \
-u "{{client_id}}:{{client_secret}}" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&refresh_token=some_token&redirect_uri=https://example.com"
# ❌ Should use "code" parameter, not "refresh_token" for authorization_code grant
Integration onboarding authentication - Wolt for Developers