{
    "openapi": "3.1.0",
    "info": {
        "title": "Kingscookies API – Mietspiegel-Daten für Deutschland",
        "version": "1.0.0",
        "summary": "Ortsübliche Vergleichsmiete, Mietspiegel-Regeln, Mietpreisbremse und Änderungen – stichtagsbezogen.",
        "description": "Alle Ergebnisse sind Berechnungen auf Grundlage veröffentlichter Mietspiegel und Landesverordnungen und als Einschätzung gekennzeichnet. Keine Rechtsberatung.",
        "contact": {
            "url": "https://kingscookies.de/docs"
        }
    },
    "servers": [
        {
            "url": "https://kingscookies.de/api/v1"
        }
    ],
    "security": [
        {
            "apiKey": []
        }
    ],
    "components": {
        "securitySchemes": {
            "apiKey": {
                "type": "http",
                "scheme": "bearer",
                "description": "API-Schlüssel als Bearer-Token: `Authorization: Bearer <schlüssel>`"
            }
        },
        "parameters": {
            "ags": {
                "name": "ags",
                "in": "query",
                "required": true,
                "description": "Amtlicher Gemeindeschlüssel (8 Ziffern)",
                "schema": {
                    "type": "string",
                    "pattern": "^\\d{8}$"
                },
                "example": "08222000"
            },
            "stichtag": {
                "name": "stichtag",
                "in": "query",
                "required": false,
                "description": "Datum, für das die Regeln gelten sollen (Standard: heute)",
                "schema": {
                    "type": "string",
                    "format": "date"
                },
                "example": "2026-10-07"
            }
        },
        "schemas": {
            "Fehler": {
                "type": "object",
                "required": [
                    "message"
                ],
                "properties": {
                    "message": {
                        "type": "string"
                    },
                    "errors": {
                        "type": "object"
                    }
                }
            },
            "Meta": {
                "type": "object",
                "properties": {
                    "api_version": {
                        "type": "string",
                        "example": "1"
                    },
                    "datenstand": {
                        "type": "string",
                        "description": "Version des zuletzt übertragenen Datenstands"
                    },
                    "stichtag": {
                        "type": "string",
                        "format": "date"
                    }
                }
            },
            "Spanne": {
                "type": "object",
                "properties": {
                    "von": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "example": "8.25"
                    },
                    "mittel": {
                        "type": "string",
                        "example": "9.70"
                    },
                    "bis": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "example": "11.35"
                    }
                }
            },
            "MietspiegelKopf": {
                "type": "object",
                "properties": {
                    "ausgabe": {
                        "type": "string",
                        "example": "2025/2026"
                    },
                    "typ": {
                        "type": "string",
                        "enum": [
                            "tabelle",
                            "regression"
                        ]
                    },
                    "qualifiziert": {
                        "type": "boolean"
                    },
                    "gueltig_ab": {
                        "type": "string",
                        "format": "date"
                    },
                    "gueltig_bis": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date"
                    },
                    "quelle": {
                        "type": "object",
                        "properties": {
                            "url": {
                                "type": "string",
                                "format": "uri"
                            },
                            "abgerufen_am": {
                                "type": "string",
                                "format": "date-time"
                            },
                            "sha256": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "responses": {
            "NichtAngemeldet": {
                "description": "API-Schlüssel fehlt oder ist ungültig",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Fehler"
                        }
                    }
                }
            },
            "ZuViele": {
                "description": "Minutenlimit oder Monatskontingent des Tarifs erreicht",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Fehler"
                        }
                    }
                }
            },
            "NichtGefunden": {
                "description": "Keine Daten für Gemeinde oder Stichtag",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Fehler"
                        }
                    }
                }
            },
            "Ungueltig": {
                "description": "Eingabe ungültig oder vom Mietspiegel nicht abgedeckt",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Fehler"
                        }
                    }
                }
            }
        }
    },
    "paths": {
        "/vergleichsmiete": {
            "get": {
                "summary": "Ortsübliche Vergleichsmiete für eine Wohnung",
                "description": "Merkmal-Schlüssel und Eingaben je Mietspiegel liefert `GET /mietspiegel/{ags}`. Unbekannte Angaben werden nicht geraten, sondern unter `unbekannt` aufgeführt. Auch per POST mit JSON-Body möglich.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ags"
                    },
                    {
                        "name": "flaeche",
                        "in": "query",
                        "required": true,
                        "description": "Wohnfläche in m²",
                        "schema": {
                            "type": "number"
                        },
                        "example": 70
                    },
                    {
                        "name": "baujahr",
                        "in": "query",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 1965
                    },
                    {
                        "name": "merkmale[]",
                        "in": "query",
                        "description": "Vorhandene Merkmale (Schlüssel aus dem Merkmalskatalog)",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    {
                        "name": "werte[name]",
                        "in": "query",
                        "description": "Weitere Eingaben, z. B. `werte[wohnlage]=4` oder `werte[bad_merkmale]=1`",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/stichtag"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Ergebnis (Einschätzung)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "einschaetzung": {
                                                    "type": "boolean",
                                                    "const": true
                                                },
                                                "gemeinde": {
                                                    "type": "object",
                                                    "properties": {
                                                        "ags": {
                                                            "type": "string"
                                                        },
                                                        "name": {
                                                            "type": "string"
                                                        }
                                                    }
                                                },
                                                "mietspiegel": {
                                                    "$ref": "#/components/schemas/MietspiegelKopf"
                                                },
                                                "vergleichsmiete_eur_qm": {
                                                    "$ref": "#/components/schemas/Spanne"
                                                },
                                                "vergleichsmiete_monat": {
                                                    "$ref": "#/components/schemas/Spanne"
                                                },
                                                "basis_eur_qm": {
                                                    "type": "string"
                                                },
                                                "zu_abschlaege": {
                                                    "type": "object"
                                                },
                                                "unbekannt": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    }
                                                },
                                                "hinweise": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/Meta"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/NichtAngemeldet"
                    },
                    "404": {
                        "$ref": "#/components/responses/NichtGefunden"
                    },
                    "422": {
                        "$ref": "#/components/responses/Ungueltig"
                    },
                    "429": {
                        "$ref": "#/components/responses/ZuViele"
                    }
                }
            }
        },
        "/mietpreisbremse": {
            "get": {
                "summary": "Gilt die Mietpreisbremse? (Einschätzung)",
                "description": "Prüft, ob eine erfasste Landesverordnung die Gemeinde am Stichtag umfasst. Optional mit Grenze (Vergleichsmiete + 10 %) und Abweichung einer gegebenen Miete. Die wichtigsten Ausnahmen werden immer mitgeliefert.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/ags"
                    },
                    {
                        "$ref": "#/components/parameters/stichtag"
                    },
                    {
                        "name": "vergleichsmiete_eur_qm",
                        "in": "query",
                        "schema": {
                            "type": "number"
                        }
                    },
                    {
                        "name": "miete_eur_qm",
                        "in": "query",
                        "schema": {
                            "type": "number"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Ergebnis mit `gilt`, `verordnung`, `ausnahmen`, `hinweise`, optional `grenze_eur_qm`, `abweichung_von_vergleichsmiete_prozent`"
                    },
                    "401": {
                        "$ref": "#/components/responses/NichtAngemeldet"
                    },
                    "404": {
                        "$ref": "#/components/responses/NichtGefunden"
                    },
                    "429": {
                        "$ref": "#/components/responses/ZuViele"
                    }
                }
            }
        },
        "/gemeinden": {
            "get": {
                "summary": "Erfasste Gemeinden",
                "responses": {
                    "200": {
                        "description": "Liste mit `ags`, `name`, `bundesland`"
                    },
                    "401": {
                        "$ref": "#/components/responses/NichtAngemeldet"
                    }
                }
            }
        },
        "/mietspiegel/{ags}": {
            "get": {
                "summary": "Mietspiegel einer Gemeinde zum Stichtag",
                "description": "Regeln, Merkmalskatalog (Schlüssel, Bezeichnung, Art, Wert, Bedingung) und Ausgaben-Historie. Vollständige Basistabellen ab Tarif Pro.",
                "parameters": [
                    {
                        "name": "ags",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "^\\d{8}$"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/stichtag"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Mietspiegel"
                    },
                    "401": {
                        "$ref": "#/components/responses/NichtAngemeldet"
                    },
                    "404": {
                        "$ref": "#/components/responses/NichtGefunden"
                    }
                }
            }
        },
        "/changes": {
            "get": {
                "summary": "Änderungen seit einem Datum",
                "description": "Freigaben neuer Mietspiegel und Verordnungs-Gebiete, älteste zuerst, Seiten zu 500 Einträgen. Nächste Seite über `nach_id` aus `meta.naechste_seite`.",
                "parameters": [
                    {
                        "name": "seit",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "nach_id",
                        "in": "query",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Liste `aenderungen`"
                    },
                    "401": {
                        "$ref": "#/components/responses/NichtAngemeldet"
                    }
                }
            }
        },
        "/qualitaet": {
            "get": {
                "summary": "Qualitätskennzahlen",
                "description": "Abdeckung, Tage bis zur Aufnahme neuer Mietspiegel, Quote nachgerechneter offizieller Beispiele, aggregierte API-Nutzung (nur Summen).",
                "responses": {
                    "200": {
                        "description": "Kennzahlen"
                    },
                    "401": {
                        "$ref": "#/components/responses/NichtAngemeldet"
                    }
                }
            }
        },
        "/feed": {
            "get": {
                "summary": "Verfügbare monatliche Daten-Feeds (Tarif Enterprise)",
                "responses": {
                    "200": {
                        "description": "Liste mit monat, bytes, url"
                    },
                    "401": {
                        "$ref": "#/components/responses/NichtAngemeldet"
                    },
                    "403": {
                        "description": "Feed nicht im Tarif enthalten"
                    }
                }
            }
        },
        "/feed/{monat}": {
            "get": {
                "summary": "Daten-Feed eines Monats als ZIP (JSON, JSON Lines, CSV, Changelog)",
                "parameters": [
                    {
                        "name": "monat",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "^\\d{4}-\\d{2}$"
                        },
                        "example": "2026-09"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "ZIP-Archiv",
                        "content": {
                            "application/zip": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Feed nicht im Tarif enthalten"
                    },
                    "404": {
                        "$ref": "#/components/responses/NichtGefunden"
                    }
                }
            }
        }
    }
}
