# Der MCP-Dienst für KI-Assistenten

Der MCP-Dienst gibt einem KI-Assistenten eine kuratierte Auswahl an Werkzeugen auf Ihren Bestand: Szenen und Medien ansehen, Displays und Standorte prüfen, Entwürfe vorschlagen und, nach ausdrücklicher Bestätigung, ein Programm setzen. Diese Seite nennt die Adresse, die Anmeldung, die Werkzeuge, die Grenzen und die Fehler.

> **Typ:** nachschlagen
> **Für wen:** Wer einen Assistenten anbindet, der über das Model Context Protocol spricht, oder wissen will, was ein solcher Assistent überhaupt tun kann.
> **Voraussetzung:** die Adresse des Dienstes Ihrer Umgebung und ein Ausweis: ein Zugriffstoken `oat_…` aus dem [delegierten Zugang](/de/api/oauth-delegated-access) oder ein API-Schlüssel `ak_…`

## Was der Dienst ist

Er ist ein dünner Adapter vor derselben API, die auch das Portal und die Kommandozeile benutzen. Er hält keine Daten, kennt kein Geheimnis und prüft keinen Ausweis: Ihr Bearer reist unverändert an die Plattform weiter, und die Rechteauflösung bleibt die der API. Es gibt dort keine Route, kein Feld und keine Regel, die es nur dort gäbe.

Was er beiträgt, sind vier Dinge: eine **Auswahl** statt einer Abbildung der ganzen API, eine **Bestätigung** vor jeder Wirkung, **Grenzen** für Ergebnisgröße und Laufzeit — und die Zusage, dass ein Werkzeug nur eines löscht: ein Display, das im Browser läuft.

**Der Dienst spricht Englisch.** Werkzeugnamen, Eingabefelder, Antwortfelder, Statuswerte, Fehlerarten, Beschreibungen und Hinweise sind englisch, damit ein Assistent in jeder Sprache dieselben Namen liest. Diese Seite bleibt deutsch und zitiert die Antworten des Dienstes wörtlich.

## Verbinden

| Was | Wert |
|---|---|
| Transport | Streamable HTTP nach der MCP-Spezifikation |
| Adresse | `https://mcp.<ihre-domain>/mcp` |
| Anmeldung | `Authorization: Bearer oat_…` oder `Authorization: Bearer ak_…` |
| Beschreibung der Ressource | `GET https://mcp.<ihre-domain>/.well-known/oauth-protected-resource` (RFC 9728) |
| Lebenszeichen | `GET /health/live`, `GET /health/ready` |

Ein Assistent, der OAuth beherrscht, braucht nur die Adresse: Ohne Ausweis antwortet `/mcp` mit `401` und der Kopfzeile `WWW-Authenticate`, die auf die Beschreibung der Ressource zeigt. Von dort findet der Client den Autorisierungs-Server und beginnt den Rundlauf aus [Delegierter Zugang mit OAuth 2.1](/de/api/oauth-delegated-access). Ein Werkzeug ohne diesen Weg trägt stattdessen einen API-Schlüssel ein.

Schon beim Handschlag prüft der Dienst den Ausweis einmal gegen `GET /v1/me`. Wird er abgelehnt, antwortet er `401` mit derselben Aufforderung — der Client beginnt dann die Anmeldung, statt in ein Gespräch zu geraten, in dem jedes Werkzeug scheitert.

Der Ausweis gehört an jede Anfrage, auch innerhalb einer Sitzung. Das gilt ebenso für `GET /mcp`, das den Ereignisstrom einer Sitzung öffnet, und für `DELETE /mcp`, das sie beendet. Beide prüft der Dienst bei jeder Anfrage gegen `GET /v1/me`, bevor er die Sitzung überhaupt ansieht. Ohne Ausweis antworten sie mit `401` und `error="invalid_request"`, mit einem abgelehnten Ausweis mit `401` und `error="invalid_token"`. Die Sitzungskennung allein öffnet also nichts.

Die Sitzung, die der Handschlag eröffnet, lebt **24 Stunden gleitend**: Jeder Aufruf setzt die Frist neu. Wer sie überschreitet, bekommt auf die nächste Nachricht ein **`404`** mit `{"error": "no_session"}` — das Zeichen der MCP-Spezifikation, einen neuen `initialize` zu schicken. Fehlt der Kopf `Mcp-Session-Id` ganz oder trägt er Zeichen, die eine Kennung nie trägt, antwortet der Dienst mit `400` und `{"error": "no_session_id"}`: Das ist kein Verfall, sondern eine falsch gebaute Anfrage.

## Die Rechte, um die der Client bittet

Die Beschreibung der Ressource nennt unter `scopes_supported` die Rechte, die die Werkzeuge dieses Dienstes brauchen — genau sie, keine weiteren. Dieselbe Liste steht als `scope` in der Kopfzeile `WWW-Authenticate`, damit auch ein Client sie hat, der die Beschreibung nicht abruft. Ein Client übernimmt sie unverändert in seine Anmeldung. Ohne `scope` weist der Autorisierungs-Server die Anfrage ab.

Auf der Einwilligung stehen diese Rechte danach **gebündelt zu Bereichen** — „Szenen“, „Playlisten und Zeitpläne“, „Medien“, „Displays und Standorte“, „Berichte“ —, jeder mit einem Satz und einem Schalter. Alle angefragten Bereiche sind zu Beginn eingeschaltet, und ein Mensch darf einzelne abschalten: **Die Einwilligung darf eine Teilmenge sein.** Ihr Zugriffstoken trägt dann nur die erteilten Rechte, und die Token-Antwort nennt sie unter `scope`.

Fehlt einem Werkzeug ein Recht, antwortet es `permission_denied` und nennt den **Bereich**, den die Einwilligung tragen müsste — mit den Worten des Einwilligungs-Bildschirms, in der englischen Fassung („Displays & locations“; auf einem deutschen Bildschirm steht dafür „Displays und Standorte“):

```json
{
  "error": "permission_denied",
  "hint": "The credential lacks the permission for this action. This tool works in the area \"Displays & locations\". The consent of this connection must include it.",
  "correlationId": "0198f2c1-…"
}
```

Damit kann ein Assistent seinem Menschen sagen, welchen Schalter er beim nächsten Rundlauf einschalten muss. Nachträglich erweitern lässt sich eine Einwilligung nicht — der Weg führt über Widerruf und erneutes Erlauben.

### Neue Rechte, neue Einwilligung

Kommt ein Werkzeug dazu, das ein Recht braucht, das bisher keines brauchte, wächst diese Liste — und **ein bestehendes Zugriffstoken wächst nicht mit**. Es trägt die Rechte, die zum Zeitpunkt seiner Einwilligung erteilt wurden. Die neuen sind darin nicht enthalten, und die Werkzeuge dahinter antworten mit `permission_denied`.

`whoami` sagt das, bevor es jemand ausprobiert: Es vergleicht die Rechte Ihres Ausweises mit denen, die die Werkzeuge dieses Dienstes brauchen, und nennt die fehlenden unter `missingPermissions`.

```json
{
  "account": { "…": "…" },
  "permissionCount": 14,
  "missingPermissions": ["location.create"],
  "hint": "These tools need a new consent: disconnect the connection in the client and connect again, new permissions only appear then. If a permission is still missing afterwards, the account itself does not carry it."
}
```

Der zweite Satz ist kein Beiwerk: Ein delegierter Zugang bekommt nie mehr, als das Konto dahinter hat. Steht ein Recht nach dem neuen Erlauben immer noch in der Liste, fehlt es der Rolle des Kontos — dann hilft nur, wer Rollen vergibt. Mit einem API-Schlüssel stellen Sie stattdessen einen neuen mit dem passenden Recht aus.

Alle Rechte, die dieser Dienst nennt, sieht der Rechte-Katalog für delegierten Zugang vor — auch die an Displays und an der Auswertung. Jedes Werkzeug ist damit über beide Wege erreichbar: über einen delegierten Zugang und über einen API-Schlüssel, der dieselben Rechte trägt. Was ein Werkzeug verändert, bleibt trotzdem an Ihre ausdrückliche Bestätigung gebunden (siehe unten).

## Die Werkzeuge

Die Werkzeuge stehen in drei Risikoklassen, und ein Client zeigt sie in dieser Reihenfolge.

| Klasse | Werkzeuge | Was sie tun |
|---|---|---|
| **Lesen** | `whoami`, `list_scenes`, `get_scene`, `get_scene_document`, `list_scene_templates`, `list_widgets`, `get_widget_schema`, `list_graphics`, `list_assets`, `list_players`, `get_player`, `get_player_screenshot`, `list_display_groups`, `list_locations`, `get_location`, `list_playlists`, `get_playlist`, `list_schedules`, `get_hygiene`, `validate_scene` | Bestand ansehen: wer der Ausweis ist, welche Szenen, Bausteine, Motive, Medien, Displays, Leinwände, Standorte, Playlisten und Programme es gibt, was in einer Szene steht, was auf einem Display zu sehen ist (samt seiner jüngsten Aufnahme als Bild), was liegen geblieben ist — und ob ein Szenen-Dokument die Regeln einhält |
| **Vorschlagen** | `create_scene_from_template`, `create_scene`, `update_scene`, `render_scene`, `create_playlist`, `add_to_playlist` | Entwürfe anlegen und ändern, die auf keinem Display erscheinen, solange sie niemand veröffentlicht — und eine veröffentlichte Fassung als Bild ansehen |
| **Schreiben** | `publish_scene`, `set_player_program`, `set_display_group_program`, `set_player_override`, `clear_player_override`, `send_player_command`, `assign_player_location`, `create_location`, `set_location_opening_hours`, `create_web_display`, `issue_web_display_link`, `delete_web_display` | veröffentlichen, ein Programm setzen, übersteuern und wieder freigeben, einen Fernwartungs-Befehl absetzen, ein Display einem Standort zuordnen, einen Standort anlegen, seine Öffnungszeiten setzen — und ein Display anlegen, das im Browser läuft, ihm eine neue Anschluss-Adresse geben oder es wieder wegräumen |

**Löschen gibt es genau einmal** — und nur für Displays, die im Browser laufen. `delete_web_display` nimmt ein Web-Display samt seinem Browser-Zugang aus dem Bestand und gibt den gebuchten Platz wieder frei. Das Gerät im Browser verlässt dabei die Organisation. Ein Display mit Gerät wird abgewiesen, mit eigenem Fehlercode und ohne Umweg. Sonst entfernt kein Werkzeug eine Szene, ein Medium, ein Display oder ein Konto.

Die Ausnahme hat einen engen Grund. Alles andere, was hier erreichbar ist, hat ein Gegenüber in der Welt: ein Gerät in einem Raum, eine Szene, an der jemand gearbeitet hat, eine Playliste, die eine Filiale seit Monaten fährt. Ein Web-Display hat keines — es ist eine Adresse in einem Browser, in einer Sekunde angelegt und in einer Sekunde weg. Ein Assistent, der eines anlegen kann, aber keines wegräumen, hinterlässt bei jedem Probelauf eine Karteileiche mit belegtem Platz.

Ebenso fehlen Konten- und Rollenverwaltung, die Ausgabe von Schlüsseln, die Abrechnung und alles, was der Betreiber der Plattform tut. Diese Bereiche sind im Dienst nicht verdrahtet, nicht nur ausgeblendet.

### Ein Display, auf dem etwas zu sehen ist

`create_web_display` ist der Weg, auf dem ein Assistent überhaupt etwas zeigen kann — ohne ihn setzt jedes andere Werkzeug einen Bildschirm voraus, den irgendwann jemand angeschlossen hat. Er antwortet mit der Kennung des Displays und einer **Anschluss-Adresse**. Die Adresse gehört in die Antwort an den Menschen: Sie auf dem Zielgerät im Browser zu öffnen ist der eine Schritt dieses Vorgangs, den kein Assistent selbst tun kann.

Bis das geschieht, steht das Display in der Flotte als „nicht verbunden“ (`"status": "not_connected"` in der Antwort) — mit Namen, Standort und, wenn gewünscht, schon mit seinem Programm. Es belegt von der Anlage an einen gebuchten Platz. Sind alle belegt, antwortet der Dienst mit `no_seat_available` statt mit einem technischen Fehler. Sobald ein Browser die Adresse geöffnet hat, zeigt das Display jede weitere Änderung von selbst — es muss dafür nicht neu geladen werden.

`issue_web_display_link` gibt demselben Display eine neue Adresse, wenn der Browser dahinter seine Ablage verloren hat. Wer sie öffnet, übernimmt das Display, und der Browser, der es bis dahin zeigte, verliert es. Name, Standort, Programm und der gebuchte Platz bleiben unberührt.

Die Aufräum-Fragen sind keine eigenen Werkzeuge, sondern Filter auf den Listen, die es ohnehin gibt: unbenutzte Medien, veröffentlichte Szenen ohne Zuweisung, Displays ohne Programm oder lange ohne Lebenszeichen. `get_hygiene` zählt sie und nennt zu jeder Zahl das Werkzeug, mit dem sich die Zeilen dahinter ansehen lassen.

Zwei Werkzeuge der Klasse **Vorschlagen** führen trotzdem `confirm`: `create_scene` und `update_scene`, weil dort Inhalt entsteht oder ersetzt wird, den vorher niemand gesehen hat. `render_scene` führt keine Bestätigung — es erzeugt ein Vorschaubild und sonst nichts.

## Eine Szene bauen

Der Weg von der Idee zum Bild ist eine Kette aus sechs Schritten. Jede Werkzeug-Beschreibung nennt den nächsten, damit ein Assistent die Reihenfolge nicht raten muss.

**1. Bausteine ansehen.** `list_widgets` nennt die Widgets, aus denen eine Szene besteht: die Kern-Widgets `text`, `image`, `video`, `shape`, `graphic` und `document`, die immer da sind, und die Widgets der Apps, die Ihre Organisation installiert hat. Je Eintrag stehen Kennung, App, Name, ein Satz, die Pflichtfelder und ob die App installiert ist. Ein Widget einer nicht installierten App lässt sich in ein Dokument schreiben, läuft aber auf keinem Display. Hat Ihre Organisation keine App gebucht, stehen alle App-Widgets auf `installed: false` — die Antwort sagt das dann auch im Klartext, statt es Sie raten zu lassen.

**2. Regeln holen.** `get_widget_schema` liefert zu einem Widget das vollständige JSON-Schema-Dokument seiner Konfiguration (Draft 2020-12): jedes Feld mit `title` und `description`, die Pflichtfelder unter `required` und unter `examples` mindestens eine **vollständige** Beispiel-Konfiguration. Nehmen Sie ein Beispiel und tauschen Sie die Werte aus — das ist die kürzeste Anleitung, die es gibt. Dazu kommen die Start-Konfiguration und die Vorschau-Varianten des Widgets.

Ein Feld nennt das Schema nicht mit Werten: die `graphicId` des Kern-Widgets `graphic`. Sie ist eine feste Kennung aus der Motiv-Bibliothek, und die listet `list_graphics` — mit Kategorie und Schlagworten, suchbar nach einer Absicht („pfeil“, „kaffee“). Geraten wird sie nicht. Das Schema prüft sie, kennt aber keine Liste, die es Ihnen zeigen könnte.

**3. Dokument bauen.** Ein Szenen-Dokument hat vier Felder:

```json
{
  "canvas": { "width": 1920, "height": 1080, "backgroundColor": "#ffffff" },
  "layoutTemplateId": null,
  "widgets": [
    {
      "id": "wgi_01K7Z9M4T0W14MCPTEXT000001",
      "appId": "core",
      "widgetType": "text",
      "appVersionPin": "0.0.0",
      "frame": { "x": 0, "y": 0, "w": 1920, "h": 1080 },
      "zIndex": 0,
      "config": { "content": "Welcome" }
    }
  ],
  "transitions": {
    "in": { "kind": "fade", "durationMs": 600 },
    "out": { "kind": "fade", "durationMs": 600 }
  }
}
```

`layoutTemplateId: null` ist die freie Szene: Jedes Widget sitzt allein über seinen `frame` in Pixeln der Leinwand. Mit einer Vorlage kommen benannte Bereiche dazu, an die sich ein Widget über `slotName` binden lässt — je Bereich höchstens eines. `config` ist der Teil, der aus Schritt 2 kommt.

**4. Trockenlauf.** `validate_scene` prüft das Dokument, ohne etwas zu speichern: die Form, die Layout-Bindungen, die referenzierten Medien und jede Konfiguration gegen das Schema ihres Widgets. Die Antwort nennt je Befund die Widget-Instanz und den Feldpfad:

```json
{
  "valid": false,
  "findings": [
    {
      "severity": "BLOCKING",
      "type": "ConfigSchemaIncompatible",
      "message": "widget 'wgi_…' (text): config/content must NOT have fewer than 1 characters",
      "widgetId": "wgi_…",
      "field": "/content"
    }
  ]
}
```

`BLOCKING` verhindert später das Veröffentlichen, `WARNING` nicht — ein Widget, das über den Rand der Leinwand steht, wird gemeldet und hält nichts auf.

Was der Trockenlauf meldet, kann auch später als **offene Beanstandung** an der Szene stehen — etwa, wenn ein Medium gelöscht oder eine App deinstalliert wurde. `get_scene` gibt sie unter `openIssues` mit `payload` und einem `hint` im Klartext heraus, der die Abhilfe beim Namen nennt: „Widget wgi_… is bound to the slot "main", which the scene does not have. Either it has no layout template or the template does not know this slot. Remove slotName from the widget or set layoutTemplateId to a template with this slot.“

**Die Löschung deckt genau ein Werkzeug ab.** Gelöscht wird nur ein Display, das im Browser läuft (`delete_web_display`, mit `confirm`). Displays mit Gerät, Szenen und Medien löscht kein Werkzeug.

**5. Anlegen oder ändern.** `create_scene` legt aus dem Dokument einen Entwurf an, `update_scene` ersetzt das Dokument einer bestehenden Szene. Beide laufen den Trockenlauf noch einmal selbst und schreiben bei einem blockierenden Befund **gar nichts** — Sie bekommen die Befunde zurück, aber keinen halben Entwurf im Bestand. Beide brauchen `confirm: true`. Ohne beschreiben sie nur, was sie täten.

Eine BESTEHENDE Szene zu ändern beginnt deshalb einen Schritt früher: `get_scene_document` liefert das Dokument des Entwurfs und die `version` dazu. Ändern Sie dieses Dokument, prüfen Sie es mit `validate_scene` und schicken Sie es **ganz** an `update_scene` — zusammen mit `expectedVersion` aus derselben Antwort, damit eine fremde Änderung dazwischen nicht überschrieben wird. Ein einzelnes Widget zu ändern gibt es nicht. Wer das Dokument neu erfindet statt es zu lesen, verliert jede Konfiguration, die er nicht kannte.

**6. Ansehen und nachbessern.** `render_scene` rendert eine **veröffentlichte Fassung** und liefert das Bild als PNG im Ergebnis — als Inhalt, nicht als Adresse. Ein reiner Entwurf hat keine Fassung. Veröffentlichen Sie ihn zuerst mit `publish_scene` — auf einem Display erscheint er dadurch nicht, solange ihm keines zugewiesen ist. Das Bild ist der einzige Weg, Fragen zu beantworten, die in keinem Schema stehen: ob der Text in seiner Box bleibt, ob etwas verdeckt ist, ob die Farben tragen. Passt etwas nicht, geht es mit `update_scene` und einem erneuten `publish_scene` weiter.

Braucht Ihre Umgebung kein Vorschaubild oder ist kein Schnappschuss-Dienst eingerichtet, sagt `render_scene` das im Klartext, statt einen Fehler zu werfen.

**Was auf einem Display wirklich steht**, beantwortet dagegen kein Render, sondern nur das Gerät selbst: `get_player_screenshot` liefert dessen jüngste Aufnahme — ebenfalls als Bild im Ergebnis, nicht als Adresse — zusammen mit `capturedAt`. Die Aufnahme kann einige Minuten alt sein, denn die Geräte nehmen im Takt auf und nach jedem Inhaltswechsel. Liegt noch keine vor, ist das kein Fehler: Die Antwort trägt `status: "no_screenshot"` und den Weg zu einer — `send_player_command` mit `command: "screenshot"` und `confirm: true` fordert eine an, die das Gerät bei seiner nächsten Meldung ablegt. Damit prüfen Sie, was eine Zuweisung am Bildschirm tatsächlich bewirkt hat, statt es aus dem Programm abzuleiten.

## Die Bestätigung

Jedes schreibende Werkzeug führt das Feld `confirm`. **Ohne `confirm: true` geschieht nichts:** Das Werkzeug liest den Ist-Zustand und antwortet mit einer Vorschau — welche Ziele es träfe, wie sie heißen, ob sie online sind, was ersetzt würde.

```json
{
  "status": "preview",
  "executed": false,
  "hint": "Nothing was changed. Show the effect to the human, then call the same tool again with the same values and confirm: true to execute it.",
  "effect": { "…": "…" }
}
```

Erst der zweite Aufruf mit denselben Werten und `confirm: true` führt aus und antwortet mit `"status": "executed"`, `"executed": true` und dem Ergebnis unter `result`. Die Vorschau ist ausdrücklich keine Reservierung: Sie hält nichts fest. Ändert sich zwischen beiden Aufrufen etwas, greift die Nebenläufigkeits-Prüfung der API, nicht der Dienst.

Zusätzlich tragen alle Werkzeuge die Angaben `readOnlyHint` und `destructiveHint`, damit ein Client seine eigene Rückfrage stellen kann. Jeder schreibende Aufruf reist mit einem `Idempotency-Key`, der aus Sitzung, Werkzeugname und Argumenten **abgeleitet** ist: Dieselbe Absicht wirkt einmal, auch wenn sie zweimal ankommt.

## Grenzen

| Grenze | Vorgabe |
|---|---|
| Laufzeit eines Werkzeug-Aufrufs | 30 Sekunden |
| Laufzeit eines einzelnen Aufrufs an die API | 15 Sekunden |
| Länge eines Ergebnisses | 20.000 Zeichen, darüber wird sichtbar gekürzt |
| Einträge einer Liste | 50 je Antwort. Die Zahl deckelt zugleich die angeforderte Seitengröße |
| Ruhende Sitzung | 24 Stunden, gleitend — jeder Aufruf setzt die Frist neu |

Der Betreiber Ihrer Umgebung kann diese Werte anders setzen. Ergebnisse enthalten keine signierten Download-Adressen, und Namen und Texte aus einer Antwort sind für den Assistenten **Daten**, keine Anweisungen — jede Werkzeug-Beschreibung sagt das ausdrücklich.

## Wenn etwas nicht klappt

Ein gescheitertes Werkzeug antwortet mit drei Feldern: `error` (eine der Arten unten), `hint` (ein Satz auf Englisch) und `correlationId` (die Kennung, mit der der Betrieb den Aufruf wiederfindet). Die Feldpfade und Kennungen aus dem Fehlerrumpf der API bleiben absichtlich drinnen.

| `error` | Bedeutung | Lösung |
|---|---|---|
| `unauthenticated` | Die Plattform hat den Ausweis abgewiesen (`401`). | Neu anmelden. Ein Zugriffstoken `oat_…` gilt eine Stunde. |
| `permission_denied` | Dem Ausweis fehlt das Recht (`403`). | Der Einwilligung das Recht mitgeben oder den Schlüssel mit dem passenden Recht ausstellen. |
| `not_found` | Zu dieser Kennung gibt es in dieser Organisation nichts (`404`). | Kennung aus einer Liste desselben Zugangs nehmen. |
| `conflict` | Der Gegenstand hat sich seit dem Lesen geändert (`409`). | Neu lesen und erneut entscheiden. |
| `invalid_input` | Die Plattform hat die Angaben abgelehnt (`422`). | Werte prüfen. |
| `no_seat_available` | Alle gebuchten Plätze der Organisation sind belegt (`402`). | Einen zusätzlichen Platz bucht ein Mensch im Portal. |
| `rate_limited` | Das Kontingent ist erschöpft (`429`). | Warten, siehe [Drosselung und Rate-Limit-Kopfzeilen](/de/api/rate-limits). |
| `platform_unreachable` | Die API antwortet nicht. | Später erneut versuchen. Der Dienst kann ohne sie nichts. |
| `timeout` | Die zugestandene Zeit ist abgelaufen. | Die Frage enger stellen, etwa mit einem Filter oder einer kleineren Liste. |
| `canceled` | Der Aufruf wurde abgebrochen, zum Beispiel weil die Verbindung abriss. | Erneut aufrufen. |
| `unexpected` | Die Plattform hat auf eine Weise geantwortet, die der Dienst nicht einordnen kann. | Später erneut versuchen und die `correlationId` dem Betrieb nennen. |

Ein fremder Mandant ist unsichtbar: Der Dienst hat keine eigene Identität, mit der ein Client mehr erreichen könnte, als sein Ausweis trägt.

## Weiterführendes

- [Delegierter Zugang mit OAuth 2.1](/de/api/oauth-delegated-access)
- [Anmeldung: Schlüssel und Sitzungen](/de/api/authentication)
- [Idempotenz von Anfang an](/de/getting-started/idempotency)
