{
  "openapi": "3.1.0",
  "info": {
    "title": "BRDMap API",
    "version": "2026.05.25",
    "summary": "Öffentliche Endpoints der Lagekarte BRDMap.de.",
    "description": "Live-Karte für Deutschland: Polizei-/Feuerwehr-Meldungen und BBK/NINA-Warnungen aus amtlichen Quellen. Kein API-Key, keine Authentifizierung. Bitte clientseitig 5–30 Min cachen und einen User-Agent mit Kontakt setzen. Vollständige Doku: https://brdmap.de/api.html",
    "contact": {
      "name": "BRDMap",
      "url": "https://brdmap.de/impressum.html"
    },
    "license": {
      "name": "Amtliche Werke gemeinfrei (§ 5 UrhG); Aufbereitung CC BY 4.0",
      "url": "https://brdmap.de/ueber.html"
    }
  },
  "servers": [
    {
      "url": "https://brdmap.de",
      "description": "Produktion"
    }
  ],
  "paths": {
    "/events": {
      "get": {
        "summary": "Aktive Events abrufen",
        "description": "Liefert published Events, neueste zuerst. Dieselben Daten wie der statische Snapshot /events.json, aber live und filterbar.",
        "parameters": [
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 720,
              "default": 48
            },
            "description": "Zeitfenster rückwärts in Stunden (max. 720 = 30 Tage)."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 300
            },
            "description": "Maximale Anzahl Events."
          },
          {
            "name": "severity_min",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5
            },
            "description": "Nur Events mit Severity ≥ diesem Wert."
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Kategorie-Filter, kommagetrennt (z. B. BRAND_FEUER,KRIMINALITAET)."
          }
        ],
        "responses": {
          "200": {
            "description": "Liste von Events.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/health/pipeline": {
      "get": {
        "summary": "Pipeline-Live-Status",
        "description": "Liveness der Ingest-Pipeline. Vom Frontend für den Status-Indikator (LIVE/RUHIG/GESTÖRT) und das Live-Update-Banner genutzt.",
        "responses": {
          "200": {
            "description": "Status-Objekt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Event": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "https://brdmap.de/event.schema.json",
        "title": "BRDMap Event",
        "description": "Ein einzelnes Vorfall-/Warnungs-Objekt wie in events.json und der /events-API. Quellen sind amtlich (Polizei/Feuerwehr-Pressemitteilungen, BBK/NINA-Warnungen).",
        "type": "object",
        "required": [
          "id",
          "category",
          "severity",
          "title_de",
          "occurred_at",
          "geo_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Eindeutige Event-ID."
          },
          "category": {
            "type": "string",
            "enum": [
              "BRAND_FEUER",
              "UNFALL_VERKEHR",
              "KRIMINALITAET",
              "POLIZEIEINSATZ",
              "WETTER_NATUR",
              "KATASTROPHE",
              "DEMO_STREIK",
              "POLITIK",
              "GROSSEVENT"
            ],
            "description": "Kategorie (LLM-klassifiziert)."
          },
          "category_label": {
            "type": "string",
            "description": "Menschenlesbares Kategorie-Label (DE)."
          },
          "severity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5,
            "description": "Schweregrad 1 (alltäglich) bis 5 (Großschadenslage). Redaktionelle LLM-Klassifikation."
          },
          "title_de": {
            "type": "string",
            "description": "Titel der Meldung."
          },
          "summary_de": {
            "type": [
              "string",
              "null"
            ],
            "description": "Kurzzusammenfassung."
          },
          "lat": {
            "type": [
              "number",
              "null"
            ],
            "description": "Breitengrad (WGS84). null wenn nicht geocodet."
          },
          "lon": {
            "type": [
              "number",
              "null"
            ],
            "description": "Längengrad (WGS84). null wenn nicht geocodet."
          },
          "geo_city": {
            "type": [
              "string",
              "null"
            ],
            "description": "Stadt/Gemeinde, falls aufgelöst."
          },
          "geo_state": {
            "type": "string",
            "enum": [
              "BW",
              "BY",
              "BE",
              "BB",
              "HB",
              "HH",
              "HE",
              "MV",
              "NI",
              "NW",
              "RP",
              "SL",
              "SN",
              "ST",
              "SH",
              "TH"
            ],
            "description": "Bundesland (ISO-3166-2:DE ohne DE-Präfix)."
          },
          "geo_confidence": {
            "type": [
              "number",
              "string",
              "null"
            ],
            "description": "Geocoding-Konfidenz/Importance."
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "Zeitstempel des Vorfalls (ISO 8601, UTC)."
          },
          "ingested_at": {
            "type": "string",
            "format": "date-time",
            "description": "Zeitpunkt der Erfassung bei BRDMap (ISO 8601, UTC)."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Ablauf (v. a. NINA-Warnungen). null = kein Ablauf."
          },
          "cancelled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Zeitpunkt der Aufhebung, falls aufgehoben."
          },
          "sub_tags": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Zusatz-Tags."
          },
          "source_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Quellen-Code (z. B. presseportal_pol_mittelhessen_pst)."
          },
          "source_display": {
            "type": [
              "string",
              "null"
            ],
            "description": "Quellen-Anzeigename."
          },
          "external_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Link zur Original-Pressemeldung."
          },
          "news_slug": {
            "type": [
              "string",
              "null"
            ],
            "description": "Slug der News-Detailseite (/news/{slug}.html)."
          }
        },
        "additionalProperties": true
      },
      "Health": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "quiet",
              "error"
            ],
            "description": "ok = aktiv, quiet = keine neuen Events seit ≥45 Min, error = Pipeline-Stall."
          },
          "latest_event_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID des jüngsten Events."
          }
        }
      }
    }
  },
  "externalDocs": {
    "description": "Menschenlesbare API-Doku",
    "url": "https://brdmap.de/api.html"
  }
}