{
  "openapi": "3.1.0",
  "info": {
    "title": "ColorbySultan | Meisterfriseur in Wiehl Public & Agent API",
    "version": "1.0.0",
    "description": "Offizielle maschinenlesbare Schnittstellen und Agent-APIs für den ColorbySultan | Meisterfriseur in Wiehl.",
    "contact": {
      "name": "ColorbySultan | Meisterfriseur in Wiehl Support",
      "email": "info@colorbysultan.de",
      "url": "https://colorbysultan.de"
    }
  },
  "servers": [
    {
      "url": "https://colorbysultan.de",
      "description": "Production Server"
    }
  ],
  "paths": {
    "/": {
      "get": {
        "operationId": "getHomepage",
        "summary": "Homepage mit Markdown Content Negotiation",
        "description": "Gibt je nach Accept-Header HTML oder strukturierte Markdown-Daten für LLMs und Agenten zurück.",
        "responses": {
          "200": {
            "description": "Erfolgreiche Antwort (HTML oder Markdown)",
            "headers": {
              "Vary": {
                "description": "Content-Negotiation Cache-Steuerung",
                "schema": {
                  "type": "string",
                  "example": "Accept"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string",
                  "description": "HTML5 Quelltext der Homepage"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string",
                  "description": "Strukturierte Markdown-Repräsentation für AI-Modelle und Agenten"
                }
              }
            }
          }
        }
      }
    },
    "/api/salon/info": {
      "get": {
        "operationId": "getSalonInfo",
        "summary": "Salon Stammdaten & Kontakt",
        "description": "Gibt grundlegende Salondaten, Adresse, Geokoordinaten und Buchungslinks zurück.",
        "responses": {
          "200": {
            "description": "Vollständige Salon Metadaten und Kontaktinformationen",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalonInfoResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/salon/services": {
      "get": {
        "operationId": "getSalonServices",
        "summary": "Dienstleistungskatalog",
        "description": "Liefert alle buchbaren Friseurdienstleistungen inklusive Richtzeiten und Preisen.",
        "responses": {
          "200": {
            "description": "Liste der Dienstleistungen mit Dauer und Preisen",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalonServicesResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/salon/hours": {
      "get": {
        "operationId": "getSalonHours",
        "summary": "Öffnungszeiten",
        "description": "Gibt die regulären wöchentlichen Öffnungszeiten des Salons zurück.",
        "responses": {
          "200": {
            "description": "Öffnungszeiten nach Wochentag",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalonHoursResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "operationId": "getOpenApiSpec",
        "summary": "OpenAPI Spezifikation",
        "description": "Liefert die vollständige maschinenlesbare OpenAPI 3.1 Spezifikation im JSON-Format.",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 JSON Spezifikation",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "OpenAPI 3.1 Dokument"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequestsError"
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "LLM Kontext Dokumentation",
        "description": "Standardisiertes Kontext-Dokument für Large Language Models und autonome Agenten.",
        "responses": {
          "200": {
            "description": "Plaintext LLM guidance",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemapXml",
        "summary": "XML Sitemap",
        "description": "Standard XML Sitemap mit allen indexierbaren URLs und Aktualisierungsdaten.",
        "responses": {
          "200": {
            "description": "Standard XML Sitemap",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error",
          "message",
          "status"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Maschinenlesbarer Fehlercode",
            "example": "rate_limit_exceeded"
          },
          "message": {
            "type": "string",
            "description": "Verständliche Fehlerbeschreibung für Mensch und Modell",
            "example": "Zu viele Anfragen. Bitte drosseln Sie die Anfragerate gemäß den Rate-Limit-Headern."
          },
          "status": {
            "type": "integer",
            "description": "HTTP-Statuscode",
            "example": 429
          },
          "details": {
            "type": "object",
            "description": "Optionale strukturierte Zusatzangaben zum Fehler",
            "nullable": true,
            "additionalProperties": true
          }
        }
      },
      "SalonInfoAddress": {
        "type": "object",
        "required": [
          "street",
          "postal_code",
          "city",
          "state",
          "country"
        ],
        "properties": {
          "street": {
            "type": "string",
            "example": "Bahnhofstraße 18"
          },
          "postal_code": {
            "type": "string",
            "example": "51674"
          },
          "city": {
            "type": "string",
            "example": "Wiehl"
          },
          "state": {
            "type": "string",
            "example": "Nordrhein-Westfalen"
          },
          "country": {
            "type": "string",
            "example": "DE"
          }
        }
      },
      "SalonInfoCoordinates": {
        "type": "object",
        "required": [
          "latitude",
          "longitude"
        ],
        "properties": {
          "latitude": {
            "type": "number",
            "format": "float",
            "example": 50.9515
          },
          "longitude": {
            "type": "number",
            "format": "float",
            "example": 7.5487
          }
        }
      },
      "SalonInfoContact": {
        "type": "object",
        "required": [
          "phone",
          "email",
          "instagram"
        ],
        "properties": {
          "phone": {
            "type": "string",
            "example": "+49 160 4947060"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "info@colorbysultan.de"
          },
          "instagram": {
            "type": "string",
            "format": "uri",
            "example": "https://instagram.com/colorbysultan"
          }
        }
      },
      "SalonInfoResponse": {
        "type": "object",
        "required": [
          "name",
          "alternate_names",
          "tagline",
          "description",
          "address",
          "coordinates",
          "contact",
          "booking_url",
          "contact_url",
          "website",
          "llms_txt",
          "openapi_spec"
        ],
        "properties": {
          "name": {
            "type": "string",
            "example": "ColorbySultan | Meisterfriseur in Wiehl"
          },
          "alternate_names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "ColorbySultan",
              "Meisterfriseur in Wiehl",
              "Friseur Wiehl"
            ]
          },
          "tagline": {
            "type": "string",
            "example": "Ihr exklusiver Friseursalon & Friseur in Wiehl"
          },
          "description": {
            "type": "string",
            "example": "ColorbySultan | Meisterfriseur in Wiehl ist spezialisiert auf Balayage, erstklassige Haarschnitte, Olaplex-Pflege und brillante Farben."
          },
          "address": {
            "$ref": "#/components/schemas/SalonInfoAddress"
          },
          "coordinates": {
            "$ref": "#/components/schemas/SalonInfoCoordinates"
          },
          "contact": {
            "$ref": "#/components/schemas/SalonInfoContact"
          },
          "booking_url": {
            "type": "string",
            "format": "uri",
            "example": "https://colorbysultan.de/login"
          },
          "contact_url": {
            "type": "string",
            "format": "uri",
            "example": "https://colorbysultan.de/contact"
          },
          "website": {
            "type": "string",
            "format": "uri",
            "example": "https://colorbysultan.de"
          },
          "llms_txt": {
            "type": "string",
            "format": "uri",
            "example": "https://colorbysultan.de/llms.txt"
          },
          "openapi_spec": {
            "type": "string",
            "format": "uri",
            "example": "https://colorbysultan.de/api/openapi.json"
          }
        }
      },
      "ServiceItem": {
        "type": "object",
        "required": [
          "id",
          "name",
          "duration",
          "price"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "name": {
            "type": "string",
            "example": "Balayage Premium"
          },
          "category": {
            "type": [
              "string",
              "null"
            ],
            "example": "Färben"
          },
          "duration": {
            "type": "integer",
            "description": "Dauer der Dienstleistung in Minuten",
            "example": 180
          },
          "price": {
            "type": "number",
            "format": "float",
            "description": "Grundpreis in EUR",
            "example": 120.00
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "example": "Individuelle Freihand-Farbtechnik mit Veredelung."
          }
        }
      },
      "SalonServicesResponse": {
        "type": "object",
        "required": [
          "salon",
          "currency",
          "services"
        ],
        "properties": {
          "salon": {
            "type": "string",
            "example": "ColorbySultan | Meisterfriseur in Wiehl"
          },
          "currency": {
            "type": "string",
            "example": "EUR"
          },
          "services": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceItem"
            }
          }
        }
      },
      "OpeningHourItem": {
        "type": "object",
        "required": [
          "day_of_week",
          "start_time",
          "end_time",
          "is_closed"
        ],
        "properties": {
          "day_of_week": {
            "type": "string",
            "enum": [
              "Monday",
              "Tuesday",
              "Wednesday",
              "Thursday",
              "Friday",
              "Saturday",
              "Sunday"
            ],
            "example": "Monday"
          },
          "start_time": {
            "type": [
              "string",
              "null"
            ],
            "example": "09:00:00"
          },
          "end_time": {
            "type": [
              "string",
              "null"
            ],
            "example": "18:00:00"
          },
          "is_closed": {
            "type": "boolean",
            "example": false
          }
        }
      },
      "SalonHoursResponse": {
        "type": "object",
        "required": [
          "salon",
          "timezone",
          "hours"
        ],
        "properties": {
          "salon": {
            "type": "string",
            "example": "ColorbySultan | Meisterfriseur in Wiehl"
          },
          "timezone": {
            "type": "string",
            "example": "Europe/Berlin"
          },
          "hours": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpeningHourItem"
            }
          }
        }
      }
    },
    "headers": {
      "RateLimit-Limit": {
        "description": "Maximale Anzahl an erlaubten Anfragen im aktuellen Zeitfenster (Standard: 60/min).",
        "schema": {
          "type": "integer",
          "example": 60
        }
      },
      "RateLimit-Remaining": {
        "description": "Verbleibende Anfragen im aktuellen Zeitfenster.",
        "schema": {
          "type": "integer",
          "example": 59
        }
      },
      "RateLimit-Reset": {
        "description": "Verbleibende Sekunden bis zum Zurücksetzen des Limits.",
        "schema": {
          "type": "integer",
          "example": 60
        }
      },
      "X-RateLimit-Limit": {
        "description": "Maximale Anzahl an Anfragen (Legacy-Header).",
        "schema": {
          "type": "integer",
          "example": 60
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Verbleibende Anfragen (Legacy-Header).",
        "schema": {
          "type": "integer",
          "example": 59
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix-Zeitstempel bis zum Zurücksetzen des Limits.",
        "schema": {
          "type": "integer",
          "example": 1773400000
        }
      },
      "Retry-After": {
        "description": "Sekunden, die der Bot warten muss, bevor eine neue Anfrage gesendet werden darf.",
        "schema": {
          "type": "integer",
          "example": 60
        }
      }
    },
    "responses": {
      "TooManyRequestsError": {
        "description": "Rate Limit überschritten. Bots und Agenten müssen pausieren.",
        "headers": {
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFoundError": {
        "description": "Ressource wurde nicht gefunden.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Interner Serverfehler.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  }
}
