> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# API reference OAuth

> OAuth 2.1 authorization server of the Admin Interface API: authorization code flow with PKCE, consent page in the admin interface, scopes and token issuance.

The OAuth API reference describes the authorization server of the REST API.

OAuth allows external applications (e.g. MCP clients or AI assistants) to access the REST API on behalf of a user account without the username, password or API key being passed to the application.\
To do so, the user logs in to the admin interface, reviews the requested permissions and gives the application their consent. The application then receives an `access_token` that contains only the granted permissions.

## Supported methods

List of all supported methods.

| **Command/info** | **Endpoints** | **GET** | **POST** | **PUT** | **DELETE** |
| - | - | - | - | - | - |
| **Server metadata** | .well-known/oauth-authorization-server | <br /><Icon icon="check" /> | <br /><Icon icon="ban" /> | <br /><Icon icon="ban" /> | <br /><Icon icon="ban" /> |
| **Authorization** | oauth/authorize/ | <br /><Icon icon="check" /> | <br /><Icon icon="check" /> | <br /><Icon icon="ban" /> | <br /><Icon icon="ban" /> |
| **Token** | oauth/token | <br /><Icon icon="ban" /> | <br /><Icon icon="check" /> | <br /><Icon icon="ban" /> | <br /><Icon icon="ban" /> |

## General

The authorization server follows OAuth 2.1 and supports only the authorization code flow with PKCE (method `S256`). Clients are public clients: they do not authenticate at the token endpoint with a client secret, but solely via the `code_verifier`.

### Flow

1. The client retrieves the server metadata (`GET .well-known/oauth-authorization-server`) and determines the URLs of the authorization and token endpoints from it.
2. The client redirects the user's browser to `GET oauth/authorize`.
3. The REST-API validates the request and redirects the browser to the consent page in the admin interface. If the user is not logged in, they log in first.
4. On the consent page, the user selects the permissions they want to grant to the application and approves or denies the request.
5. The browser is redirected back to the client's `redirect_uri` – with an authorization code (`code`) on approval, or with the error `access_denied` on denial.
6. The client exchanges the authorization code via `POST oauth/token` for an `access_token` and a `refresh_token`.

As with the regular login, the `access_token` received is sent in the `X-Authorization` header (see [API basics](/en/schnittstellen/admin-interface-api/api-basics)).

### Client registration

The client does not need to be registered in the shop beforehand. The `client_id` is an HTTPS URL at which the client provides a JSON document with its metadata (Client ID Metadata Document). The document must contain at least the fields `client_id`, `client_name` and `redirect_uris`. The value of `client_id` in the document must exactly match the URL from which the document is retrieved.

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "client_id": "https://client.example.com/oauth/client.json",
    "client_name": "Example client",
    "client_uri": "https://client.example.com",
    "redirect_uris": [
        "https://client.example.com/oauth/callback"
    ]
}
```

The `redirect_uri` of an authorization request is compared exactly with the `redirect_uris` listed in the document. For loopback addresses (e.g. `http://127.0.0.1/callback`), only the port may differ.

### Scopes

A scope corresponds to exactly one permission of a permission area and has the form `<area>:<permission>`, e.g. `configuration:read`. The available scopes are derived from the permissions that can be assigned to user accounts (see [API reference user management](/en/schnittstellen/admin-interface-api/api-referenz-benutzerverwaltung)) and are listed in the server metadata under `scopes_supported`.

A user can only grant scopes whose permissions they hold themselves. The issued `access_token` contains only the granted permissions, even if the user account has further permissions. The scope `admin:active` corresponds to full access and can only be granted by administrators.

### Validity

The authorization request (parameter `request` of the consent page) is valid for 10 minutes, the authorization code for 1 minute. The authorization code can only be redeemed once. A `refresh_token` can also be used only once: each renewal issues a new `refresh_token` and invalidates the previous one.

## Using the methods

### GET .well-known/oauth-authorization-server

This endpoint returns the metadata of the authorization server according to RFC 8414. It is accessible without login.

#### Example

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<your-shop>.de/admin/api/v1/.well-known/oauth-authorization-server
```

#### Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "authorization_endpoint": "https://www.<your-shop>.de/admin/api/v1/oauth/authorize",
    "authorization_response_iss_parameter_supported": true,
    "client_id_metadata_document_supported": true,
    "code_challenge_methods_supported": ["S256"],
    "grant_types_supported": ["authorization_code", "refresh_token"],
    "issuer": "https://www.<your-shop>.de/admin/api/v1",
    "response_types_supported": ["code"],
    "scopes_supported": ["configuration:read", "configuration:write", ...],
    "token_endpoint": "https://www.<your-shop>.de/admin/api/v1/oauth/token",
    "token_endpoint_auth_methods_supported": ["none"]
}
```

### GET oauth/authorize

This endpoint is the entry point of the authorization flow. It is called by the user's browser without login, validates the request and, on success, redirects to the consent page in the admin interface.

The request is described via the query parameters `response_type` (always `code`), `client_id`, `redirect_uri`, `code_challenge` and `code_challenge_method` (always `S256`). Optionally, the requested scopes can be specified, separated by spaces, via the `scope` parameter. If `scope` is not specified, the user alone decides on the consent page which permissions are granted. The optional parameter `state` is returned unchanged to the client on redirect; the optional parameter `resource` is also taken over.

#### Example

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<your-shop>.de/admin/api/v1/oauth/authorize?response_type=code&client_id=https%3A%2F%2Fclient.example.com%2Foauth%2Fclient.json&redirect_uri=https%3A%2F%2Fclient.example.com%2Foauth%2Fcallback&code_challenge=<code challenge>&code_challenge_method=S256&scope=orders%3Aread%20products%3Aread&state=<state>
```

#### Response

On success, the browser is redirected to the consent page of the admin interface:

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<your-shop>.de/admin/oauth/authorize/?request=<request token>
```

#### Error codes

| **Error** | **Type** | **Reason** |
| - | - | - |
| 400 Bad Request | "unsupported\_response\_type" | `response_type` is not `code`. |
| 400 Bad Request | "invalid\_request" | `code_challenge` is missing or `code_challenge_method` is not `S256`. <br /> `redirect_uri` is not listed in the client's metadata document. |
| 400 Bad Request | "invalid\_client" | `client_id` is not an HTTPS URL with a path. <br /> The client's metadata document could not be retrieved. <br /> The metadata document is incomplete or not a JSON object. <br /> The `client_id` in the metadata document differs from the retrieved URL. |
| 400 Bad Request | "invalid\_scope" | A requested scope does not exist. |

### GET oauth/authorize/\{request}

This endpoint returns the details of a pending authorization request that are shown on the consent page. It is called by the admin interface and requires login.

#### Example

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<your-shop>.de/admin/api/v1/oauth/authorize/<request token>
```

#### Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "clientName": "Example client",
    "clientUri": "https://client.example.com",
    "redirectUri": "https://client.example.com/oauth/callback",
    "scopes": ["orders:read", "products:read"]
}
```

#### Error codes

| **Error** | **Type** | **Reason** |
| - | - | - |
| 404 Not Found | "invalid\_request" | The authorization request is unknown or has expired. |

### POST oauth/authorize/\{request}/approve

This endpoint approves a pending authorization request. It is called by the admin interface and requires login. An authorization code is created for the logged-in user account, and the URL to which the browser must be redirected back to the client is returned. The URL contains the parameters `code`, `state` (if specified) and `iss`.

The granted scopes are passed in the request body. Only scopes that the client requested (or any, if the client requested none) and whose permissions the logged-in user account holds itself can be granted.

#### Example

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<your-shop>.de/admin/api/v1/oauth/authorize/<request token>/approve
```

#### Request body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "scopes": ["orders:read", "products:read"]
}
```

#### Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "redirectUrl": "https://client.example.com/oauth/callback?code=<code>&state=<state>&iss=https%3A%2F%2Fwww.<your-shop>.de%2Fadmin%2Fapi%2Fv1"
}
```

#### Error codes

| **Error** | **Type** | **Reason** |
| - | - | - |
| 400 Bad Request | | Request body could not be loaded. |
| 400 Bad Request | "invalid\_scope" | No scope was passed. <br /> A scope was not requested by the client or the user account does not hold the corresponding permission. |
| 404 Not Found | "invalid\_request" | The authorization request is unknown or has expired. |
| 503 Service Unavailable | "internalError" | The authorization code could not be created. |

### POST oauth/authorize/\{request}/deny

This endpoint denies a pending authorization request. It is called by the admin interface and requires login. No authorization code is created. The URL to which the browser must be redirected back to the client is returned. The URL contains the parameter `error=access_denied` as well as `state` (if specified) and `iss`.

#### Example

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<your-shop>.de/admin/api/v1/oauth/authorize/<request token>/deny
```

#### Request body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{}
```

#### Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "redirectUrl": "https://client.example.com/oauth/callback?error=access_denied&state=<state>&iss=https%3A%2F%2Fwww.<your-shop>.de%2Fadmin%2Fapi%2Fv1"
}
```

#### Error codes

| **Error** | **Type** | **Reason** |
| - | - | - |
| 404 Not Found | "invalid\_request" | The authorization request is unknown or has expired. |

### POST oauth/token

This endpoint issues an `access_token` and a `refresh_token`. It is accessible without login. Unlike the other REST API endpoints, it does not expect a JSON body but form-encoded parameters (`application/x-www-form-urlencoded`).

The `grant_type` parameter determines whether an authorization code is redeemed (`authorization_code`) or an existing token is renewed (`refresh_token`). When redeeming an authorization code, `code`, `client_id`, `redirect_uri` and `code_verifier` are passed in addition, where `client_id` and `redirect_uri` must match the original authorization request. When renewing, `refresh_token` and `client_id` are passed. A `refresh_token` is only accepted from the client it was issued to.

#### Example

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<your-shop>.de/admin/api/v1/oauth/token
```

#### Request body

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
grant_type=authorization_code&code=<code>&client_id=<client id>&redirect_uri=<redirect uri>&code_verifier=<code verifier>
```

or

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
grant_type=refresh_token&refresh_token=<refresh token>&client_id=<client id>
```

#### Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "access_token": <accessToken>,
    "token_type": "Bearer",
    "expires_in": <validity in seconds>,
    "refresh_token": <refreshToken>,
    "scope": "orders:read products:read"
}
```

#### Error codes

| **Error** | **Type** | **Reason** |
| - | - | - |
| 400 Bad Request | "unsupported\_grant\_type" | `grant_type` is neither `authorization_code` nor `refresh_token`. |
| 400 Bad Request | "invalid\_grant" | The authorization code is unknown or has expired. <br /> The authorization code was issued for another client or another `redirect_uri`. <br /> `code_verifier` is not correct. <br /> The `refresh_token` is unknown or has expired. <br /> The `refresh_token` was not issued for this client. <br /> The account is locked or not available. |
| 503 Service Unavailable | "internalError" | The tokens could not be created. |


## Related topics

- [API basics](/en/schnittstellen/admin-interface-api/api-basics.md)
- [Admin Interface API](/en/schnittstellen/admin-interface-api.md)
- [app - WEBSALE APP](/en/konfiguration/app-websale-app.md)
- [authentication - Authentication & access data](/en/konfiguration/authentication-authentifizierungs-zugriffsdaten.md)
- [Configuration deep links](/en/admin-interface/konfigurations-deeplinks.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.