{
  "openapi": "3.1.0",
  "info": {
    "title": "DomainWarn API",
    "version": "1.0.0",
    "description": "Öffentliche API von DomainWarn: Domains, Monitore, Incidents, Ereignisse und Kunden einer Organisation aus Skripten, CI-Pipelines und eigenen Integrationen lesen und schreiben.\n\nAuthentifizierung mit einem API-Token als Bearer-Token; Tokens werden im Dashboard unter Einstellungen → API erzeugt und gelten für genau eine Organisation mit dem Recht `read` oder `write`. 300 Anfragen je Minute und Token. Alle Zeitpunkte sind ISO 8601 in UTC.",
    "contact": {
      "name": "DomainWarn",
      "url": "https://domainwarn.de/docs/api",
      "email": "info@domainwarn.com"
    },
    "termsOfService": "https://domainwarn.de/legal/terms"
  },
  "externalDocs": {
    "description": "Dokumentation der API",
    "url": "https://domainwarn.de/docs/api"
  },
  "servers": [
    {
      "url": "https://api.domainwarn.com/api/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Organisation",
      "description": "Die Organisation, für die das Token gilt"
    },
    {
      "name": "Übersicht",
      "description": "Zusammenfassung wie auf der Startseite des Dashboards"
    },
    {
      "name": "Domains",
      "description": "Überwachte Domains anlegen, ändern, pausieren und prüfen"
    },
    {
      "name": "Monitore",
      "description": "Einzelne Prüfungen je Domain, ihre Ergebnisse und Verfügbarkeit"
    },
    {
      "name": "DNS",
      "description": "DNS-Schnappschüsse und Änderungen"
    },
    {
      "name": "Incidents",
      "description": "Störungen mit Ursache, Status und Quittierung"
    },
    {
      "name": "Ereignisse",
      "description": "Erkannte Änderungen und Verlauf"
    },
    {
      "name": "Kunden",
      "description": "Kunden, denen Domains zugeordnet sind"
    }
  ],
  "paths": {
    "/organizations": {
      "get": {
        "operationId": "listOrganizations",
        "tags": [
          "Organisation"
        ],
        "summary": "Organisation des Tokens",
        "description": "Liefert genau die Organisation, für die das Token gilt, mit Slug, Tarif und der Rolle des Tokens. Praktisch, um den Slug für alle weiteren Aufrufe zu ermitteln.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Organization"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/dashboard": {
      "get": {
        "operationId": "getDashboard",
        "tags": [
          "Übersicht"
        ],
        "summary": "Übersicht",
        "description": "Zähler je Zustand, offene Incidents, Änderungen der letzten 24 Stunden, Auslastung des Tarifs und Verlauf der letzten 14 Tage. Die Antwort trägt einen ETag; mit `If-None-Match` antwortet der Server bei unverändertem Stand mit 304.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "required": false,
            "description": "ETag der letzten Antwort; bei unverändertem Stand antwortet der Server mit 304 ohne Body",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Dashboard"
                    }
                  }
                }
              }
            },
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Kennung des Standes für `If-None-Match`"
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "example": "private, max-age=30"
                },
                "description": "Kurze Haltbarkeit, die Antwort ist je Organisation"
              }
            }
          },
          "304": {
            "description": "Unverändert seit dem ETag aus `If-None-Match`, kein Body",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Kennung des Standes für `If-None-Match`"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/usage": {
      "get": {
        "operationId": "getUsage",
        "tags": [
          "Übersicht"
        ],
        "summary": "Auslastung des Tarifs",
        "description": "Grenzen des wirksamen Tarifs und die aktuelle Nutzung: Domains, Monitore, Mitglieder, Kanäle und Prüfungen der letzten 24 Stunden.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Usage"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains": {
      "get": {
        "operationId": "listDomains",
        "tags": [
          "Domains"
        ],
        "summary": "Domains auflisten",
        "description": "Alle Domains der Organisation mit Zustand, Kunde und Anzahl offener Incidents, seitenweise. Monitore sind hier nicht enthalten, dafür den Einzelabruf nutzen.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Zustände, kommagetrennt: healthy, warning, critical, unknown",
            "schema": {
              "type": "string",
              "example": "critical,warning"
            }
          },
          {
            "name": "customer",
            "in": "query",
            "required": false,
            "description": "Nur Domains dieses Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "cms",
            "in": "query",
            "required": false,
            "description": "CMS-Schlüssel, kommagetrennt; `none` für erreichbar ohne bekanntes System, `unknown` für noch nicht erkannt",
            "schema": {
              "type": "string",
              "example": "wordpress"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Teil des Domainnamens",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sortierung, Minus für absteigend",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "-name",
                "health_status",
                "-health_status",
                "created_at",
                "-created_at",
                "last_checked_at",
                "-last_checked_at"
              ],
              "default": "name"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Seitennummer",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Einträge je Seite (1 bis 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Domain"
                      }
                    },
                    "links": {
                      "$ref": "#/components/schemas/Links"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createDomain",
        "tags": [
          "Domains"
        ],
        "summary": "Domain anlegen",
        "description": "Legt die Domain mit den Standard-Monitoren an und startet die erste Prüfung. Das Domainlimit des Tarifs gilt; darüber antwortet der Server mit 422.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Angelegt",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Domain"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Domain, Unicode oder Punycode; Subdomains und Schemata werden entfernt"
                  },
                  "customer_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Kunde, dem die Domain zugeordnet wird"
                  },
                  "run_checks": {
                    "type": "boolean",
                    "default": true,
                    "description": "Erste Prüfung sofort starten"
                  }
                }
              },
              "example": {
                "name": "kunde.de",
                "customer_id": null
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/domains/export.csv": {
      "get": {
        "operationId": "exportDomainsCsv",
        "tags": [
          "Domains"
        ],
        "summary": "Domains als CSV",
        "description": "Dieselbe Liste wie beim Auflisten als CSV-Datei mit allen Zeilen statt Seiten (UTF-8 mit BOM, `Content-Disposition: attachment`). Spalten: domain, customer, health, cms, cms_version, registrar, domain_expires_at, certificate_target, certificate_valid_to, certificate_days_left, open_incidents, last_checked_at, paused, dashboard_url. Das Zertifikat ist das der Apex-Domain auf Port 443, sonst das des ersten aktiven Zertifikatsmonitors (`certificate_target` nennt es).\n\nLese-Token genügt (`read`).\n\nEigenes Limit: 30 Aufrufe je Stunde und Organisation.",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Zustände, kommagetrennt: healthy, warning, critical, unknown",
            "schema": {
              "type": "string",
              "example": "critical,warning"
            }
          },
          {
            "name": "customer",
            "in": "query",
            "required": false,
            "description": "Nur Domains dieses Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "cms",
            "in": "query",
            "required": false,
            "description": "CMS-Schlüssel, kommagetrennt; `none` für erreichbar ohne bekanntes System, `unknown` für noch nicht erkannt",
            "schema": {
              "type": "string",
              "example": "wordpress"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Teil des Domainnamens",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sortierung, Minus für absteigend",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "-name",
                "health_status",
                "-health_status",
                "created_at",
                "-created_at",
                "last_checked_at",
                "-last_checked_at"
              ],
              "default": "name"
            }
          },
          {
            "name": "delimiter",
            "in": "query",
            "required": false,
            "description": "Trennzeichen; ohne Angabe Semikolon bei Sprache de (Excel), sonst Komma",
            "schema": {
              "type": "string",
              "enum": [
                "comma",
                "semicolon"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "CSV-Datei",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/cms": {
      "get": {
        "operationId": "listDomainCms",
        "tags": [
          "Domains"
        ],
        "summary": "Erkannte Systeme",
        "description": "Welche CMS und Shopsysteme auf den Domains erkannt wurden, mit Anzahl; `meta.none` zählt erreichbare Domains ohne bekanntes System, `meta.unknown` noch nicht erkannte. Werte für den Filter `cms` der Domainliste.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string",
                            "description": "CMS-Schlüssel"
                          },
                          "name": {
                            "type": "string",
                            "description": "Name"
                          },
                          "count": {
                            "type": "integer",
                            "description": "Domains"
                          }
                        }
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "none": {
                          "type": "integer",
                          "description": "Erreichbar ohne bekanntes System"
                        },
                        "unknown": {
                          "type": "integer",
                          "description": "Noch nicht erkannt"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/bulk": {
      "post": {
        "operationId": "bulkCreateDomains",
        "tags": [
          "Domains"
        ],
        "summary": "Domains gesammelt anlegen",
        "description": "Bis zu 200 Domains je Aufruf, als Liste oder als Text mit einer Domain je Zeile (Trennzeichen auch Komma, Semikolon, Leerzeichen; Zeilen mit # werden übersprungen). Ungültige oder doppelte Domains landen in `meta.errors`, die übrigen werden angelegt.\n\nBraucht ein Token mit Schreibrecht (`write`).\n\nEigenes Limit: 3 Aufrufe je Stunde und Organisation.",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Angelegte Domains und Fehler je Eingabe",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Domain"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "created": {
                          "type": "integer"
                        },
                        "failed": {
                          "type": "integer"
                        },
                        "errors": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 200,
                    "description": "Liste von Domains (alternativ zu `text`)"
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 20000,
                    "description": "Domains als Text (alternativ zu `domains`)"
                  },
                  "customer_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Kunde für alle angelegten Domains"
                  }
                }
              },
              "example": {
                "text": "kunde-a.de\nkunde-b.de\nshop.kunde-c.com",
                "customer_id": null
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/domains/import/zone-file": {
      "post": {
        "operationId": "previewZoneFileImport",
        "tags": [
          "Domains"
        ],
        "summary": "Zonendatei auswerten",
        "description": "Liest eine BIND-Zonendatei und liefert die Website-Hostnamen (A, AAAA, CNAME) als Vorschau, je Eintrag mit dem Hinweis, ob er schon überwacht wird. Höchstens 200 je Aufruf, weitere Seiten über `offset` = `next_offset`. Legt nichts an: die bestätigte Auswahl geht an den Import.\n\nBraucht ein Token mit Schreibrecht (`write`).\n\nEigenes Limit: 60 Aufrufe je Minute und Organisation.",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "origin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Erkannte Zone"
                        },
                        "records": {
                          "type": "integer",
                          "description": "Gelesene Records"
                        },
                        "hostnames": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "hostname": {
                                "type": "string"
                              },
                              "is_apex": {
                                "type": "boolean",
                                "description": "Die Zone selbst"
                              },
                              "already_monitored": {
                                "type": "boolean",
                                "description": "Ein Website-Monitor auf diesen Hostnamen besteht schon"
                              }
                            }
                          }
                        },
                        "total": {
                          "type": "integer",
                          "description": "Hostnamen insgesamt"
                        },
                        "offset": {
                          "type": "integer",
                          "description": "Erster Eintrag dieser Seite"
                        },
                        "next_offset": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Offset der nächsten Seite, null am Ende"
                        },
                        "truncated": {
                          "type": "boolean",
                          "description": "Mehr Hostnamen als eine Seite"
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Hostnamen je Seite"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "maxLength": 500000,
                    "description": "Inhalt der Zonendatei"
                  },
                  "origin": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 255,
                    "description": "Zone für Dateien ohne `$ORIGIN` (z. B. kunde.de); fehlt sie bei relativen Namen, antwortet der Server mit 422"
                  },
                  "offset": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 0,
                    "description": "Erster Eintrag der Seite (aus `next_offset`)"
                  }
                }
              },
              "example": {
                "text": "$ORIGIN kunde.de.\n@ IN A 203.0.113.10\nwww IN CNAME kunde.de.\nshop IN A 203.0.113.11"
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/domains/import/commit": {
      "post": {
        "operationId": "commitDomainImport",
        "tags": [
          "Domains"
        ],
        "summary": "Import bestätigen",
        "description": "Legt die bestätigte Liste aus einer Zonendatei im Hintergrund an, bis zu 5000 Domains je Import. Die Antwort (202) ist der Import mit seiner ID; den Fortschritt liefert `GET /domains/import/{import}`, bis `status` done oder failed ist. Anders als beim gesammelten Anlegen starten die Monitore zu ihrem regulären Zeitpunkt statt sofort. Ist das Domainlimit des Tarifs erreicht, gelten die restlichen Namen mit demselben Grund als abgelehnt.\n\nBraucht ein Token mit Schreibrecht (`write`).\n\nEigenes Limit: 10 Imports je Stunde und Organisation.",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Der angelegte Import (status queued)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DomainImport"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domains"
                ],
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 255
                    },
                    "minItems": 1,
                    "maxItems": 5000,
                    "description": "Bestätigte Domains oder Hostnamen"
                  },
                  "customer_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Kunde für alle angelegten Domains"
                  }
                }
              },
              "example": {
                "domains": [
                  "kunde.de",
                  "shop.kunde.de"
                ],
                "customer_id": null
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/domains/import/{import}": {
      "get": {
        "operationId": "getDomainImport",
        "tags": [
          "Domains"
        ],
        "summary": "Import-Fortschritt abrufen",
        "description": "Stand eines Imports: Zähler je Block, nach dem Ende die Liste der abgelehnten oder übersprungenen Namen mit Grund. Alle paar Sekunden abfragen, bis `status` done oder failed ist. Innenansicht der Agentur: Kundenzugänge sehen Imports nicht.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "import",
            "in": "path",
            "required": true,
            "description": "ID des Imports aus der Antwort auf das Bestätigen",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DomainImport"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}": {
      "get": {
        "operationId": "getDomain",
        "tags": [
          "Domains"
        ],
        "summary": "Domain abrufen",
        "description": "Eine Domain mit allen Monitoren, deren letzten Befunden und der Anzahl offener Incidents.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Domain"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "updateDomain",
        "tags": [
          "Domains"
        ],
        "summary": "Domain ändern",
        "description": "Kunde zuordnen, Überwachung ein- oder ausschalten oder Benachrichtigungsregeln nur für diese Domain setzen. Nur mitgesendete Felder ändern sich.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Domain"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "customer_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Kunde oder null zum Lösen"
                  },
                  "is_active": {
                    "type": "boolean",
                    "description": "false pausiert die Überwachung dauerhaft, true nimmt sie wieder auf"
                  },
                  "notification_overrides": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "Abweichende Benachrichtigungsregeln",
                    "properties": {
                      "failure_minutes": {
                        "type": "integer",
                        "description": "Minuten bis zur Meldung eines Ausfalls (1 bis 1440)",
                        "minimum": 1,
                        "maximum": 1440
                      },
                      "recovery_minutes": {
                        "type": "integer",
                        "description": "Minuten bis zur Entwarnung (1 bis 1440)",
                        "minimum": 1,
                        "maximum": 1440
                      },
                      "min_severity": {
                        "type": "string",
                        "enum": [
                          "info",
                          "warning",
                          "critical"
                        ],
                        "description": "Kleinster gemeldeter Schweregrad"
                      },
                      "ignore_quiet_hours": {
                        "type": "boolean",
                        "description": "Auch in den Ruhezeiten melden"
                      },
                      "notify_on_change": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Änderungsarten, die gemeldet werden"
                      }
                    }
                  }
                }
              },
              "example": {
                "customer_id": "3f9c1a52-6a2e-4c0e-9d4b-1c9a1a0e5b77",
                "notification_overrides": {
                  "min_severity": "critical"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteDomain",
        "tags": [
          "Domains"
        ],
        "summary": "Domain löschen",
        "description": "Entfernt die Domain mit Monitoren, Ergebnissen, Incidents und Ereignissen endgültig.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Gelöscht, keine Antwort"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/pause": {
      "post": {
        "operationId": "pauseDomain",
        "tags": [
          "Domains"
        ],
        "summary": "Domain pausieren",
        "description": "Setzt die Überwachung bis zu einem Zeitpunkt aus, etwa während eines Umzugs. Ohne `until` wird die Pause aufgehoben. Offene Incidents bleiben bestehen.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Domain"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "until": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Ende der Pause, in der Zukunft; null hebt die Pause auf"
                  }
                }
              },
              "example": {
                "until": "2026-10-01T06:00:00Z"
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/monitoring": {
      "patch": {
        "operationId": "setMonitoringGroups",
        "tags": [
          "Domains"
        ],
        "summary": "Überwachungsbereiche schalten",
        "description": "Schaltet die Bereiche Website (`web`: http, tls, ct_log, redirects, ipv6), Mail (`mail`: mx, spf, dkim, dmarc, mta_sts, tls_rpt, bimi, reverse_dns, smtp, dane) und DNS (`dns`: dns, dnssec, domain, blacklist, caa, nameservers) ein oder aus. Ausgeschaltete Bereiche schließen ihre offenen Incidents.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Domain"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "groups"
                ],
                "properties": {
                  "groups": {
                    "type": "object",
                    "properties": {
                      "web": {
                        "type": "boolean"
                      },
                      "mail": {
                        "type": "boolean"
                      },
                      "dns": {
                        "type": "boolean"
                      }
                    },
                    "description": "Bereiche mit gewünschtem Zustand; nicht genannte bleiben unverändert"
                  }
                }
              },
              "example": {
                "groups": {
                  "mail": false
                }
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/detect-cms": {
      "post": {
        "operationId": "detectDomainCms",
        "tags": [
          "Domains"
        ],
        "summary": "System neu erkennen",
        "description": "Reiht die Erkennung von CMS und Shopsystem für die Domain ein; das Ergebnis erscheint in `cms` der Domain.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Erkennung eingereiht",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "queued": {
                          "type": "boolean",
                          "description": "Eingereiht"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/check-now": {
      "post": {
        "operationId": "checkDomainNow",
        "tags": [
          "Domains"
        ],
        "summary": "Jetzt prüfen",
        "description": "Stellt alle aktiven Monitore der Domain sofort in die Warteschlange, z. B. nach einem Deploy oder einer DNS-Änderung. Ergebnisse erscheinen wenige Sekunden später in den Monitoren.\n\nBraucht ein Token mit Schreibrecht (`write`).\n\nEigenes Limit: 5 je Domain und Stunde, 60 je Organisation und Stunde.",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Prüfungen eingereiht",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "dispatched": {
                          "type": "integer",
                          "description": "Anzahl eingereihter Prüfungen"
                        },
                        "requested_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/fixes": {
      "get": {
        "operationId": "listFixes",
        "tags": [
          "DNS"
        ],
        "summary": "Fehlende Records",
        "description": "Vorschläge für fehlende DNS-Records (DMARC, SPF, TLS-RPT, CAA) aus den aktuellen Befunden der Domain, mit den verbundenen Cloudflare-Integrationen und ob die Zone bei Cloudflare liegt.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Fix"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "integrations": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "provider": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "dns_hosted_at_cloudflare": {
                          "type": "boolean",
                          "description": "Alle Nameserver der Domain zeigen auf Cloudflare (nur dann ist Anlegen möglich)"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/fixes/{fix}/apply": {
      "post": {
        "operationId": "applyFix",
        "tags": [
          "DNS"
        ],
        "summary": "Record bei Cloudflare anlegen",
        "description": "Legt den vorgeschlagenen Record über die angegebene Cloudflare-Integration an. Nur additiv: bestehende Records werden nie geändert; ist bereits ein passender Record vorhanden oder liegt die Zone nicht (mehr) bei Cloudflare, antwortet der Server mit 422. Der Monitor wird anschließend neu geprüft.\n\nBraucht ein Token mit Schreibrecht (`write`).\n\nEigenes Limit: 20 je Minute.",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "fix",
            "in": "path",
            "required": true,
            "description": "Schlüssel des Vorschlags aus der Liste der fehlenden Records",
            "schema": {
              "type": "string",
              "pattern": "^[a-z_]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Record angelegt",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "fix": {
                          "$ref": "#/components/schemas/Fix"
                        },
                        "record_id": {
                          "type": "string",
                          "description": "ID des angelegten Records bei Cloudflare"
                        },
                        "zone": {
                          "type": "string",
                          "description": "Name der Cloudflare-Zone"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "integration_id"
                ],
                "properties": {
                  "integration_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Cloudflare-Integration der Organisation"
                  },
                  "rua": {
                    "type": "string",
                    "description": "Berichtsadresse für dmarc_missing und tls_rpt_missing (Pflicht bei diesen Vorschlägen)"
                  },
                  "senders": {
                    "type": "string",
                    "description": "Weitere SPF-Mechanismen für spf_missing, durch Komma getrennt (include:…, ip4:…, ip6:…, a, mx); leer bestätigt, dass keine weiteren Dienste senden"
                  }
                }
              },
              "example": {
                "integration_id": "3f9c1a52-6a2e-4c0e-9d4b-1c9a1a0e5b77",
                "rua": "dmarc-reports@agentur.de"
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/suggestions": {
      "get": {
        "operationId": "listHostnameSuggestions",
        "tags": [
          "Monitore"
        ],
        "summary": "Hostnamen-Vorschläge",
        "description": "Hostnamen unter der Domain, die in Certificate-Transparency-Logs auftauchen, aber noch nicht überwacht werden. Standardmäßig nur offene; mit `all=1` auch angenommene und verworfene, seitenweise zu 200.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "all",
            "in": "query",
            "required": false,
            "description": "Auch entschiedene Vorschläge",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Seitennummer",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/HostnameSuggestion"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer"
                        },
                        "per_page": {
                          "type": "integer"
                        },
                        "has_more": {
                          "type": "boolean",
                          "description": "Weitere Seite vorhanden"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/suggestions/{suggestion}/accept": {
      "post": {
        "operationId": "acceptHostnameSuggestion",
        "tags": [
          "Monitore"
        ],
        "summary": "Vorschlag annehmen",
        "description": "Legt einen Website-Monitor auf den Hostnamen an und markiert den Vorschlag als angenommen. 422, wenn der Hostname nicht zur Domain gehört oder das Limit an Hostnamen je Domain erreicht ist.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "suggestion",
            "in": "path",
            "required": true,
            "description": "ID des Hostnamen-Vorschlags",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Angenommen",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/HostnameSuggestion"
                    },
                    "monitor": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Monitor"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Angelegter Monitor; null, wenn es ihn schon gab"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Der Vorschlag wurde bereits entschieden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/suggestions/{suggestion}/dismiss": {
      "post": {
        "operationId": "dismissHostnameSuggestion",
        "tags": [
          "Monitore"
        ],
        "summary": "Vorschlag verwerfen",
        "description": "Markiert den Vorschlag als verworfen; der Hostname wird nicht erneut vorgeschlagen.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "suggestion",
            "in": "path",
            "required": true,
            "description": "ID des Hostnamen-Vorschlags",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verworfen",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/HostnameSuggestion"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Der Vorschlag wurde bereits entschieden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/monitors": {
      "get": {
        "operationId": "listMonitors",
        "tags": [
          "Monitore"
        ],
        "summary": "Monitore einer Domain",
        "description": "Alle Monitore der Domain mit Zustand, letzten Befunden und Rohdaten, sortiert nach Prüfart und Ziel.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Monitor"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createMonitor",
        "tags": [
          "Monitore"
        ],
        "summary": "Monitor anlegen",
        "description": "Zusätzlicher Monitor, etwa eine weitere URL oder ein Mailserver-Zertifikat. Ziele müssen zur Domain gehören; nur bei `tls` ist jeder öffentliche Hostname erlaubt. Das Intervall wird auf das Minimum des Tarifs begrenzt.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Angelegt",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Monitor"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "type",
                  "target"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "http",
                      "tls",
                      "dns",
                      "mx",
                      "spf",
                      "dmarc",
                      "domain",
                      "dkim",
                      "dnssec",
                      "mta_sts",
                      "blacklist",
                      "tls_rpt",
                      "bimi",
                      "smtp",
                      "reverse_dns",
                      "ct_log",
                      "redirects",
                      "caa",
                      "nameservers",
                      "ipv6",
                      "dane"
                    ],
                    "description": "Prüfart"
                  },
                  "target": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "URL (http) oder Hostname; ohne Schema wird https:// ergänzt"
                  },
                  "interval_seconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 604800,
                    "description": "Prüfintervall in Sekunden"
                  },
                  "config": {
                    "type": "object",
                    "properties": {
                      "port": {
                        "type": "integer",
                        "enum": [
                          443,
                          8443,
                          465,
                          587,
                          25,
                          993,
                          143,
                          995,
                          110
                        ]
                      },
                      "starttls": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "enum": [
                          "smtp",
                          "imap",
                          "pop3",
                          null
                        ]
                      }
                    },
                    "description": "Nur bei tls: Port und STARTTLS-Protokoll"
                  }
                }
              },
              "example": {
                "type": "tls",
                "target": "mail.kunde.de",
                "config": {
                  "port": 587,
                  "starttls": "smtp"
                }
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/monitors/{monitor}": {
      "patch": {
        "operationId": "updateMonitor",
        "tags": [
          "Monitore"
        ],
        "summary": "Monitor ändern",
        "description": "Intervall, Aktivierung und Konfiguration je Prüfart: `expected_status` und `slow_ms` (http), `selectors` (dkim). Ein deaktivierter Monitor schließt seine offenen Incidents.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "monitor",
            "in": "path",
            "required": true,
            "description": "ID des Monitors",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Monitor"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "interval_seconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 604800,
                    "description": "Prüfintervall in Sekunden"
                  },
                  "is_enabled": {
                    "type": "boolean",
                    "description": "Aktiv"
                  },
                  "config": {
                    "type": "object",
                    "properties": {
                      "expected_status": {
                        "type": "array",
                        "items": {
                          "type": "integer",
                          "minimum": 100,
                          "maximum": 599
                        }
                      },
                      "slow_ms": {
                        "type": "integer",
                        "minimum": 100,
                        "maximum": 60000
                      },
                      "selectors": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 63
                        },
                        "maxItems": 20
                      }
                    },
                    "description": "Erwartete HTTP-Status, Schwelle für „langsam“ in ms (http) oder DKIM-Selektoren (dkim)"
                  }
                }
              },
              "example": {
                "config": {
                  "expected_status": [
                    200,
                    301
                  ],
                  "slow_ms": 2000
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteMonitor",
        "tags": [
          "Monitore"
        ],
        "summary": "Monitor löschen",
        "description": "Entfernt den Monitor und schließt seine offenen Incidents.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "monitor",
            "in": "path",
            "required": true,
            "description": "ID des Monitors",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Gelöscht, keine Antwort"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/maintenance-windows": {
      "get": {
        "operationId": "listMaintenanceWindows",
        "tags": [
          "Monitore"
        ],
        "summary": "Wartungsfenster auflisten",
        "description": "Alle Wartungsfenster der Organisation, aktive zuerst; mit `domain` nur die, die diese Domain betreffen (eigene, die ihres Kunden und die der ganzen Organisation).\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "description": "Nur Fenster, die diese Domain betreffen",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/MaintenanceWindow"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createMaintenanceWindow",
        "tags": [
          "Monitore"
        ],
        "summary": "Wartungsfenster anlegen",
        "description": "Einmalig (`starts_at`, `ends_at`) oder wöchentlich (`weekdays`, `time_from`, `time_to` in `timezone`). Mit `domain_id` gilt es für eine Domain, mit `customer_id` für alle Domains des Kunden, ohne beides für die ganze Organisation. Während des Fensters entstehen keine Incidents und Meldungen.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Angelegt",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/MaintenanceWindow"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "kind"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Bezeichnung"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "once",
                      "weekly"
                    ],
                    "description": "Einmalig oder wöchentlich"
                  },
                  "customer_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Kunde, dessen Domains betroffen sind"
                  },
                  "domain_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Einzelne Domain (setzt `customer_id` zurück)"
                  },
                  "starts_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Beginn, einmalig (Pflicht bei `once`)"
                  },
                  "ends_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Ende, einmalig, nach dem Beginn (Pflicht bei `once`)"
                  },
                  "weekdays": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 7
                    },
                    "maxItems": 7,
                    "description": "Wochentage 1 (Montag) bis 7 (Sonntag) (Pflicht bei `weekly`)"
                  },
                  "time_from": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^\\d{2}:\\d{2}$",
                    "description": "Beginn HH:MM (Pflicht bei `weekly`)"
                  },
                  "time_to": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^\\d{2}:\\d{2}$",
                    "description": "Ende HH:MM, ungleich Beginn; vor dem Beginn reicht das Fenster über Mitternacht (Pflicht bei `weekly`)"
                  },
                  "timezone": {
                    "type": "string",
                    "default": "Europe/Berlin",
                    "description": "Zeitzone für Wochentage und Uhrzeiten"
                  },
                  "is_enabled": {
                    "type": "boolean",
                    "default": true,
                    "description": "Aktiv"
                  }
                }
              },
              "example": {
                "name": "Nächtliches Deploy",
                "kind": "weekly",
                "customer_id": "3f9c1a52-6a2e-4c0e-9d4b-1c9a1a0e5b77",
                "weekdays": [
                  2,
                  4
                ],
                "time_from": "02:00",
                "time_to": "03:00",
                "timezone": "Europe/Berlin"
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/maintenance-windows/{window}": {
      "patch": {
        "operationId": "updateMaintenanceWindow",
        "tags": [
          "Monitore"
        ],
        "summary": "Wartungsfenster ändern",
        "description": "Dieselben Felder wie beim Anlegen, alle optional; nur mitgesendete Felder ändern sich. Die Regeln je Art gelten für den Stand nach der Änderung.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "window",
            "in": "path",
            "required": true,
            "description": "ID des Wartungsfensters",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/MaintenanceWindow"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Bezeichnung"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "once",
                      "weekly"
                    ],
                    "description": "Einmalig oder wöchentlich"
                  },
                  "customer_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Kunde oder null"
                  },
                  "domain_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Domain oder null"
                  },
                  "starts_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Beginn, einmalig"
                  },
                  "ends_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Ende, einmalig"
                  },
                  "weekdays": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 7
                    },
                    "maxItems": 7,
                    "description": "Wochentage 1 bis 7"
                  },
                  "time_from": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^\\d{2}:\\d{2}$",
                    "description": "Beginn HH:MM"
                  },
                  "time_to": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^\\d{2}:\\d{2}$",
                    "description": "Ende HH:MM"
                  },
                  "timezone": {
                    "type": "string",
                    "description": "Zeitzone"
                  },
                  "is_enabled": {
                    "type": "boolean",
                    "description": "Aktiv"
                  }
                }
              },
              "example": {
                "is_enabled": false
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteMaintenanceWindow",
        "tags": [
          "Monitore"
        ],
        "summary": "Wartungsfenster löschen",
        "description": "Braucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "window",
            "in": "path",
            "required": true,
            "description": "ID des Wartungsfensters",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Gelöscht, keine Antwort"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/monitors/{monitor}/results": {
      "get": {
        "operationId": "listCheckResults",
        "tags": [
          "Monitore"
        ],
        "summary": "Prüfergebnisse",
        "description": "Einzelne Prüfungen eines Monitors, neueste zuerst, cursor-paginiert. Der Cursor der nächsten Seite steht in `links.next`.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "monitor",
            "in": "path",
            "required": true,
            "description": "ID des Monitors",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Nur Prüfungen ab diesem Zeitpunkt",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Nur Prüfungen bis zu diesem Zeitpunkt",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Einträge je Seite (1 bis 500)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor der nächsten Seite aus `meta.next_cursor` der vorigen Antwort",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CheckResult"
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "next": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Cursor der nächsten Seite"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/monitors/{monitor}/uptime": {
      "get": {
        "operationId": "getUptime",
        "tags": [
          "Monitore"
        ],
        "summary": "Verfügbarkeit und Antwortzeit",
        "description": "Verfügbarkeit, Antwortzeiten (Median, 95. Perzentil) und Ausfallzeit je Zeitraum, dazu Messpunkte für Diagramme.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "monitor",
            "in": "path",
            "required": true,
            "description": "ID des Monitors",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "range",
            "in": "query",
            "required": false,
            "description": "Zeitraum",
            "schema": {
              "type": "string",
              "enum": [
                "24h",
                "7d",
                "30d",
                "90d"
              ],
              "default": "24h"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Uptime"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/dns": {
      "get": {
        "operationId": "getDns",
        "tags": [
          "DNS"
        ],
        "summary": "Aktuelle DNS-Records",
        "description": "Der jüngste DNS-Schnappschuss der Domain mit allen Records je Typ; null, solange noch keiner vorliegt.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/DnsSnapshot"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/dns/snapshots": {
      "get": {
        "operationId": "listDnsSnapshots",
        "tags": [
          "DNS"
        ],
        "summary": "DNS-Verlauf",
        "description": "Alle Schnappschüsse der Domain, neueste zuerst, ohne Records (dafür den Vergleich nutzen). Jeder Schnappschuss steht für einen Zeitraum mit unveränderter Konfiguration.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Höchstzahl",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DnsSnapshot"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/dns/diff": {
      "get": {
        "operationId": "diffDnsSnapshots",
        "tags": [
          "DNS"
        ],
        "summary": "Zwei DNS-Stände vergleichen",
        "description": "Beide Schnappschüsse mit Records und die Unterschiede dazwischen (hinzugefügte, entfernte und geänderte Records je Typ).\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "description": "ID des älteren Schnappschusses",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "ID des neueren Schnappschusses",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "from": {
                          "$ref": "#/components/schemas/DnsSnapshot"
                        },
                        "to": {
                          "$ref": "#/components/schemas/DnsSnapshot"
                        },
                        "diff": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Unterschiede je Record-Typ"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/incidents": {
      "get": {
        "operationId": "listIncidents",
        "tags": [
          "Incidents"
        ],
        "summary": "Incidents auflisten",
        "description": "Standardmäßig nur offene und quittierte Incidents, offene und kritische zuerst; cursor-paginiert.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "`open` (offen und quittiert), `all` oder Status kommagetrennt: open, acknowledged, resolved",
            "schema": {
              "type": "string",
              "default": "open",
              "example": "open"
            }
          },
          {
            "name": "severity",
            "in": "query",
            "required": false,
            "description": "Schweregrade, kommagetrennt: info, warning, critical",
            "schema": {
              "type": "string",
              "example": "critical,warning"
            }
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "description": "Nur Incidents dieser Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "customer",
            "in": "query",
            "required": false,
            "description": "Nur Domains dieses Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Einträge je Seite (1 bis 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor der nächsten Seite aus `meta.next_cursor` der vorigen Antwort",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Incident"
                      }
                    },
                    "links": {
                      "$ref": "#/components/schemas/Links"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CursorMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/incidents/{incident}": {
      "get": {
        "operationId": "getIncident",
        "tags": [
          "Incidents"
        ],
        "summary": "Incident abrufen",
        "description": "Ein Incident mit Domain, Monitor, Ursache und dem Namen des Quittierenden.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "incident",
            "in": "path",
            "required": true,
            "description": "ID des Incidents",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Incident"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/incidents/{incident}/acknowledge": {
      "post": {
        "operationId": "acknowledgeIncident",
        "tags": [
          "Incidents"
        ],
        "summary": "Incident quittieren",
        "description": "Markiert den Incident als gesehen; Erinnerungen hören auf, die Entwarnung kommt weiterhin.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "incident",
            "in": "path",
            "required": true,
            "description": "ID des Incidents",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Incident"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/events": {
      "get": {
        "operationId": "listEvents",
        "tags": [
          "Ereignisse"
        ],
        "summary": "Ereignisse auflisten",
        "description": "Erkannte Änderungen und Incident-Übergänge aller Domains, neueste zuerst, cursor-paginiert. Geeignet für eigene Auswertungen oder ein Änderungsprotokoll.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "severity",
            "in": "query",
            "required": false,
            "description": "Schweregrade, kommagetrennt: info, warning, critical",
            "schema": {
              "type": "string",
              "example": "critical,warning"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Ereignisarten, kommagetrennt",
            "schema": {
              "type": "string",
              "example": "dns.record_changed,tls.renewed"
            }
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "description": "Nur Ereignisse dieser Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "customer",
            "in": "query",
            "required": false,
            "description": "Nur Domains dieses Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Nur Ereignisse ab diesem Zeitpunkt",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Nur Ereignisse bis zu diesem Zeitpunkt",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Einträge je Seite (1 bis 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor der nächsten Seite aus `meta.next_cursor` der vorigen Antwort",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "links": {
                      "$ref": "#/components/schemas/Links"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CursorMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/domains/{domain}/timeline": {
      "get": {
        "operationId": "getDomainTimeline",
        "tags": [
          "Ereignisse"
        ],
        "summary": "Zeitleiste einer Domain",
        "description": "Ereignisse einer Domain, neueste zuerst; dieselben Filter wie bei allen Ereignissen.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "description": "ID der Domain",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "severity",
            "in": "query",
            "required": false,
            "description": "Schweregrade, kommagetrennt: info, warning, critical",
            "schema": {
              "type": "string",
              "example": "critical,warning"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Ereignisarten, kommagetrennt",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Ab Zeitpunkt",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Bis Zeitpunkt",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Einträge je Seite (1 bis 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor der nächsten Seite aus `meta.next_cursor` der vorigen Antwort",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "links": {
                      "$ref": "#/components/schemas/Links"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/CursorMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/customers": {
      "get": {
        "operationId": "listCustomers",
        "tags": [
          "Kunden"
        ],
        "summary": "Kunden auflisten",
        "description": "Kunden der Organisation mit Anzahl der Domains, alphabetisch; archivierte nur auf Wunsch.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Teil von Name oder Referenz",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "archived",
            "in": "query",
            "required": false,
            "description": "true liefert nur archivierte, false nur aktive (Standard)",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Seitennummer",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Einträge je Seite (1 bis 200)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Customer"
                      }
                    },
                    "links": {
                      "$ref": "#/components/schemas/Links"
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createCustomer",
        "tags": [
          "Kunden"
        ],
        "summary": "Kunden anlegen",
        "description": "Braucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Angelegt",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 160,
                    "description": "Name, eindeutig je Organisation"
                  },
                  "reference": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 64,
                    "description": "Eigene Referenz"
                  },
                  "notes": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 5000,
                    "description": "Notizen"
                  },
                  "contact_email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email",
                    "description": "Kontaktadresse für Berichte"
                  },
                  "monthly_report": {
                    "type": "boolean",
                    "description": "Monatlichen Bericht senden"
                  },
                  "report_locale": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "de",
                      "en",
                      null
                    ],
                    "description": "Sprache des Berichts"
                  }
                }
              },
              "example": {
                "name": "Musterfirma GmbH",
                "reference": "K-1042",
                "contact_email": "it@musterfirma.de",
                "monthly_report": true,
                "report_locale": "de"
              }
            }
          }
        }
      }
    },
    "/orgs/{organization}/customers/{customer}": {
      "get": {
        "operationId": "getCustomer",
        "tags": [
          "Kunden"
        ],
        "summary": "Kunden abrufen",
        "description": "Lese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "customer",
            "in": "path",
            "required": true,
            "description": "ID des Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "updateCustomer",
        "tags": [
          "Kunden"
        ],
        "summary": "Kunden ändern",
        "description": "Dieselben Felder wie beim Anlegen, dazu `is_archived`. `name` muss immer mitgesendet werden.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "customer",
            "in": "path",
            "required": true,
            "description": "ID des Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 160,
                    "description": "Name"
                  },
                  "reference": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 64,
                    "description": "Eigene Referenz"
                  },
                  "notes": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 5000,
                    "description": "Notizen"
                  },
                  "contact_email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email",
                    "description": "Kontaktadresse"
                  },
                  "is_archived": {
                    "type": "boolean",
                    "description": "Archivieren oder wiederherstellen"
                  },
                  "monthly_report": {
                    "type": "boolean",
                    "description": "Monatlichen Bericht senden"
                  },
                  "report_locale": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "de",
                      "en",
                      null
                    ],
                    "description": "Sprache des Berichts"
                  }
                }
              },
              "example": {
                "name": "Musterfirma GmbH",
                "is_archived": true
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteCustomer",
        "tags": [
          "Kunden"
        ],
        "summary": "Kunden löschen",
        "description": "Entfernt den Kunden; seine Domains bleiben erhalten und verlieren nur die Zuordnung.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "customer",
            "in": "path",
            "required": true,
            "description": "ID des Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Gelöscht, keine Antwort"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/customers/{customer}/report": {
      "get": {
        "operationId": "getCustomerReport",
        "tags": [
          "Kunden"
        ],
        "summary": "Monatsbericht abrufen",
        "description": "Der Monatsbericht des Kunden als Daten: Zusammenfassung, je Domain Verfügbarkeit, Ausfallzeit, Incidents und Zertifikat, dazu Incidents, Änderungen und anstehende Abläufe. Ohne `month` der Vormonat, Sprache über `locale`.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "customer",
            "in": "path",
            "required": true,
            "description": "ID des Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Berichtsmonat als YYYY-MM; Standard ist der Vormonat",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}$",
              "example": "2026-08"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Sprache des Berichts (Texte, Datumsformate); ohne Angabe die Berichtssprache des Kunden, sonst die der Organisation. Accept-Language gilt hier nicht.",
            "schema": {
              "type": "string",
              "enum": [
                "de",
                "en"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CustomerReport"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/customers/{customer}/report/pdf": {
      "get": {
        "operationId": "getCustomerReportPdf",
        "tags": [
          "Kunden"
        ],
        "summary": "Monatsbericht als PDF",
        "description": "Derselbe Bericht als PDF; `download=1` liefert ihn als Anhang statt inline.\n\nLese-Token genügt (`read`).",
        "x-scope": "read",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "customer",
            "in": "path",
            "required": true,
            "description": "ID des Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Berichtsmonat als YYYY-MM; Standard ist der Vormonat",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}$",
              "example": "2026-08"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Sprache des Berichts (Texte, Datumsformate); ohne Angabe die Berichtssprache des Kunden, sonst die der Organisation. Accept-Language gilt hier nicht.",
            "schema": {
              "type": "string",
              "enum": [
                "de",
                "en"
              ]
            }
          },
          {
            "name": "download",
            "in": "query",
            "required": false,
            "description": "Als Download (Content-Disposition attachment)",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "PDF-Datei",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/customers/{customer}/report/share": {
      "post": {
        "operationId": "shareCustomerReport",
        "tags": [
          "Kunden"
        ],
        "summary": "Bericht freigeben",
        "description": "Erzeugt einen signierten Link auf das PDF, 60 Tage gültig, ohne Login abrufbar – zum Weitergeben an den Kunden.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "customer",
            "in": "path",
            "required": true,
            "description": "ID des Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Berichtsmonat als YYYY-MM; Standard ist der Vormonat",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}$",
              "example": "2026-08"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Sprache des Berichts (Texte, Datumsformate); ohne Angabe die Berichtssprache des Kunden, sonst die der Organisation. Accept-Language gilt hier nicht.",
            "schema": {
              "type": "string",
              "enum": [
                "de",
                "en"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erfolg",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string",
                          "format": "uri",
                          "description": "Signierter Link"
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "Gültig bis"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/orgs/{organization}/customers/{customer}/status-page": {
      "post": {
        "operationId": "enableCustomerStatusPage",
        "tags": [
          "Kunden"
        ],
        "summary": "Status-Seite einschalten",
        "description": "Erzeugt das Token der öffentlichen Status-Seite des Kunden (ohne Login erreichbar); ein bestehendes wird ersetzt, die alte Adresse gilt dann nicht mehr. Die Adresse steht in `status_page_url`. Für archivierte Kunden antwortet der Server mit 422.\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "customer",
            "in": "path",
            "required": true,
            "description": "ID des Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Eingeschaltet, Adresse in `status_page_url`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "disableCustomerStatusPage",
        "tags": [
          "Kunden"
        ],
        "summary": "Status-Seite abschalten",
        "description": "Löscht das Token; die Adresse antwortet danach mit 404. Liefert den Kunden zurück (`status_page_url` ist null).\n\nBraucht ein Token mit Schreibrecht (`write`).",
        "x-scope": "write",
        "parameters": [
          {
            "name": "organization",
            "in": "path",
            "required": true,
            "description": "Slug der Organisation, steht in der Adresse des Dashboards und unter Einstellungen → API. Ein Token erreicht nur seine eigene Organisation, andere antworten mit 404.",
            "schema": {
              "type": "string",
              "example": "meine-agentur"
            }
          },
          {
            "name": "customer",
            "in": "path",
            "required": true,
            "description": "ID des Kunden",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Abgeschaltet",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API-Token aus dem Dashboard (Einstellungen → API) im Header `Authorization: Bearer <Token>`; dazu `Accept: application/json`."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Token fehlt, ist abgelaufen oder widerrufen",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Token darf das nicht (Lese-Token bei schreibender Methode oder gesperrter Bereich)",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "NotFound": {
        "description": "Organisation oder Objekt nicht gefunden, auch bei fremder Organisation",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "Organisation gesperrt oder ohne aktiven Tarif",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/PlanProblem"
            }
          }
        }
      },
      "ValidationError": {
        "description": "Eingabe ungültig, Meldungen je Feld in `errors`",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationProblem"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Limit überschritten; `Retry-After` nennt die Wartezeit in Sekunden",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      }
    },
    "schemas": {
      "Fix": {
        "type": "object",
        "description": "Vorschlag für einen fehlenden DNS-Record, den DomainWarn über eine Cloudflare-Integration anlegen kann",
        "properties": {
          "key": {
            "type": "string",
            "description": "Schlüssel des Vorschlags, z. B. dmarc_missing, spf_missing, tls_rpt_missing, caa_missing"
          },
          "finding": {
            "type": "string",
            "description": "Befund, der den Vorschlag auslöst"
          },
          "type": {
            "type": "string",
            "description": "Record-Typ (TXT, CAA)"
          },
          "name": {
            "type": "string",
            "description": "Name des Records"
          },
          "content": {
            "type": "string",
            "description": "Inhalt des Records, wie er angelegt würde"
          },
          "monitor_id": {
            "type": "string",
            "format": "uuid",
            "description": "Monitor, dessen Befund den Vorschlag auslöst"
          },
          "note_key": {
            "type": "string",
            "description": "Schlüssel des Hinweises zum Vorschlag, z. B. dmarc_missing, spf_include, spf_mx, caa_missing; das Dashboard übersetzt ihn"
          },
          "note_params": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Platzhalter des Hinweises, z. B. provider (spf_include) oder ca (caa_missing)"
          },
          "input": {
            "type": "string",
            "enum": [
              "rua",
              "senders"
            ],
            "description": "Pflichtangabe beim Anwenden: Berichtsadresse (rua) oder Versanddienste (senders); fehlt, wenn keine nötig ist"
          },
          "input_default": {
            "type": "string",
            "description": "Vorschlag für die Pflichtangabe (nur mit `input`)"
          }
        },
        "required": [
          "key",
          "finding",
          "type",
          "name",
          "content",
          "monitor_id",
          "note_key",
          "note_params"
        ]
      },
      "Organization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID der Organisation"
          },
          "name": {
            "type": "string",
            "description": "Name"
          },
          "slug": {
            "type": "string",
            "description": "Slug für die Adresse `/orgs/{organization}`"
          },
          "plan": {
            "type": "string",
            "enum": [
              "trial",
              "free",
              "freelancer",
              "agency",
              "agency_pro"
            ],
            "description": "Wirksamer Tarif: trial während der Testphase (danach free), sonst der gebuchte oder geschenkte Tarif"
          },
          "monitoring_active": {
            "type": "boolean",
            "description": "Ob die Prüfungen laufen (false bei gesperrter Organisation)"
          },
          "trial_days_left": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Verbleibende Tage der Testphase, null außerhalb der Testphase"
          },
          "timezone": {
            "type": "string",
            "description": "Zeitzone der Organisation"
          },
          "locale": {
            "type": "string",
            "enum": [
              "de",
              "en"
            ],
            "description": "Sprache der Organisation"
          },
          "suspended": {
            "type": "boolean",
            "description": "Vom Betreiber gesperrt"
          },
          "role": {
            "type": "string",
            "enum": [
              "viewer",
              "member"
            ],
            "description": "Rolle des Tokens: viewer (read) oder member (write)"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Anlagezeitpunkt"
          }
        }
      },
      "Customer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID des Kunden"
          },
          "name": {
            "type": "string",
            "description": "Name, eindeutig je Organisation"
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "description": "Eigene Referenz, z. B. Kundennummer"
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notizen"
          },
          "contact_email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "description": "Kontaktadresse für Berichte"
          },
          "is_archived": {
            "type": "boolean",
            "description": "Archiviert"
          },
          "monthly_report": {
            "type": "boolean",
            "description": "Monatlicher Kundenbericht per E-Mail"
          },
          "report_locale": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "de",
              "en",
              null
            ],
            "description": "Sprache des Berichts"
          },
          "last_report_sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Letzter Berichtsversand"
          },
          "status_page_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Öffentliche Status-Seite des Kunden (enthält das Token); null, solange keine eingeschaltet ist"
          },
          "domains_count": {
            "type": "integer",
            "description": "Anzahl zugeordneter Domains"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Anlagezeitpunkt"
          }
        }
      },
      "Monitor": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID des Monitors"
          },
          "domain_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID der Domain"
          },
          "type": {
            "type": "string",
            "enum": [
              "http",
              "tls",
              "dns",
              "mx",
              "spf",
              "dmarc",
              "domain",
              "dkim",
              "dnssec",
              "mta_sts",
              "blacklist",
              "tls_rpt",
              "bimi",
              "smtp",
              "reverse_dns",
              "ct_log",
              "redirects",
              "caa",
              "nameservers",
              "ipv6",
              "dane"
            ],
            "description": "Prüfart"
          },
          "target": {
            "type": "string",
            "description": "Ziel: URL bei http, sonst Hostname"
          },
          "config": {
            "type": "object",
            "additionalProperties": true,
            "description": "Konfiguration je Prüfart, z. B. expected_status und slow_ms (http), port und starttls (tls), selectors (dkim)"
          },
          "interval_seconds": {
            "type": "integer",
            "description": "Prüfintervall in Sekunden (vom Tarif begrenzt)"
          },
          "is_enabled": {
            "type": "boolean",
            "description": "Aktiv"
          },
          "current_status": {
            "type": "string",
            "enum": [
              "ok",
              "warning",
              "critical",
              "unknown"
            ],
            "description": "Aktueller Zustand"
          },
          "next_check_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Nächste Prüfung"
          },
          "last_checked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Letzte Prüfung"
          },
          "consecutive_failures": {
            "type": "integer",
            "description": "Fehlschläge in Folge"
          },
          "consecutive_errors": {
            "type": "integer",
            "description": "Prüffehler in Folge (Prüfung selbst nicht möglich)"
          },
          "failure_locations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Prüfstandorte, die den aktuellen Ausfall sehen; leer, solange die Prüfung besteht"
          },
          "is_volatile": {
            "type": "boolean",
            "description": "Ergebnis schwankt zwischen Prüfungen"
          },
          "last_payload": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Rohdaten der letzten Prüfung, Aufbau je Prüfart"
          },
          "last_payload_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Zeitpunkt der Rohdaten"
          },
          "last_findings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Finding"
            },
            "description": "Befunde der letzten Prüfung"
          },
          "pending_change": {
            "type": "boolean",
            "description": "Änderung erkannt, Bestätigungsprüfung steht aus"
          },
          "last_fingerprint": {
            "type": [
              "string",
              "null"
            ],
            "description": "Fingerabdruck der zuletzt gesehenen Konfiguration"
          }
        }
      },
      "Finding": {
        "type": "object",
        "description": "Befund einer Prüfung, Text in der Sprache aus dem Accept-Language-Header",
        "properties": {
          "code": {
            "type": "string",
            "description": "Maschinenlesbarer Schlüssel, z. B. spf.too_many_lookups"
          },
          "severity": {
            "type": "string",
            "enum": [
              "info",
              "warning",
              "critical"
            ],
            "description": "Schweregrad"
          },
          "params": {
            "type": "object",
            "additionalProperties": true,
            "description": "Werte zum Befund, z. B. Anzahl der Lookups"
          },
          "message": {
            "type": "string",
            "description": "Übersetzte Beschreibung"
          },
          "recommendation": {
            "type": [
              "string",
              "null"
            ],
            "description": "Übersetzte Empfehlung, wenn es eine gibt"
          }
        },
        "additionalProperties": true
      },
      "Domain": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID der Domain"
          },
          "name": {
            "type": "string",
            "description": "Domain in ASCII (Punycode)"
          },
          "unicode_name": {
            "type": "string",
            "description": "Domain in Unicode"
          },
          "customer_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "ID des Kunden"
          },
          "customer": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "ID"
              },
              "name": {
                "type": "string",
                "description": "Name"
              }
            },
            "description": "Zugeordneter Kunde"
          },
          "is_active": {
            "type": "boolean",
            "description": "Überwachung aktiv"
          },
          "paused_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Pausiert bis"
          },
          "is_paused": {
            "type": "boolean",
            "description": "Derzeit pausiert"
          },
          "in_maintenance": {
            "type": "boolean",
            "description": "Gerade in einem aktiven Wartungsfenster (keine Incidents und Meldungen)"
          },
          "plan_paused": {
            "type": "boolean",
            "description": "Vom Tarif pausiert (über dem Domainlimit)"
          },
          "cms": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "key": {
                "type": "string",
                "description": "Schlüssel, z. B. wordpress"
              },
              "name": {
                "type": "string",
                "description": "Name"
              },
              "version": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Erkannte Version"
              }
            },
            "description": "Erkanntes Content-Management-System"
          },
          "cms_detected_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Zeitpunkt der CMS-Erkennung"
          },
          "mail_detected": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Ob die Domain Mail empfängt (MX vorhanden)"
          },
          "monitoring_groups": {
            "type": "object",
            "properties": {
              "web": {
                "type": "boolean",
                "description": "Website und Zertifikate"
              },
              "mail": {
                "type": "boolean",
                "description": "Mail-Infrastruktur"
              },
              "dns": {
                "type": "boolean",
                "description": "DNS, DNSSEC, Domain und Blacklists"
              }
            },
            "description": "Ein- oder ausgeschaltete Überwachungsbereiche"
          },
          "notification_overrides": {
            "type": [
              "object",
              "null"
            ],
            "description": "Abweichende Benachrichtigungsregeln nur für diese Domain; null übernimmt die Einstellungen der Organisation",
            "properties": {
              "failure_minutes": {
                "type": "integer",
                "description": "Minuten bis zur Meldung eines Ausfalls (1 bis 1440)",
                "minimum": 1,
                "maximum": 1440
              },
              "recovery_minutes": {
                "type": "integer",
                "description": "Minuten bis zur Entwarnung (1 bis 1440)",
                "minimum": 1,
                "maximum": 1440
              },
              "min_severity": {
                "type": "string",
                "enum": [
                  "info",
                  "warning",
                  "critical"
                ],
                "description": "Kleinster gemeldeter Schweregrad"
              },
              "ignore_quiet_hours": {
                "type": "boolean",
                "description": "Auch in den Ruhezeiten melden"
              },
              "notify_on_change": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Änderungsarten, die gemeldet werden"
              }
            }
          },
          "health_status": {
            "type": "string",
            "enum": [
              "healthy",
              "warning",
              "critical",
              "unknown"
            ],
            "description": "Gesamtzustand aus allen Monitoren"
          },
          "health_computed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Zeitpunkt der Berechnung"
          },
          "last_checked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Letzte Prüfung"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Ablauf der Domain (Registry), nicht für .de"
          },
          "expiry_available": {
            "type": "boolean",
            "description": "Ob ein Ablaufdatum ermittelt werden kann"
          },
          "monitors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Monitor"
            },
            "description": "Monitore (nur bei Einzelabruf, Anlegen und Ändern)"
          },
          "open_incidents_count": {
            "type": "integer",
            "description": "Offene Incidents"
          },
          "suggestions_count": {
            "type": "integer",
            "description": "Offene Hostnamen-Vorschläge (nur bei Einzelabruf)"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Anlagezeitpunkt"
          }
        }
      },
      "HostnameSuggestion": {
        "type": "object",
        "description": "Aus Certificate-Transparency-Logs entdeckter Hostname unter einer Domain, der noch nicht überwacht wird",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID des Vorschlags"
          },
          "domain_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID der Domain"
          },
          "hostname": {
            "type": "string",
            "description": "Vorgeschlagener Hostname"
          },
          "source": {
            "type": "string",
            "enum": [
              "ct_log"
            ],
            "description": "Quelle des Vorschlags"
          },
          "status": {
            "type": "string",
            "enum": [
              "new",
              "added",
              "dismissed"
            ],
            "description": "new (offen), added (Monitor angelegt) oder dismissed (verworfen)"
          },
          "first_seen_at": {
            "type": "string",
            "format": "date-time",
            "description": "Erstmals gesehen"
          },
          "last_seen_at": {
            "type": "string",
            "format": "date-time",
            "description": "Zuletzt gesehen"
          }
        }
      },
      "DomainImport": {
        "type": "object",
        "description": "Import einer bestätigten Domainliste im Hintergrund; die Zähler wachsen blockweise, bis status done oder failed ist",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID des Imports"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "done",
              "failed"
            ],
            "description": "Wartend, läuft, abgeschlossen oder abgebrochen"
          },
          "customer_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Kunde für alle angelegten Domains"
          },
          "total": {
            "type": "integer",
            "description": "Namen im Import (ohne Leerzeilen, Kommentare und Doppelte)"
          },
          "created": {
            "type": "integer",
            "description": "Angelegt (neue Domains und Hostnamen bestehender Domains)"
          },
          "skipped": {
            "type": "integer",
            "description": "Übersprungen: bereits überwacht oder vorhanden"
          },
          "failed": {
            "type": "integer",
            "description": "Abgelehnt, Grund in errors"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Eingabe"
                },
                "reason": {
                  "type": "string",
                  "description": "Meldung"
                }
              }
            },
            "description": "Abgelehnte und übersprungene Namen mit Grund"
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Grund bei status failed"
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Beginn der Verarbeitung"
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Ende der Verarbeitung"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Angelegt am"
          }
        }
      },
      "MaintenanceWindow": {
        "type": "object",
        "description": "Wartungsfenster: für eine Domain, einen Kunden oder die ganze Organisation; währenddessen entstehen keine Incidents und Meldungen",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID des Wartungsfensters"
          },
          "name": {
            "type": "string",
            "description": "Bezeichnung"
          },
          "kind": {
            "type": "string",
            "enum": [
              "once",
              "weekly"
            ],
            "description": "Einmalig (starts_at bis ends_at) oder wöchentlich (weekdays, time_from, time_to)"
          },
          "customer_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Kunde, dessen Domains betroffen sind; null für alle"
          },
          "customer_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Name des Kunden"
          },
          "domain_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Einzelne betroffene Domain; null für alle"
          },
          "domain_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Domain in Unicode"
          },
          "starts_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Beginn (einmalig)"
          },
          "ends_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Ende (einmalig)"
          },
          "weekdays": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            },
            "description": "Wochentage 1 (Montag) bis 7 (Sonntag), wöchentlich"
          },
          "time_from": {
            "type": [
              "string",
              "null"
            ],
            "description": "Beginn HH:MM in der Zeitzone des Fensters (wöchentlich)"
          },
          "time_to": {
            "type": [
              "string",
              "null"
            ],
            "description": "Ende HH:MM; vor time_from reicht das Fenster über Mitternacht"
          },
          "timezone": {
            "type": "string",
            "description": "Zeitzone des Fensters"
          },
          "is_enabled": {
            "type": "boolean",
            "description": "Aktiv"
          },
          "is_active": {
            "type": "boolean",
            "description": "Gerade wirksam"
          },
          "is_expired": {
            "type": "boolean",
            "description": "Einmaliges Fenster, dessen Ende vorbei ist"
          }
        }
      },
      "Incident": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID des Incidents"
          },
          "domain_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID der Domain"
          },
          "domain": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "ID"
              },
              "name": {
                "type": "string",
                "description": "Domain"
              },
              "unicode_name": {
                "type": "string",
                "description": "Domain in Unicode"
              },
              "customer_id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              }
            },
            "description": "Betroffene Domain"
          },
          "monitor_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "ID des Monitors"
          },
          "monitor": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "ID"
              },
              "type": {
                "type": "string",
                "description": "Prüfart"
              },
              "target": {
                "type": "string",
                "description": "Ziel"
              }
            },
            "description": "Auslösender Monitor"
          },
          "type": {
            "type": "string",
            "description": "Art, z. B. http.down, tls.expiring, spf.invalid"
          },
          "severity": {
            "type": "string",
            "enum": [
              "info",
              "warning",
              "critical"
            ],
            "description": "Schweregrad"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "acknowledged",
              "resolved"
            ],
            "description": "Status"
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "description": "Beginn"
          },
          "acknowledged_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Quittiert am"
          },
          "acknowledged_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Name des Quittierenden"
          },
          "resolved_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Behoben am"
          },
          "resolved_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Grund der Auflösung, z. B. recovered, monitor_removed"
          },
          "failure_count": {
            "type": "integer",
            "description": "Fehlgeschlagene Prüfungen"
          },
          "notification_count": {
            "type": "integer",
            "description": "Versendete Benachrichtigungen"
          },
          "reminder_count": {
            "type": "integer",
            "description": "Versendete Erinnerungen"
          },
          "cause": {
            "type": "object",
            "additionalProperties": true,
            "description": "Ursache mit Befunden (`findings`) und Rohdaten"
          }
        }
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID des Ereignisses"
          },
          "type": {
            "type": "string",
            "description": "Art, z. B. dns.record_changed, tls.renewed, incident.opened"
          },
          "severity": {
            "type": "string",
            "enum": [
              "info",
              "warning",
              "critical"
            ],
            "description": "Schweregrad"
          },
          "domain_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "ID der Domain"
          },
          "domain": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "ID"
              },
              "name": {
                "type": "string",
                "description": "Domain"
              },
              "unicode_name": {
                "type": "string",
                "description": "Domain in Unicode"
              }
            },
            "description": "Betroffene Domain"
          },
          "monitor_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "ID des Monitors"
          },
          "incident_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Zugehöriger Incident"
          },
          "previous_value": {
            "description": "Wert vor der Änderung (Aufbau je Art)"
          },
          "new_value": {
            "description": "Wert nach der Änderung"
          },
          "context": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Weitere Angaben"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "Zeitpunkt"
          }
        }
      },
      "DnsSnapshot": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID des Schnappschusses"
          },
          "fingerprint": {
            "type": "string",
            "description": "Fingerabdruck aller Records"
          },
          "source": {
            "type": "string",
            "description": "Quelle der Abfrage"
          },
          "resolver": {
            "type": [
              "string",
              "null"
            ],
            "description": "Benutzter Resolver"
          },
          "first_seen_at": {
            "type": "string",
            "format": "date-time",
            "description": "Erstmals gesehen"
          },
          "last_seen_at": {
            "type": "string",
            "format": "date-time",
            "description": "Zuletzt bestätigt"
          },
          "previous_snapshot_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Vorheriger Schnappschuss"
          },
          "records": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "oneOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "array",
                    "prefixItems": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "string"
                      }
                    ],
                    "minItems": 2,
                    "maxItems": 2,
                    "description": "MX: [Priorität, Host]"
                  }
                ]
              }
            },
            "description": "Records je Typ (A, AAAA, MX, NS, TXT, …), MX als Paar [Priorität, Host]; fehlt in der Liste der Schnappschüsse"
          },
          "record_count": {
            "type": "integer",
            "description": "Anzahl aller Records"
          }
        }
      },
      "CheckResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "ID"
          },
          "checked_at": {
            "type": "string",
            "format": "date-time",
            "description": "Zeitpunkt"
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "warning",
              "critical",
              "error"
            ],
            "description": "Ergebnis; `error`, wenn die Prüfung nicht möglich war (dann `error_code`)"
          },
          "latency_ms": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Antwortzeit in Millisekunden"
          },
          "http_status": {
            "type": [
              "integer",
              "null"
            ],
            "description": "HTTP-Status (nur http)"
          },
          "error_code": {
            "type": [
              "integer",
              "null"
            ],
            "enum": [
              0,
              1,
              2,
              3,
              4,
              5,
              6,
              7,
              8,
              9,
              10,
              null
            ],
            "description": "Grund bei status error: 0 unbekannt, 1 Resolver nicht erreichbar, 2 Resolver-Timeout, 3 Abruf nicht möglich, 4 Ziel vom Schutz abgelehnt, 5 Timeout, 6 interner Fehler, 7 Ausfall vom zweiten Standort widerlegt (zählt nicht als Ausfall), 8 Hilfsprobe eines zweiten Standorts (zählt nicht in die Verfügbarkeit), 9 Domain existiert nicht (NXDOMAIN), 10 Prüfung unvollständig (Zeitbudget: nicht alle Nameserver erreicht, kein Urteil)"
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "Prüfstandort, z. B. primary; null bei älteren Ergebnissen"
          },
          "payload": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Rohdaten"
          },
          "findings": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/Finding"
            },
            "description": "Befunde"
          }
        }
      },
      "Uptime": {
        "type": "object",
        "properties": {
          "range": {
            "type": "string",
            "enum": [
              "24h",
              "7d",
              "30d",
              "90d"
            ],
            "description": "Zeitraum"
          },
          "source": {
            "type": "string",
            "enum": [
              "raw",
              "check_result_hourly",
              "check_result_daily"
            ],
            "description": "Auflösung: Einzelprüfungen (24h), Stunden (7d, 30d) oder Tage (90d)"
          },
          "summary": {
            "type": "object",
            "properties": {
              "uptime_ratio": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Verfügbarkeit 0 bis 1"
              },
              "checks_total": {
                "type": "integer",
                "description": "Prüfungen im Zeitraum"
              },
              "latency_p50": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Median der Antwortzeit in ms"
              },
              "latency_p95": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "95. Perzentil der Antwortzeit in ms"
              },
              "downtime_seconds": {
                "type": "integer",
                "description": "Ausfallzeit in Sekunden (nicht bei 24h)"
              }
            }
          },
          "points": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Messpunkte: bei 24h je Prüfung (t, status, latency_ms), sonst je Stunde oder Tag (t, uptime_ratio, latency_p50, latency_p95, checks_failed, downtime_seconds)"
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "object",
            "properties": {
              "key": {
                "type": "string",
                "description": "Tarifschlüssel"
              },
              "name": {
                "type": "string",
                "description": "Tarifname"
              },
              "domains": {
                "type": "integer",
                "description": "Domainlimit"
              },
              "hostnames_per_domain": {
                "type": "integer",
                "description": "Hostnamen je Domain"
              },
              "retention_days": {
                "type": "integer",
                "description": "Verlauf in Tagen"
              },
              "members": {
                "type": "integer",
                "description": "Mitglieder"
              },
              "channels": {
                "type": "integer",
                "description": "Kanäle"
              },
              "min_interval": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                },
                "description": "Kleinstes Prüfintervall je Check-Typ in Minuten"
              },
              "sms_per_month": {
                "type": "integer",
                "description": "SMS je Monat"
              }
            },
            "additionalProperties": true
          },
          "domains": {
            "type": "integer",
            "description": "Domains"
          },
          "monitors": {
            "type": "integer",
            "description": "Monitore"
          },
          "members": {
            "type": "integer",
            "description": "Mitglieder"
          },
          "channels": {
            "type": "integer",
            "description": "Kanäle"
          },
          "checks_24h": {
            "type": "integer",
            "description": "Prüfungen der letzten 24 Stunden"
          }
        }
      },
      "CustomerReport": {
        "type": "object",
        "description": "Monatsbericht; Zeitangaben sind für die Anzeige formatiert (Sprache des Berichts)",
        "properties": {
          "organization": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "description": "Agentur"
              }
            }
          },
          "customer": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "name": {
                "type": "string",
                "description": "Kunde"
              },
              "reference": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "period": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "format": "date"
              },
              "to": {
                "type": "string",
                "format": "date"
              },
              "label": {
                "type": "string",
                "description": "Monat als Text"
              },
              "month": {
                "type": "string",
                "description": "YYYY-MM"
              }
            }
          },
          "generated_at": {
            "type": "string",
            "description": "Erstellt am (formatiert)"
          },
          "locale": {
            "type": "string",
            "description": "Sprache des Berichts"
          },
          "summary": {
            "type": "object",
            "properties": {
              "domains": {
                "type": "integer"
              },
              "healthy": {
                "type": "integer"
              },
              "warning": {
                "type": "integer"
              },
              "critical": {
                "type": "integer"
              },
              "uptime": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Verfügbarkeit in Prozent"
              },
              "incidents": {
                "type": "integer"
              },
              "critical_incidents": {
                "type": "integer"
              },
              "changes": {
                "type": "integer"
              },
              "downtime_minutes": {
                "type": "integer"
              }
            }
          },
          "domains": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Domain"
                },
                "health": {
                  "type": "string",
                  "enum": [
                    "healthy",
                    "warning",
                    "critical",
                    "unknown"
                  ]
                },
                "uptime": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "downtime_minutes": {
                  "type": "integer"
                },
                "incidents": {
                  "type": "integer"
                },
                "critical_incidents": {
                  "type": "integer"
                },
                "certificate_valid_to": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "certificate_days_left": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "certificate_issuer": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "domain_expires_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date"
                },
                "registrar": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "additionalProperties": true
            }
          },
          "incidents": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "domain": {
                  "type": "string",
                  "description": "Domain"
                },
                "type": {
                  "type": "string",
                  "description": "Incident-Typ"
                },
                "label": {
                  "type": "string",
                  "description": "Bezeichnung"
                },
                "severity": {
                  "type": "string",
                  "enum": [
                    "info",
                    "warning",
                    "critical"
                  ]
                },
                "started_at": {
                  "type": "string",
                  "description": "Beginn (formatiert)"
                },
                "resolved_at": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "duration_minutes": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "open",
                    "acknowledged",
                    "resolved"
                  ]
                }
              }
            }
          },
          "changes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "domain": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "type": {
                  "type": "string",
                  "description": "Ereignistyp"
                },
                "label": {
                  "type": "string",
                  "description": "Bezeichnung"
                },
                "severity": {
                  "type": "string",
                  "enum": [
                    "info",
                    "warning",
                    "critical"
                  ]
                },
                "occurred_at": {
                  "type": "string",
                  "description": "Zeitpunkt (formatiert)"
                },
                "previous": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "new": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "expiring_certificates": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Zertifikate, die bald ablaufen"
          },
          "expiring_domains": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Domains, die bald ablaufen"
          }
        },
        "additionalProperties": true
      },
      "Dashboard": {
        "type": "object",
        "properties": {
          "domains": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "description": "Alle Domains"
              },
              "healthy": {
                "type": "integer",
                "description": "Gesund"
              },
              "warning": {
                "type": "integer",
                "description": "Warnung"
              },
              "critical": {
                "type": "integer",
                "description": "Kritisch"
              },
              "unknown": {
                "type": "integer",
                "description": "Noch nicht geprüft"
              }
            }
          },
          "needs_attention": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Incident"
            },
            "description": "Offene Incidents, kritische zuerst (höchstens 50)"
          },
          "recent_changes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Event"
            },
            "description": "Erkannte Änderungen der letzten 24 Stunden (höchstens 30)"
          },
          "usage": {
            "type": "object",
            "properties": {
              "domains": {
                "type": "integer",
                "description": "Genutzte Domains"
              },
              "domains_limit": {
                "type": "integer",
                "description": "Domainlimit des Tarifs"
              },
              "plan": {
                "type": "string",
                "description": "Tarifschlüssel"
              },
              "plan_name": {
                "type": "string",
                "description": "Tarifname"
              }
            }
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "string",
                  "format": "date"
                },
                "incidents": {
                  "type": "integer"
                },
                "changes": {
                  "type": "integer"
                },
                "checks_failed": {
                  "type": "integer"
                },
                "checks_total": {
                  "type": "integer"
                }
              }
            },
            "description": "Letzte 14 Tage je Tag"
          },
          "generated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Erstellt am (bis 30 Sekunden gecacht, ETag wird gesetzt)"
          }
        }
      },
      "PageMeta": {
        "type": "object",
        "description": "Seitenweise Paginierung",
        "properties": {
          "current_page": {
            "type": "integer"
          },
          "from": {
            "type": [
              "integer",
              "null"
            ]
          },
          "to": {
            "type": [
              "integer",
              "null"
            ]
          },
          "last_page": {
            "type": "integer"
          },
          "per_page": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "path": {
            "type": "string"
          }
        }
      },
      "CursorMeta": {
        "type": "object",
        "description": "Cursor-Paginierung: `next_cursor` als Parameter `cursor` der nächsten Anfrage mitgeben, null am Ende",
        "properties": {
          "path": {
            "type": "string"
          },
          "per_page": {
            "type": "integer"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "prev_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Links": {
        "type": "object",
        "properties": {
          "first": {
            "type": [
              "string",
              "null"
            ]
          },
          "last": {
            "type": [
              "string",
              "null"
            ]
          },
          "prev": {
            "type": [
              "string",
              "null"
            ]
          },
          "next": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ProblemDetails": {
        "type": "object",
        "description": "Fehler nach RFC 9457 (Content-Type application/problem+json)",
        "required": [
          "type",
          "title",
          "status"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Fehlerart, z. B. https://domainwarn.com/errors/not-found"
          },
          "title": {
            "type": "string",
            "description": "Kurzbezeichnung"
          },
          "status": {
            "type": "integer",
            "description": "HTTP-Status"
          },
          "detail": {
            "type": "string",
            "description": "Erklärung"
          }
        }
      },
      "PlanProblem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ProblemDetails"
          },
          {
            "type": "object",
            "properties": {
              "plan": {
                "type": "string",
                "description": "Wirksamer Tarif"
              },
              "suspended": {
                "type": "boolean",
                "description": "Vom Betreiber gesperrt"
              }
            }
          }
        ]
      },
      "ValidationProblem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ProblemDetails"
          },
          {
            "type": "object",
            "properties": {
              "errors": {
                "type": "object",
                "additionalProperties": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "description": "Meldungen je Feld"
              }
            }
          }
        ]
      }
    }
  }
}