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

> OAuth-2.1-Autorisierungsserver der Admin Interface API: Authorization Code Flow mit PKCE, Zustimmungsseite im Admin Interface, Scopes und Token-Ausgabe.

Die API-Referenz OAuth beschreibt den Autorisierungsserver der REST API.

Über OAuth können externe Anwendungen (z. B. MCP-Clients oder KI-Assistenten) im Namen eines Benutzerkontos auf die REST API zugreifen, ohne dass Benutzername, Passwort oder API-Schlüssel an die Anwendung weitergegeben werden.\
Der Benutzer meldet sich dazu im Admin Interface an, prüft die angefragten Berechtigungen und erteilt der Anwendung seine Zustimmung. Die Anwendung erhält anschließend ein `access_token`, das nur die freigegebenen Berechtigungen enthält.

## Unterstützte Methoden

Angabe aller unterstützten Methoden.

| **Befehl/Info** | **Endpunkte** | **GET** | **POST** | **PUT** | **DELETE** |
| - | - | - | - | - | - |
| **Server-Metadaten** | .well-known/oauth-authorization-server | <br /><Icon icon="check" /> | <br /><Icon icon="ban" /> | <br /><Icon icon="ban" /> | <br /><Icon icon="ban" /> |
| **Autorisierung** | 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" /> |

## Allgemein

Der Autorisierungsserver folgt OAuth 2.1 und unterstützt ausschließlich den Authorization Code Flow mit PKCE (Methode `S256`). Clients sind öffentliche Clients: Sie authentifizieren sich am Token-Endpunkt nicht mit einem Client-Secret, sondern ausschließlich über den `code_verifier`.

### Ablauf

1. Der Client ruft die Server-Metadaten (`GET .well-known/oauth-authorization-server`) ab und ermittelt daraus die URLs des Autorisierungs- und Token-Endpunkts.
2. Der Client leitet den Browser des Benutzers auf `GET oauth/authorize` weiter.
3. Die REST-API prüft die Anfrage und leitet den Browser auf die Zustimmungsseite im Admin Interface weiter. Ist der Benutzer nicht angemeldet, meldet er sich zunächst an.
4. Auf der Zustimmungsseite wählt der Benutzer die Berechtigungen aus, die er der Anwendung erteilen möchte, und bestätigt oder lehnt die Anfrage ab.
5. Der Browser wird an die `redirect_uri` des Clients zurückgeleitet – bei Zustimmung mit einem Autorisierungscode (`code`), bei Ablehnung mit dem Fehler `access_denied`.
6. Der Client tauscht den Autorisierungscode über `POST oauth/token` gegen ein `access_token` und ein `refresh_token`.

Das erhaltene `access_token` wird wie bei der regulären Anmeldung im Header `X-Authorization` mitgesendet (siehe [API Basics](/schnittstellen/admin-interface-api/api-basics)).

### Client-Registrierung

Eine vorherige Registrierung des Clients im Shop ist nicht erforderlich. Als `client_id` dient eine HTTPS-URL, unter der der Client ein JSON-Dokument mit seinen Metadaten bereitstellt (Client ID Metadata Document). Das Dokument muss mindestens die Felder `client_id`, `client_name` und `redirect_uris` enthalten. Der Wert von `client_id` im Dokument muss exakt der URL entsprechen, unter der das Dokument abgerufen wird.

```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": "Beispiel-Client",
    "client_uri": "https://client.example.com",
    "redirect_uris": [
        "https://client.example.com/oauth/callback"
    ]
}
```

Die `redirect_uri` einer Autorisierungsanfrage wird exakt mit den im Dokument hinterlegten `redirect_uris` verglichen. Bei Loopback-Adressen (z. B. `http://127.0.0.1/callback`) darf lediglich der Port abweichen.

### Scopes

Ein Scope entspricht genau einem Recht eines Berechtigungsbereichs und hat die Form `<bereich>:<recht>`, z. B. `configuration:read`. Die verfügbaren Scopes ergeben sich aus den Rechten, die für Benutzerkonten vergeben werden können (siehe [API-Referenz Benutzerverwaltung](/schnittstellen/admin-interface-api/api-referenz-benutzerverwaltung)), und werden in den Server-Metadaten unter `scopes_supported` aufgelistet.

Ein Benutzer kann nur Scopes erteilen, deren Rechte er selbst besitzt. Das ausgestellte `access_token` enthält ausschließlich die erteilten Rechte, auch wenn das Benutzerkonto weitergehende Rechte besitzt. Der Scope `admin:active` entspricht dem Vollzugriff und kann nur von Administratoren erteilt werden.

### Gültigkeitsdauer

Die Autorisierungsanfrage (Parameter `request` der Zustimmungsseite) ist 10 Minuten gültig, der Autorisierungscode 1 Minute. Der Autorisierungscode kann nur einmal eingelöst werden. Auch ein `refresh_token` ist nur einmal verwendbar: Bei jeder Erneuerung wird ein neues `refresh_token` ausgegeben und das bisherige ungültig.

## Verwendung der Methoden

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

Dieser Endpunkt liefert die Metadaten des Autorisierungsservers gemäß RFC 8414. Er ist ohne Anmeldung erreichbar.

#### Beispiel

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

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "authorization_endpoint": "https://www.<ihr-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.<ihr-shop>.de/admin/api/v1",
    "response_types_supported": ["code"],
    "scopes_supported": ["configuration:read", "configuration:write", ...],
    "token_endpoint": "https://www.<ihr-shop>.de/admin/api/v1/oauth/token",
    "token_endpoint_auth_methods_supported": ["none"]
}
```

### GET oauth/authorize

Dieser Endpunkt ist der Einstiegspunkt des Autorisierungsablaufs. Er wird ohne Anmeldung vom Browser des Benutzers aufgerufen, prüft die Anfrage und leitet bei Erfolg auf die Zustimmungsseite im Admin Interface weiter.

Die Anfrage wird über die Query-Parameter `response_type` (immer `code`), `client_id`, `redirect_uri`, `code_challenge` und `code_challenge_method` (immer `S256`) beschrieben. Optional können über den Parameter `scope` die gewünschten Scopes durch Leerzeichen getrennt angegeben werden. Wird `scope` nicht angegeben, entscheidet der Benutzer auf der Zustimmungsseite allein über die erteilten Rechte. Der optionale Parameter `state` wird bei der Rückleitung unverändert an den Client zurückgegeben, ebenso wird der optionale Parameter `resource` übernommen.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-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>
```

#### Antwort

Bei Erfolg wird der Browser auf die Zustimmungsseite des Admin Interface weitergeleitet:

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

#### Fehlercodes

| **Fehler** | **Typ** | **Grund** |
| - | - | - |
| 400 Bad Request | "unsupported\_response\_type" | `response_type` ist nicht `code`. |
| 400 Bad Request | "invalid\_request" | `code_challenge` fehlt oder `code_challenge_method` ist nicht `S256`. <br /> `redirect_uri` ist im Metadaten-Dokument des Clients nicht hinterlegt. |
| 400 Bad Request | "invalid\_client" | `client_id` ist keine HTTPS-URL mit Pfad. <br /> Das Metadaten-Dokument des Clients konnte nicht abgerufen werden. <br /> Das Metadaten-Dokument ist unvollständig oder kein JSON-Objekt. <br /> Die `client_id` im Metadaten-Dokument weicht von der abgerufenen URL ab. |
| 400 Bad Request | "invalid\_scope" | Ein angefragter Scope existiert nicht. |

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

Dieser Endpunkt liefert die Angaben zu einer offenen Autorisierungsanfrage, die auf der Zustimmungsseite angezeigt werden. Er wird vom Admin Interface aufgerufen und erfordert eine Anmeldung.

#### Beispiel

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

#### Antwort

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

#### Fehlercodes

| **Fehler** | **Typ** | **Grund** |
| - | - | - |
| 404 Not Found | "invalid\_request" | Die Autorisierungsanfrage ist unbekannt oder abgelaufen. |

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

Dieser Endpunkt erteilt einer offenen Autorisierungsanfrage die Zustimmung. Er wird vom Admin Interface aufgerufen und erfordert eine Anmeldung. Es wird ein Autorisierungscode für das angemeldete Benutzerkonto erzeugt und die URL zurückgegeben, auf die der Browser zum Client weitergeleitet werden muss. Die URL enthält die Parameter `code`, `state` (sofern angegeben) und `iss`.

Im Request Body werden die erteilten Scopes übergeben. Es können nur Scopes erteilt werden, die der Client angefragt hat (oder beliebige, wenn der Client keine angefragt hat) und deren Rechte das angemeldete Benutzerkonto selbst besitzt.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-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"]
}
```

#### Antwort

```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.<ihr-shop>.de%2Fadmin%2Fapi%2Fv1"
}
```

#### Fehlercodes

| **Fehler** | **Typ** | **Grund** |
| - | - | - |
| 400 Bad Request | | Request body konnte nicht geladen werden. |
| 400 Bad Request | "invalid\_scope" | Es wurde kein Scope übergeben. <br /> Ein Scope wurde vom Client nicht angefragt oder das Benutzerkonto besitzt das entsprechende Recht nicht. |
| 404 Not Found | "invalid\_request" | Die Autorisierungsanfrage ist unbekannt oder abgelaufen. |
| 503 Service Unavailable | "internalError" | Der Autorisierungscode konnte nicht erzeugt werden. |

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

Dieser Endpunkt lehnt eine offene Autorisierungsanfrage ab. Er wird vom Admin Interface aufgerufen und erfordert eine Anmeldung. Es wird kein Autorisierungscode erzeugt. Zurückgegeben wird die URL, auf die der Browser zum Client weitergeleitet werden muss. Die URL enthält den Parameter `error=access_denied` sowie `state` (sofern angegeben) und `iss`.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-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"]}}
{}
```

#### Antwort

```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.<ihr-shop>.de%2Fadmin%2Fapi%2Fv1"
}
```

#### Fehlercodes

| **Fehler** | **Typ** | **Grund** |
| - | - | - |
| 404 Not Found | "invalid\_request" | Die Autorisierungsanfrage ist unbekannt oder abgelaufen. |

### POST oauth/token

Dieser Endpunkt stellt ein `access_token` und ein `refresh_token` aus. Er ist ohne Anmeldung erreichbar. Anders als die übrigen Endpunkte der REST API erwartet er keinen JSON-Body, sondern formularkodierte Parameter (`application/x-www-form-urlencoded`).

Über den Parameter `grant_type` wird festgelegt, ob ein Autorisierungscode eingelöst (`authorization_code`) oder ein bestehendes Token erneuert wird (`refresh_token`). Beim Einlösen eines Autorisierungscodes werden zusätzlich `code`, `client_id`, `redirect_uri` und `code_verifier` übergeben, wobei `client_id` und `redirect_uri` mit der ursprünglichen Autorisierungsanfrage übereinstimmen müssen. Beim Erneuern werden `refresh_token` und `client_id` übergeben. Ein `refresh_token` wird nur von dem Client akzeptiert, für den es ausgestellt wurde.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-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>
```

oder

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

#### Antwort

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

#### Fehlercodes

| **Fehler** | **Typ** | **Grund** |
| - | - | - |
| 400 Bad Request | "unsupported\_grant\_type" | `grant_type` ist weder `authorization_code` noch `refresh_token`. |
| 400 Bad Request | "invalid\_grant" | Der Autorisierungscode ist unbekannt oder abgelaufen. <br /> Der Autorisierungscode wurde für einen anderen Client oder eine andere `redirect_uri` ausgestellt. <br /> `code_verifier` ist nicht korrekt. <br /> Das `refresh_token` ist unbekannt oder abgelaufen. <br /> Das `refresh_token` wurde nicht für diesen Client ausgestellt. <br /> Das Konto ist gesperrt oder nicht verfügbar. |
| 503 Service Unavailable | "internalError" | Die Tokens konnten nicht erstellt werden. |


## Related topics

- [API Basics](/schnittstellen/admin-interface-api/api-basics.md)
- [Admin Interface API](/schnittstellen/admin-interface-api.md)
- [app - WEBSALE APP](/konfiguration/app-websale-app.md)
- [authentication - Authentifizierungs- & Zugriffsdaten](/konfiguration/authentication-authentifizierungs-zugriffsdaten.md)
- [Konfigurations-Deeplinks](/admin-interface/konfigurations-deeplinks.md)


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