{
  "openapi": "3.1.0",
  "info": {
    "title": "Agile Webseite API",
    "version": "1.0.0",
    "description": "Die REST-API von **Agile Webseite** bietet alle Funktionen des Dashboards: WordPress-Websites anlegen und klonen, Domains verbinden, Backups, Seiten und Beiträge, Plugins, Anmeldelinks, Protokolle und Webhooks.\n\n## Schnellstart\n1. Im Dashboard unter **API und Webhooks** einen Schlüssel anlegen (Rechte wählen). Er wird nur einmal angezeigt.\n2. Erster Aufruf:\n```bash\ncurl -H \"Authorization: Bearer agile_web_…\" https://webseite.agiledeveloper.de/api/v1/websites\n```\n3. Seite anlegen:\n```bash\ncurl -X POST -H \"Authorization: Bearer agile_web_…\" -H \"Content-Type: application/json\" \\\n  -d '{\"titel\":\"Aktuelles\",\"inhalt\":\"Ab Montag haben wir neue Öffnungszeiten.\",\"status\":\"publish\"}' \\\n  https://webseite.agiledeveloper.de/api/v1/websites/<id>/inhalte/seiten\n```\n\n## Authentifizierung\n`Authorization: Bearer <schlüssel>` mit einem API-Schlüssel (`agile_web_…`) oder einem OAuth-Access-Token (Authorization Code mit PKCE, siehe MCP). Rechte: `websites:lesen`, `websites:schreiben`, `websites:loeschen`, `inhalte:lesen`, `inhalte:schreiben`, `backups:lesen`, `backups:schreiben`, `zugang:verwalten`, `protokolle:lesen`, `webhooks:verwalten`.\n\n## Aufträge\nLange Vorgänge (Einrichten, Backups, Wiederherstellen, Design, Domains) antworten mit **202** und einem Auftrag. Den Stand fragen Sie unter `/api/v1/auftraege/{id}` ab.\n\n## Fehler\nEinheitlich `{ \"fehler\": { \"code\", \"nachricht\", \"details\" } }` mit passendem HTTP-Status (400, 401, 403, 404, 409, 429, 500, 502).\n\n## Pagination\nListen von Seiten und Beiträgen liefern 50 Einträge je Seite (`?seite=2`). Websites, Backups und Domains kommen vollständig.\n\n## Rate-Limits\n240 Anfragen pro Minute je Schlüssel bzw. App. Jede Antwort trägt `RateLimit-Limit`, `RateLimit-Remaining` und `RateLimit-Reset`; bei 429 zusätzlich `Retry-After`.\n\n## Idempotenz\nPOST-Anfragen akzeptieren `Idempotency-Key`. Eine Wiederholung mit demselben Schlüssel liefert die gespeicherte Antwort (Header `Idempotent-Replayed: true`).\n\n## Webhooks\nEreignisse: `website.online` (Website ist online), `website.fehler` (Website-Fehler (Einrichtung oder Erreichbarkeit)), `domain.verbunden` (Domain verbunden (mit HTTPS)), `backup.fertig` (Backup fertig (manuell angestoßen)), `wiederherstellung.fertig` (Wiederherstellung abgeschlossen), `update.fehlgeschlagen` (Update fehlgeschlagen (Backup zurückgespielt)), `update.erfolgreich` (Nächtliches Update erfolgreich), `website.geloescht` (Website gelöscht). Zustellung per POST mit JSON (Schema WebhookEreignis) und Header `Agile-Signature: t=<unix>,v1=<hex>`; `v1` ist HMAC-SHA256 mit dem Webhook-Geheimnis über `<t>.<body>`. Antworten Sie mit 2xx; sonst wiederholen wir nach 1, 5, 30, 120, 360 und 1440 Minuten.\n\n## MCP für Claude und ChatGPT\nMCP-Server: `https://webseite.agiledeveloper.de/mcp` (Streamable HTTP, OAuth 2.1 mit Discovery und dynamischer Registrierung). Anleitung: [/docs/mcp](https://webseite.agiledeveloper.de/docs/mcp).",
    "contact": {
      "name": "Agile Developer",
      "email": "info@agiledeveloper.de",
      "url": "https://agiledeveloper.de"
    },
    "license": {
      "name": "Proprietär",
      "url": "https://agiledeveloper.de/impressum"
    }
  },
  "servers": [
    {
      "url": "https://webseite.agiledeveloper.de",
      "description": "Produktion"
    }
  ],
  "tags": [
    {
      "name": "Websites",
      "description": "WordPress-Websites anlegen, lesen, gestalten, klonen, abschalten und löschen."
    },
    {
      "name": "Domains",
      "description": "Eigene Domains verbinden (beliebiger Anbieter), DNS-Prüfung, HTTPS, Hauptadresse."
    },
    {
      "name": "Backups",
      "description": "Tägliche und manuelle Sicherungen, Wiederherstellen per Klick."
    },
    {
      "name": "Inhalte",
      "description": "Seiten, Beiträge und Plugins über die WordPress-REST-API."
    },
    {
      "name": "Zugang",
      "description": "Anmeldelink für WordPress, Admin-Passwort zurücksetzen."
    },
    {
      "name": "Protokolle",
      "description": "PHP-Fehler- und Zugriffsprotokolle."
    },
    {
      "name": "Konto",
      "description": "Konto und freie Plätze."
    },
    {
      "name": "Webhook-Endpunkte",
      "description": "Endpunkte für signierte Ereignisse anlegen und Zustellungen lesen."
    }
  ],
  "security": [
    {
      "apiSchluessel": []
    },
    {
      "oauth2": [
        "lesen"
      ]
    }
  ],
  "paths": {
    "/api/v1/zwecke": {
      "get": {
        "tags": [
          "Websites"
        ],
        "summary": "Website-Arten und Stile",
        "operationId": "getZwecke",
        "description": "Vorbereitete Zwecke (Handwerk, Restaurant, Praxis, Agentur, Verein, Blog, Shop, Landingpage) und Gestaltungsstile.\n\nJeder gültige Zugang.",
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      }
    },
    "/api/v1/konto": {
      "get": {
        "tags": [
          "Konto"
        ],
        "summary": "Konto und freie Plätze",
        "operationId": "getKonto",
        "description": "Jeder gültige Zugang.",
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      }
    },
    "/api/v1/websites": {
      "get": {
        "tags": [
          "Websites"
        ],
        "summary": "Websites auflisten",
        "operationId": "getWebsites",
        "description": "Recht: `websites:lesen` (OAuth: lesen).",
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "daten": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Website"
                      }
                    },
                    "kapazitaet": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Websites"
        ],
        "summary": "Neue WordPress-Website anlegen",
        "operationId": "postWebsites",
        "description": "Legt eine fertig eingerichtete WordPress-Instanz an: deutsches WordPress, Theme mit Ihren Farben, vorbereitete Seiten mit Texten (optional KI-Entwurf), Impressum- und Datenschutz-Vorlage, Kontaktformular, Menü. Die Einrichtung läuft im Hintergrund (1 bis 3 Minuten); Fortschritt über den Auftrag.\n\nRecht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional: gleiche Anfrage mit gleichem Schlüssel wird nur einmal ausgeführt (24 h).",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NeueWebsite"
              },
              "example": {
                "zweck": "handwerk",
                "firma": {
                  "name": "Malerbetrieb Muster",
                  "slogan": "Farbe mit Sorgfalt",
                  "beschreibung": "Familienbetrieb für Innen- und Fassadenarbeiten.",
                  "strasse": "Hauptstraße 1",
                  "plz": "72227",
                  "ort": "Egenhausen",
                  "telefon": "07453 123456",
                  "email": "info@malerbetrieb-muster.de",
                  "leistungen": [
                    "Innenanstrich",
                    "Fassade",
                    "Tapezieren"
                  ],
                  "oeffnungszeiten": [
                    {
                      "tage": "Montag bis Freitag",
                      "zeiten": "7:30 bis 17:00 Uhr"
                    }
                  ]
                },
                "stil": "markant",
                "farben": {
                  "haupt": "#1f4e79",
                  "akzent": "#f2a541"
                },
                "ki": true
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "website": {
                      "$ref": "#/components/schemas/Website"
                    },
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}": {
      "get": {
        "tags": [
          "Websites"
        ],
        "summary": "Website lesen",
        "operationId": "getWebsitesId",
        "description": "Mit Status, Domains, Ressourcen, Firmendaten und laufendem Auftrag.\n\nRecht: `websites:lesen` (OAuth: lesen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Website"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Websites"
        ],
        "summary": "Website endgültig löschen",
        "operationId": "deleteWebsitesId",
        "description": "Löscht Container, Datenbank, Dateien und Backups. Zur Bestätigung muss im Body `bestaetigung` die Vorschau-Adresse (Slug) stehen.\n\nRecht: `websites:loeschen` (OAuth: loeschen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "bestaetigung"
                ],
                "properties": {
                  "bestaetigung": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "bestaetigung": "malerbetrieb-muster"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "loeschen"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/design": {
      "post": {
        "tags": [
          "Websites"
        ],
        "summary": "Farben, Stil oder Logo ändern",
        "operationId": "postWebsitesIdDesign",
        "description": "Recht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Design"
              },
              "example": {
                "farben": {
                  "haupt": "#0b5e5a"
                },
                "stil": "modern"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/firmendaten": {
      "put": {
        "tags": [
          "Websites"
        ],
        "summary": "Firmendaten ändern",
        "operationId": "putWebsitesIdFirmendaten",
        "description": "Aktualisiert Fußbereich, Seitentitel und Angaben für Vorlagen. Bestehende Seiteninhalte bleiben unverändert.\n\nRecht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Firma"
              },
              "example": {
                "name": "Malerbetrieb Muster",
                "slogan": "Farbe mit Sorgfalt",
                "beschreibung": "Familienbetrieb für Innen- und Fassadenarbeiten.",
                "strasse": "Hauptstraße 1",
                "plz": "72227",
                "ort": "Egenhausen",
                "telefon": "07453 123456",
                "email": "info@malerbetrieb-muster.de",
                "leistungen": [
                  "Innenanstrich",
                  "Fassade",
                  "Tapezieren"
                ],
                "oeffnungszeiten": [
                  {
                    "tage": "Montag bis Freitag",
                    "zeiten": "7:30 bis 17:00 Uhr"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/suchmaschinen": {
      "post": {
        "tags": [
          "Websites"
        ],
        "summary": "Für Suchmaschinen freigeben oder sperren",
        "operationId": "postWebsitesIdSuchmaschinen",
        "description": "Neue Websites sind zunächst für Suchmaschinen gesperrt, bis Texte, Impressum und Datenschutz geprüft sind.\n\nRecht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "an"
                ],
                "properties": {
                  "an": {
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "an": true
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/klonen": {
      "post": {
        "tags": [
          "Websites"
        ],
        "summary": "Kopie anlegen (Staging)",
        "operationId": "postWebsitesIdKlonen",
        "description": "Legt eine vollständige Kopie unter neuer Vorschau-Adresse an, z. B. zum gefahrlosen Testen.\n\nRecht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "name": "Testkopie"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "website": {
                      "$ref": "#/components/schemas/Website"
                    },
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/zustand": {
      "post": {
        "tags": [
          "Websites"
        ],
        "summary": "Website abschalten oder starten",
        "operationId": "postWebsitesIdZustand",
        "description": "Recht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "aktiv"
                ],
                "properties": {
                  "aktiv": {
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "aktiv": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/domains": {
      "get": {
        "tags": [
          "Domains"
        ],
        "summary": "Domains und DNS-Anleitung",
        "operationId": "getWebsitesIdDomains",
        "description": "Recht: `websites:lesen` (OAuth: lesen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Domains"
        ],
        "summary": "Eigene Domain verbinden",
        "operationId": "postWebsitesIdDomains",
        "description": "Egal bei welchem Anbieter: Die Antwort enthält die nötigen DNS-Einträge (A/AAAA bzw. CNAME). Wir prüfen danach automatisch; sobald die Domain auf uns zeigt, wird HTTPS eingerichtet und die erste Domain zur Hauptadresse.\n\nRecht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional: gleiche Anfrage mit gleichem Schlüssel wird nur einmal ausgeführt (24 h).",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain"
                ],
                "properties": {
                  "domain": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "domain": "malerbetrieb-muster.de"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainEintrag"
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/domains/{did}": {
      "delete": {
        "tags": [
          "Domains"
        ],
        "summary": "Domain trennen",
        "operationId": "deleteWebsitesIdDomainsDid",
        "description": "Recht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "did",
            "in": "path",
            "required": true,
            "description": "Domain-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "geloescht": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/domains/{did}/pruefen": {
      "post": {
        "tags": [
          "Domains"
        ],
        "summary": "DNS jetzt prüfen",
        "operationId": "postWebsitesIdDomainsDidPruefen",
        "description": "Recht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "did",
            "in": "path",
            "required": true,
            "description": "Domain-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/hauptdomain": {
      "post": {
        "tags": [
          "Domains"
        ],
        "summary": "Hauptadresse festlegen",
        "operationId": "postWebsitesIdHauptdomain",
        "description": "`domain: null` stellt auf die Vorschau-Adresse zurück. Alle Links in WordPress werden umgeschrieben.\n\nRecht: `websites:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "example": {
                "domain": "malerbetrieb-muster.de"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/backups": {
      "get": {
        "tags": [
          "Backups"
        ],
        "summary": "Backups auflisten",
        "operationId": "getWebsitesIdBackups",
        "description": "Täglich, vor jedem Update und manuell. Aufbewahrung: 7 tägliche, 3 vor Updates, 5 manuelle.\n\nRecht: `backups:lesen` (OAuth: lesen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "daten": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Backup"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Backups"
        ],
        "summary": "Backup jetzt anlegen",
        "operationId": "postWebsitesIdBackups",
        "description": "Recht: `backups:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional: gleiche Anfrage mit gleichem Schlüssel wird nur einmal ausgeführt (24 h).",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/backups/{bid}/wiederherstellen": {
      "post": {
        "tags": [
          "Backups"
        ],
        "summary": "Backup zurückspielen",
        "operationId": "postWebsitesIdBackupsBidWiederherstellen",
        "description": "Ersetzt Dateien und Datenbank durch den Stand des Backups. Vorher entsteht automatisch eine Sicherung des aktuellen Stands.\n\nRecht: `websites:loeschen` (OAuth: loeschen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "bid",
            "in": "path",
            "required": true,
            "description": "Backup-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "loeschen"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/inhalte/{typ}": {
      "get": {
        "tags": [
          "Inhalte"
        ],
        "summary": "Seiten oder Beiträge auflisten",
        "operationId": "getWebsitesIdInhalteTyp",
        "description": "Recht: `inhalte:lesen` (OAuth: lesen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "typ",
            "in": "path",
            "required": true,
            "description": "seiten oder beitraege",
            "schema": {
              "type": "string",
              "enum": [
                "seiten",
                "beitraege"
              ]
            }
          },
          {
            "name": "suche",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seite",
            "in": "query",
            "description": "Seitennummer (50 je Seite)",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "daten": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Inhalt"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Inhalte"
        ],
        "summary": "Seite oder Beitrag anlegen",
        "operationId": "postWebsitesIdInhalteTyp",
        "description": "`inhalt` als einfacher Text (Absätze, „## Überschrift“, „- Liste“) oder als Gutenberg-Block-Markup. Status draft (Standard), publish oder private.\n\nRecht: `inhalte:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "typ",
            "in": "path",
            "required": true,
            "description": "seiten oder beitraege",
            "schema": {
              "type": "string",
              "enum": [
                "seiten",
                "beitraege"
              ]
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional: gleiche Anfrage mit gleichem Schlüssel wird nur einmal ausgeführt (24 h).",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InhaltEingabe"
              },
              "example": {
                "titel": "Unsere Preise",
                "inhalt": "## Preise\n\nAlle Preise inklusive Material.\n\n- Innenanstrich ab Anfrage\n- Fassade nach Besichtigung",
                "status": "publish"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Inhalt"
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/inhalte/{typ}/{pid}": {
      "get": {
        "tags": [
          "Inhalte"
        ],
        "summary": "Seite oder Beitrag lesen",
        "operationId": "getWebsitesIdInhalteTypPid",
        "description": "Recht: `inhalte:lesen` (OAuth: lesen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "typ",
            "in": "path",
            "required": true,
            "description": "seiten oder beitraege",
            "schema": {
              "type": "string",
              "enum": [
                "seiten",
                "beitraege"
              ]
            }
          },
          {
            "name": "pid",
            "in": "path",
            "required": true,
            "description": "WordPress-id der Seite bzw. des Beitrags",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Inhalt"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      },
      "patch": {
        "tags": [
          "Inhalte"
        ],
        "summary": "Seite oder Beitrag ändern",
        "operationId": "patchWebsitesIdInhalteTypPid",
        "description": "Recht: `inhalte:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "typ",
            "in": "path",
            "required": true,
            "description": "seiten oder beitraege",
            "schema": {
              "type": "string",
              "enum": [
                "seiten",
                "beitraege"
              ]
            }
          },
          {
            "name": "pid",
            "in": "path",
            "required": true,
            "description": "WordPress-id der Seite bzw. des Beitrags",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InhaltEingabe"
              },
              "example": {
                "status": "publish"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Inhalt"
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Inhalte"
        ],
        "summary": "In den Papierkorb",
        "operationId": "deleteWebsitesIdInhalteTypPid",
        "description": "Recht: `inhalte:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "typ",
            "in": "path",
            "required": true,
            "description": "seiten oder beitraege",
            "schema": {
              "type": "string",
              "enum": [
                "seiten",
                "beitraege"
              ]
            }
          },
          {
            "name": "pid",
            "in": "path",
            "required": true,
            "description": "WordPress-id der Seite bzw. des Beitrags",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/plugins": {
      "get": {
        "tags": [
          "Inhalte"
        ],
        "summary": "Plugins auflisten",
        "operationId": "getWebsitesIdPlugins",
        "description": "Recht: `inhalte:lesen` (OAuth: lesen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Inhalte"
        ],
        "summary": "Plugin aktivieren oder deaktivieren",
        "operationId": "postWebsitesIdPlugins",
        "description": "Installiert bei Bedarf aus wordpress.org (Slug, z. B. wordpress-seo).\n\nRecht: `inhalte:schreiben` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "slug"
                ],
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "aktiv": {
                    "type": "boolean",
                    "default": true
                  }
                }
              },
              "example": {
                "slug": "wordpress-seo",
                "aktiv": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/anmeldelink": {
      "post": {
        "tags": [
          "Zugang"
        ],
        "summary": "Einmal-Anmeldelink für WordPress",
        "operationId": "postWebsitesIdAnmeldelink",
        "description": "Gilt 90 Sekunden und genau einmal. Öffnet das WordPress-Dashboard ohne Passwort.\n\nRecht: `zugang:verwalten` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ziel": {
                    "type": "string",
                    "default": "/wp-admin/"
                  }
                }
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "adresse": {
                      "type": "string"
                    },
                    "gueltig_sekunden": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/admin-passwort": {
      "post": {
        "tags": [
          "Zugang"
        ],
        "summary": "Admin-Passwort zurücksetzen",
        "operationId": "postWebsitesIdAdminPasswort",
        "description": "Das neue Passwort steht genau einmal im Ergebnis des Auftrags.\n\nRecht: `zugang:verwalten` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "auftrag": {
                      "$ref": "#/components/schemas/Auftrag"
                    }
                  }
                },
                "example": {
                  "auftrag": {
                    "id": "5c0f6c1e-2b1a-4c55-9f0e-7d3a1b2c3d4e",
                    "art": "backup",
                    "status": "offen",
                    "created_at": "2026-10-11T10:00:00Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/websites/{id}/protokolle": {
      "get": {
        "tags": [
          "Protokolle"
        ],
        "summary": "PHP-Fehler oder Zugriffe",
        "operationId": "getWebsitesIdProtokolle",
        "description": "Recht: `protokolle:lesen` (OAuth: lesen).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Website-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "art",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "fehler",
                "zugriffe"
              ],
              "default": "fehler"
            }
          },
          {
            "name": "anzahl",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      }
    },
    "/api/v1/auftraege/{aid}": {
      "get": {
        "tags": [
          "Websites"
        ],
        "summary": "Auftrag abfragen",
        "operationId": "getAuftraegeAid",
        "description": "Status offen, laeuft, fertig oder fehler; `schritt` beschreibt den aktuellen Schritt.\n\nRecht: `websites:lesen` (OAuth: lesen).",
        "parameters": [
          {
            "name": "aid",
            "in": "path",
            "required": true,
            "description": "Auftrags-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Auftrag"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      }
    },
    "/api/v1/ereignisse": {
      "get": {
        "tags": [
          "Webhook-Endpunkte"
        ],
        "summary": "Ereignistypen",
        "operationId": "getEreignisse",
        "description": "Jeder gültige Zugang.",
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "lesen"
            ]
          }
        ]
      }
    },
    "/api/v1/webhooks": {
      "get": {
        "tags": [
          "Webhook-Endpunkte"
        ],
        "summary": "Webhooks auflisten",
        "operationId": "getWebhooks",
        "description": "Recht: `webhooks:verwalten` (OAuth: schreiben).",
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Webhook-Endpunkte"
        ],
        "summary": "Webhook anlegen",
        "operationId": "postWebhooks",
        "description": "Nur https. Das Geheimnis wird nur in dieser Antwort gezeigt.\n\nRecht: `webhooks:verwalten` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional: gleiche Anfrage mit gleichem Schlüssel wird nur einmal ausgeführt (24 h).",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "website.online",
                        "website.fehler",
                        "domain.verbunden",
                        "backup.fertig",
                        "wiederherstellung.fertig",
                        "update.fehlgeschlagen",
                        "update.erfolgreich",
                        "website.geloescht"
                      ]
                    }
                  },
                  "description": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "url": "https://example.com/hooks/agile",
                "events": [
                  "website.online",
                  "update.fehlgeschlagen"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Eingabe ungültig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "409": {
            "description": "Konflikt (Zustand, Limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/webhooks/{wid}": {
      "delete": {
        "tags": [
          "Webhook-Endpunkte"
        ],
        "summary": "Webhook löschen",
        "operationId": "deleteWebhooksWid",
        "description": "Recht: `webhooks:verwalten` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "wid",
            "in": "path",
            "required": true,
            "description": "Webhook-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    },
    "/api/v1/webhooks/{wid}/zustellungen": {
      "get": {
        "tags": [
          "Webhook-Endpunkte"
        ],
        "summary": "Zustellprotokoll",
        "operationId": "getWebhooksWidZustellungen",
        "description": "Recht: `webhooks:verwalten` (OAuth: schreiben).",
        "parameters": [
          {
            "name": "wid",
            "in": "path",
            "required": true,
            "description": "Webhook-id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "403": {
            "description": "Recht fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit überschritten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fehler"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiSchluessel": []
          },
          {
            "oauth2": [
              "schreiben"
            ]
          }
        ]
      }
    }
  },
  "webhooks": {
    "website.online": {
      "post": {
        "operationId": "webhookWebsiteOnline",
        "security": [],
        "summary": "Website ist online",
        "description": "Ereignis `website.online`. Signatur im Header Agile-Signature prüfen.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEreignis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empfang bestätigt"
          }
        }
      }
    },
    "website.fehler": {
      "post": {
        "operationId": "webhookWebsiteFehler",
        "security": [],
        "summary": "Website-Fehler (Einrichtung oder Erreichbarkeit)",
        "description": "Ereignis `website.fehler`. Signatur im Header Agile-Signature prüfen.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEreignis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empfang bestätigt"
          }
        }
      }
    },
    "domain.verbunden": {
      "post": {
        "operationId": "webhookDomainVerbunden",
        "security": [],
        "summary": "Domain verbunden (mit HTTPS)",
        "description": "Ereignis `domain.verbunden`. Signatur im Header Agile-Signature prüfen.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEreignis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empfang bestätigt"
          }
        }
      }
    },
    "backup.fertig": {
      "post": {
        "operationId": "webhookBackupFertig",
        "security": [],
        "summary": "Backup fertig (manuell angestoßen)",
        "description": "Ereignis `backup.fertig`. Signatur im Header Agile-Signature prüfen.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEreignis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empfang bestätigt"
          }
        }
      }
    },
    "wiederherstellung.fertig": {
      "post": {
        "operationId": "webhookWiederherstellungFertig",
        "security": [],
        "summary": "Wiederherstellung abgeschlossen",
        "description": "Ereignis `wiederherstellung.fertig`. Signatur im Header Agile-Signature prüfen.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEreignis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empfang bestätigt"
          }
        }
      }
    },
    "update.fehlgeschlagen": {
      "post": {
        "operationId": "webhookUpdateFehlgeschlagen",
        "security": [],
        "summary": "Update fehlgeschlagen (Backup zurückgespielt)",
        "description": "Ereignis `update.fehlgeschlagen`. Signatur im Header Agile-Signature prüfen.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEreignis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empfang bestätigt"
          }
        }
      }
    },
    "update.erfolgreich": {
      "post": {
        "operationId": "webhookUpdateErfolgreich",
        "security": [],
        "summary": "Nächtliches Update erfolgreich",
        "description": "Ereignis `update.erfolgreich`. Signatur im Header Agile-Signature prüfen.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEreignis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empfang bestätigt"
          }
        }
      }
    },
    "website.geloescht": {
      "post": {
        "operationId": "webhookWebsiteGeloescht",
        "security": [],
        "summary": "Website gelöscht",
        "description": "Ereignis `website.geloescht`. Signatur im Header Agile-Signature prüfen.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEreignis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Empfang bestätigt"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Fehler": {
        "type": "object",
        "required": [
          "fehler"
        ],
        "properties": {
          "fehler": {
            "type": "object",
            "required": [
              "code",
              "nachricht"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Maschinenlesbarer Code, z. B. anmeldung, recht, eingabe, limit"
              },
              "nachricht": {
                "type": "string"
              },
              "details": {}
            }
          }
        },
        "example": {
          "fehler": {
            "code": "recht",
            "nachricht": "Diesem Zugang fehlt das Recht „inhalte:schreiben“.",
            "details": {
              "benoetigt": "inhalte:schreiben"
            }
          }
        }
      },
      "Firma": {
        "type": "object",
        "required": [
          "name",
          "email"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "slogan": {
            "type": "string"
          },
          "beschreibung": {
            "type": "string",
            "description": "Was Sie machen, für wen, was Sie auszeichnet (Grundlage für KI-Texte)"
          },
          "strasse": {
            "type": "string"
          },
          "plz": {
            "type": "string"
          },
          "ort": {
            "type": "string"
          },
          "telefon": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Empfänger für Kontaktanfragen"
          },
          "inhaber": {
            "type": "string"
          },
          "register": {
            "type": "string"
          },
          "ustid": {
            "type": "string"
          },
          "leistungen": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 9
          },
          "oeffnungszeiten": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "tage": {
                  "type": "string"
                },
                "zeiten": {
                  "type": "string"
                }
              }
            }
          }
        },
        "example": {
          "name": "Malerbetrieb Muster",
          "slogan": "Farbe mit Sorgfalt",
          "beschreibung": "Familienbetrieb für Innen- und Fassadenarbeiten.",
          "strasse": "Hauptstraße 1",
          "plz": "72227",
          "ort": "Egenhausen",
          "telefon": "07453 123456",
          "email": "info@malerbetrieb-muster.de",
          "leistungen": [
            "Innenanstrich",
            "Fassade",
            "Tapezieren"
          ],
          "oeffnungszeiten": [
            {
              "tage": "Montag bis Freitag",
              "zeiten": "7:30 bis 17:00 Uhr"
            }
          ]
        }
      },
      "NeueWebsite": {
        "type": "object",
        "required": [
          "zweck",
          "firma"
        ],
        "properties": {
          "zweck": {
            "type": "string",
            "enum": [
              "handwerk",
              "restaurant",
              "praxis",
              "agentur",
              "verein",
              "blog",
              "shop",
              "landingpage"
            ]
          },
          "firma": {
            "$ref": "#/components/schemas/Firma"
          },
          "stil": {
            "type": "string",
            "enum": [
              "modern",
              "klassisch",
              "markant",
              "freundlich"
            ]
          },
          "farben": {
            "type": "object",
            "properties": {
              "haupt": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "akzent": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              }
            }
          },
          "adresse": {
            "type": "string",
            "description": "Wunsch für die Vorschau-Adresse <adresse>.webseite.agiledeveloper.de"
          },
          "ki": {
            "type": "boolean",
            "default": true,
            "description": "Texte als KI-Entwurf aus den Firmendaten schreiben lassen"
          },
          "logo": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "daten": {
                "type": "string",
                "description": "data:image/png;base64,…"
              }
            }
          }
        }
      },
      "Design": {
        "type": "object",
        "properties": {
          "farben": {
            "type": "object",
            "properties": {
              "haupt": {
                "type": "string"
              },
              "akzent": {
                "type": "string"
              }
            }
          },
          "stil": {
            "type": "string",
            "enum": [
              "modern",
              "klassisch",
              "markant",
              "freundlich"
            ]
          },
          "logo": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "daten": {
                "type": "string"
              }
            }
          }
        }
      },
      "Website": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "zweck": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "wird_eingerichtet",
              "online",
              "fehler",
              "gestoppt",
              "wird_geloescht"
            ]
          },
          "status_text": {
            "type": [
              "string",
              "null"
            ]
          },
          "adresse": {
            "type": "string"
          },
          "vorschau_adresse": {
            "type": "string"
          },
          "haupt_domain": {
            "type": [
              "string",
              "null"
            ]
          },
          "suchmaschinen_freigegeben": {
            "type": "boolean"
          },
          "domains": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DomainEintrag"
            }
          },
          "ressourcen": {
            "type": "object",
            "properties": {
              "speicher_mb": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "datenbank_mb": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "arbeitsspeicher_mb": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "cpu_prozent": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "speicher_limit_mb": {
                "type": "integer"
              }
            }
          },
          "wordpress_version": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "DomainEintrag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "wartet",
              "verbunden",
              "fehler"
            ]
          },
          "https": {
            "type": "boolean"
          },
          "pruef_text": {
            "type": [
              "string",
              "null"
            ]
          },
          "anleitung": {
            "type": "object"
          }
        }
      },
      "Backup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "art": {
            "type": "string",
            "enum": [
              "taeglich",
              "vor_update",
              "manuell",
              "vor_wiederherstellung"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "laeuft",
              "fertig",
              "fehler"
            ]
          },
          "groesse_mb": {
            "type": [
              "number",
              "null"
            ]
          },
          "wp_version": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          }
        }
      },
      "Auftrag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "art": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "offen",
              "laeuft",
              "fertig",
              "fehler"
            ]
          },
          "schritt": {
            "type": [
              "string",
              "null"
            ]
          },
          "ergebnis": {
            "type": [
              "object",
              "null"
            ]
          },
          "fehler": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          }
        }
      },
      "Inhalt": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "titel": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "adresse": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "geaendert": {
            "type": [
              "string",
              "null"
            ]
          },
          "inhalt": {
            "type": "string"
          }
        }
      },
      "InhaltEingabe": {
        "type": "object",
        "properties": {
          "titel": {
            "type": "string"
          },
          "inhalt": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "publish",
              "private"
            ]
          },
          "slug": {
            "type": "string"
          }
        }
      },
      "WebhookEreignis": {
        "type": "object",
        "description": "Body jeder Webhook-Zustellung",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "typ": {
            "type": "string",
            "enum": [
              "website.online",
              "website.fehler",
              "domain.verbunden",
              "backup.fertig",
              "wiederherstellung.fertig",
              "update.fehlgeschlagen",
              "update.erfolgreich",
              "website.geloescht"
            ]
          },
          "erstellt": {
            "type": "string",
            "format": "date-time"
          },
          "daten": {
            "type": "object"
          }
        },
        "example": {
          "id": "9b1f0c5e-0000-4000-8000-000000000001",
          "typ": "website.online",
          "erstellt": "2026-10-11T12:00:00Z",
          "daten": {
            "website": "…",
            "adresse": "https://malerbetrieb-muster.webseite.agiledeveloper.de"
          }
        }
      }
    },
    "securitySchemes": {
      "apiSchluessel": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "agile_web_…",
        "description": "API-Schlüssel aus dem Dashboard (API und Webhooks)."
      },
      "oauth2": {
        "type": "oauth2",
        "description": "Authorization Code mit PKCE (S256). Clients registrieren sich dynamisch unter /oauth/register.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://webseite.agiledeveloper.de/oauth/authorize",
            "tokenUrl": "https://webseite.agiledeveloper.de/oauth/token",
            "refreshUrl": "https://webseite.agiledeveloper.de/oauth/token",
            "scopes": {
              "lesen": "Lesen",
              "schreiben": "Ändern und anlegen",
              "loeschen": "Löschen und Backups zurückspielen"
            }
          }
        }
      }
    }
  }
}