{
  "openapi": "3.0.3",
  "info": {
    "title": "Hugo Gebäudereinigung Anfrage-API",
    "description": "Öffentliche API zur Prüfung des vorgeprüften Einsatzgebiets und zur Übermittlung einer unverbindlichen Reinigungsanfrage. Preise, Termine, Verfügbarkeit und Auftragsannahme werden nicht automatisch bestätigt.",
    "version": "1.0.0",
    "contact": {
      "name": "Hugo Gebäudereinigung",
      "url": "https://hugo-gebaeudereinigung.de/kontakt/",
      "email": "info@hugo-gebaeudereinigung.de"
    }
  },
  "servers": [
    {
      "url": "https://hugo-gebaeudereinigung.de",
      "description": "Produktive Website"
    }
  ],
  "paths": {
    "/api/inquiry": {
      "post": {
        "operationId": "sendCleaningInquiry",
        "summary": "Unverbindliche Reinigungsanfrage senden",
        "description": "Übermittelt eine validierte Anfrage per E-Mail an Hugo Gebäudereinigung. Die anfragende Person muss der Verarbeitung ihrer Angaben ausdrücklich zugestimmt haben. Eine erfolgreiche Annahme bestätigt weder Preis noch Termin noch Auftrag.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InquiryRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Anfrage wurde an das Mailsystem übergeben.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InquiryAccepted"
                }
              }
            }
          },
          "400": {
            "description": "JSON oder Pflichtangaben sind ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Request-Body ist größer als 32 KiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate-Limit wurde erreicht.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Anfrage konnte nicht an das Mailsystem übergeben werden.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/service-area": {
      "get": {
        "operationId": "checkCleaningServiceArea",
        "summary": "Einsatzmöglichkeit anhand der PLZ vorprüfen",
        "description": "Prüft eine fünfstellige deutsche PLZ gegen die 20 hinterlegten Hauptorte. Eine nicht hinterlegte PLZ wird zur manuellen Adressprüfung markiert und nicht pauschal ausgeschlossen.",
        "parameters": [
          {
            "name": "postalCode",
            "in": "query",
            "required": true,
            "description": "Fünfstellige deutsche Postleitzahl des Reinigungsobjekts.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{5}$",
              "example": "90443"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ergebnis der PLZ-Vorprüfung.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceAreaResult"
                }
              }
            }
          },
          "400": {
            "description": "PLZ fehlt oder ist ungültig.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "InquiryRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "service",
          "objectType",
          "areaSquareMeters",
          "frequency",
          "postalCode",
          "city",
          "streetAddress",
          "fullName",
          "email",
          "privacyConsent"
        ],
        "properties": {
          "service": {
            "type": "string",
            "description": "Technischer Slug der gewünschten Reinigungsleistung.",
            "enum": [
              "gebaeudereinigung",
              "unterhaltsreinigung",
              "bueroreinigung",
              "praxisreinigung",
              "treppenhausreinigung",
              "glasreinigung",
              "grundreinigung",
              "bauendreinigung",
              "bauzwischenreinigung",
              "fassadenreinigung",
              "hochdruckreinigung",
              "terrassenreinigung",
              "garagenreinigung",
              "parkplatzreinigung",
              "aussenflaechenreinigung",
              "dachrinnenreinigung",
              "ladenreinigung",
              "gastronomiereinigung",
              "sanitaerreinigung",
              "gemeinschaftsflaechenreinigung",
              "fensterreinigung"
            ],
            "example": "bueroreinigung"
          },
          "objectType": {
            "type": "string",
            "description": "Art des zu reinigenden Objekts.",
            "enum": [
              "buero",
              "praxis",
              "mehrfamilienhaus",
              "laden",
              "gastronomie",
              "gewerbeobjekt",
              "privatobjekt",
              "anderes"
            ],
            "example": "buero"
          },
          "areaSquareMeters": {
            "type": "number",
            "format": "float",
            "minimum": 1,
            "maximum": 1000000,
            "description": "Ungefähre zu reinigende Fläche in Quadratmetern.",
            "example": 240
          },
          "frequency": {
            "type": "string",
            "description": "Gewünschter Turnus.",
            "enum": [
              "einmalig",
              "woechentlich",
              "mehrmals-pro-woche",
              "taeglich",
              "nach-absprache"
            ],
            "example": "woechentlich"
          },
          "postalCode": {
            "type": "string",
            "pattern": "^[0-9]{5}$",
            "description": "Postleitzahl des Reinigungsobjekts.",
            "example": "90443"
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "Ort des Reinigungsobjekts.",
            "example": "Nürnberg"
          },
          "streetAddress": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160,
            "description": "Straße und Hausnummer des Reinigungsobjekts.",
            "example": "Okenstr. 15"
          },
          "fullName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "Name der anfragenden Person oder des Unternehmens."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254,
            "description": "E-Mail-Adresse für die Rückmeldung."
          },
          "phone": {
            "type": "string",
            "maxLength": 80,
            "description": "Freiwillige Telefonnummer für Rückfragen."
          },
          "message": {
            "type": "string",
            "maxLength": 6000,
            "description": "Freiwillige ergänzende Angaben zu Flächen, Zugang, Verschmutzung oder Zeitfenstern."
          },
          "privacyConsent": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Muss true sein. Bestätigt die Kenntnisnahme der Datenschutzerklärung und die Verarbeitung der Angaben zur Bearbeitung der Anfrage."
          }
        }
      },
      "InquiryAccepted": {
        "type": "object",
        "required": [
          "accepted",
          "inquiryId",
          "service",
          "postalCode",
          "manualReview",
          "message"
        ],
        "properties": {
          "accepted": {
            "type": "boolean",
            "example": true
          },
          "inquiryId": {
            "type": "string",
            "format": "uuid"
          },
          "service": {
            "type": "string",
            "example": "Büroreinigung"
          },
          "postalCode": {
            "type": "string",
            "example": "90443"
          },
          "manualReview": {
            "type": "boolean",
            "example": false
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ServiceAreaResult": {
        "type": "object",
        "required": [
          "postalCode",
          "served",
          "manualReview",
          "area",
          "areaSlug",
          "serviceCount",
          "message"
        ],
        "properties": {
          "postalCode": {
            "type": "string",
            "example": "90443"
          },
          "served": {
            "type": "boolean",
            "example": true
          },
          "manualReview": {
            "type": "boolean",
            "example": false
          },
          "area": {
            "type": "string",
            "nullable": true,
            "example": "Nürnberg"
          },
          "areaSlug": {
            "type": "string",
            "nullable": true,
            "example": "nuernberg"
          },
          "serviceCount": {
            "type": "integer",
            "enum": [
              21
            ],
            "example": 21
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
