{
  "openapi": "3.1.0",
  "info": {
    "title": "Ladehase API",
    "version": "1.0.0",
    "description": "Öffentliche API von Ladehase: Ladestationen verbinden, Tarife festlegen, Ladungen starten und stoppen, abrechnen, auswerten. Alles, was im Dashboard geht, geht auch hier. Beträge in Rappen, Energie in Wattstunden, Energiepreise in Hundertstel-Rappen pro kWh.",
    "contact": {
      "name": "Ladehase",
      "email": "developer@ladehase.com",
      "url": "https://www.ladehase.com/de/docs"
    }
  },
  "servers": [
    {
      "url": "https://api.ladehase.com",
      "description": "Produktion"
    }
  ],
  "tags": [
    {
      "name": "Organisation"
    },
    {
      "name": "Verbindungen"
    },
    {
      "name": "Standorte"
    },
    {
      "name": "Geräte"
    },
    {
      "name": "Tarife"
    },
    {
      "name": "QR-Codes"
    },
    {
      "name": "Schilder"
    },
    {
      "name": "Sitzungen"
    },
    {
      "name": "Zahlungen"
    },
    {
      "name": "Terminals"
    },
    {
      "name": "Zugänge"
    },
    {
      "name": "Berichte"
    },
    {
      "name": "Team"
    },
    {
      "name": "Webhooks"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API-Schlüssel aus dem Dashboard (Entwickler): lh_test_… für Testdaten, lh_live_… für Livedaten."
      }
    },
    "schemas": {
      "Organization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «org_»",
            "example": "org_9c1f0b7a2e3d4c5b"
          },
          "object": {
            "type": "string",
            "enum": [
              "organization"
            ]
          },
          "name": {
            "type": "string",
            "example": "Hof Meier"
          },
          "slug": {
            "type": "string",
            "description": "Subdomain der Instanz",
            "example": "hof-meier"
          },
          "instance_url": {
            "type": "string",
            "example": "https://hof-meier.ladehase.com"
          },
          "test_mode": {
            "type": "boolean",
            "description": "Testmodus mit simulierten Ladepunkten und Testzahlungen"
          },
          "vat_registered": {
            "type": "boolean"
          },
          "vat_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "vat_rate_bps": {
            "type": "integer",
            "description": "MWST-Satz in Basispunkten (810 = 8.1 %)"
          },
          "accent_color": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "slug",
          "instance_url",
          "test_mode",
          "vat_registered",
          "vat_number",
          "vat_rate_bps",
          "accent_color"
        ],
        "additionalProperties": {}
      },
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "code"
        ]
      },
      "IntegrationList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Integration"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "Integration": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «int_»",
            "example": "int_4a7c2b9d0e1f3a5c"
          },
          "object": {
            "type": "string",
            "enum": [
              "integration"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "easee",
              "zaptec",
              "ocpp",
              "goe",
              "shelly",
              "mock",
              "zahls",
              "freika"
            ],
            "description": "Hersteller oder Zahlungspartner. «mock» = Testmodus."
          },
          "livemode": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "needs_attention",
              "disconnected"
            ]
          },
          "public_info": {
            "type": "object",
            "additionalProperties": {},
            "description": "Öffentliche Angaben ohne Geheimnisse"
          },
          "webhook_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Bei zahls.ch einzutragende Webhook-URL"
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_checked_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zeitpunkt (ISO 8601, UTC)",
            "example": "2026-10-25T08:30:00.000Z"
          },
          "last_synced_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zeitpunkt (ISO 8601, UTC)",
            "example": "2026-10-25T08:30:00.000Z"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "kind",
          "livemode",
          "name",
          "status",
          "public_info",
          "webhook_url",
          "last_error",
          "last_checked_at",
          "last_synced_at",
          "created_at"
        ]
      },
      "Object": {
        "type": "object",
        "additionalProperties": {}
      },
      "LocationList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Location"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "Location": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «loc_»",
            "example": "loc_2b8e1c0d9f7a6b5c"
          },
          "object": {
            "type": "string",
            "enum": [
              "location"
            ]
          },
          "name": {
            "type": "string",
            "example": "Hofladen"
          },
          "street": {
            "type": [
              "string",
              "null"
            ]
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": "string"
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "time_zone": {
            "type": "string"
          },
          "opening_hours": {
            "type": [
              "string",
              "null"
            ]
          },
          "payment_integration_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zahlungskonto für QR-Zahlungen an diesem Standort"
          },
          "is_public": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "street",
          "postal_code",
          "city",
          "country",
          "latitude",
          "longitude",
          "time_zone",
          "opening_hours",
          "payment_integration_id",
          "is_public",
          "created_at"
        ]
      },
      "Deleted": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "deleted": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "id",
          "object",
          "deleted"
        ]
      },
      "DeviceList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Device"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "Device": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «dev_»",
            "example": "dev_7d3a9c1b0e2f4a6b"
          },
          "object": {
            "type": "string",
            "enum": [
              "device"
            ]
          },
          "kind": {
            "type": "string",
            "description": "Geräteart, vorerst «ev_charger»"
          },
          "livemode": {
            "type": "boolean"
          },
          "name": {
            "type": "string",
            "example": "Ladepunkt Scheune"
          },
          "location_id": {
            "type": "string"
          },
          "integration_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "manufacturer": {
            "type": [
              "string",
              "null"
            ]
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "serial_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "max_power_w": {
            "type": [
              "integer",
              "null"
            ]
          },
          "tariff_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "billing": {
            "type": "object",
            "additionalProperties": {},
            "description": "Abrechnungsmodell, Reservationsgrenzen, Pakete"
          },
          "enabled": {
            "type": "boolean",
            "description": "Von Ladehase verwaltet und für Fahrende freigegeben"
          },
          "locked": {
            "type": "boolean",
            "description": "Vorübergehend gesperrt (keine neuen Ladungen)"
          },
          "prepared": {
            "type": "boolean",
            "description": "«Autorisierung erforderlich» beim Hersteller gesetzt"
          },
          "status": {
            "type": "string",
            "description": "Zusammengefasster Status für Anzeigen"
          },
          "state": {
            "$ref": "#/components/schemas/DeviceState"
          },
          "active_session_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "connectors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "code": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "id",
                "code",
                "url"
              ]
            }
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "kind",
          "livemode",
          "name",
          "location_id",
          "integration_id",
          "manufacturer",
          "model",
          "serial_number",
          "max_power_w",
          "tariff_id",
          "billing",
          "enabled",
          "locked",
          "prepared",
          "status",
          "state",
          "active_session_id",
          "connectors",
          "created_at"
        ]
      },
      "DeviceState": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "online": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "description": "offline, available, vehicle_connected, awaiting_authorization, charging, suspended, finished, error"
          },
          "cable_plugged": {
            "type": "boolean"
          },
          "power_w": {
            "type": "integer",
            "description": "Aktuelle Leistung in Watt"
          },
          "meter_wh": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Zählerstand in Wh"
          },
          "authorization_required": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "last_seen_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zeitpunkt (ISO 8601, UTC)",
            "example": "2026-10-25T08:30:00.000Z"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": {}
      },
      "Session": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «ses_»",
            "example": "ses_1a2b3c4d5e6f7a8b9c0d"
          },
          "object": {
            "type": "string",
            "enum": [
              "session"
            ]
          },
          "livemode": {
            "type": "boolean"
          },
          "state": {
            "type": "string",
            "description": "Zustand gemäss Zustandsautomat (created … settled)"
          },
          "mode": {
            "type": "string",
            "enum": [
              "reservation",
              "prepaid",
              "access"
            ]
          },
          "channel": {
            "type": "string",
            "enum": [
              "qr",
              "terminal",
              "api",
              "rfid",
              "access_link"
            ]
          },
          "location_id": {
            "type": "string"
          },
          "device_id": {
            "type": "string"
          },
          "connector_id": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "authorized_amount": {
            "type": "integer",
            "description": "Reservierter beziehungsweise bezahlter Betrag in Rappen",
            "example": 1235
          },
          "amount": {
            "type": "integer",
            "description": "Hochgerechneter Betrag (laufend) oder Endbetrag in Rappen",
            "example": 1235
          },
          "captured_amount": {
            "type": "integer",
            "description": "Belasteter Betrag in Rappen",
            "example": 1235
          },
          "refunded_amount": {
            "type": "integer",
            "description": "Zurückerstatteter Betrag in Rappen",
            "example": 1235
          },
          "vat_amount": {
            "type": "integer",
            "description": "MWST-Anteil in Rappen",
            "example": 1235
          },
          "energy_wh": {
            "type": "integer",
            "description": "Geladene Energie in Wh"
          },
          "idle_minutes": {
            "type": "integer"
          },
          "stop_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "receipt_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zeitpunkt (ISO 8601, UTC)",
            "example": "2026-10-25T08:30:00.000Z"
          },
          "ended_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zeitpunkt (ISO 8601, UTC)",
            "example": "2026-10-25T08:30:00.000Z"
          },
          "settled_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zeitpunkt (ISO 8601, UTC)",
            "example": "2026-10-25T08:30:00.000Z"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "livemode",
          "state",
          "mode",
          "channel",
          "location_id",
          "device_id",
          "connector_id",
          "currency",
          "authorized_amount",
          "amount",
          "captured_amount",
          "refunded_amount",
          "vat_amount",
          "energy_wh",
          "idle_minutes",
          "stop_reason",
          "receipt_number",
          "started_at",
          "ended_at",
          "settled_at",
          "created_at"
        ],
        "additionalProperties": {}
      },
      "TariffList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tariff"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "Tariff": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «trf_»",
            "example": "trf_5e2a8b1c9d0f3e7a"
          },
          "object": {
            "type": "string",
            "enum": [
              "tariff"
            ]
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "version": {
            "type": "integer"
          },
          "version_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "rules": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Tarifregeln, siehe TariffRules"
          },
          "archived": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "description",
          "version",
          "version_id",
          "rules",
          "archived",
          "created_at",
          "updated_at"
        ]
      },
      "CodeList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Code"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "Code": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «qr_»",
            "example": "qr_3c9a1e7b0d2f4a6c"
          },
          "object": {
            "type": "string",
            "enum": [
              "code"
            ]
          },
          "code": {
            "type": "string",
            "description": "Kurzcode auf dem Schild",
            "example": "k7m2p9x"
          },
          "target": {
            "type": "string",
            "enum": [
              "connector",
              "location"
            ]
          },
          "connector_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": "string",
            "example": "https://hof-meier.ladehase.com/k7m2p9x"
          },
          "display_url": {
            "type": "string"
          },
          "scans": {
            "type": "integer"
          },
          "disabled": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "code",
          "target",
          "connector_id",
          "location_id",
          "label",
          "url",
          "display_url",
          "scans",
          "disabled",
          "created_at"
        ]
      },
      "SessionList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Session"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "PaymentList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Payment"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "Payment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «pay_»",
            "example": "pay_8f1e2d3c4b5a6978"
          },
          "object": {
            "type": "string",
            "enum": [
              "payment"
            ]
          },
          "livemode": {
            "type": "boolean"
          },
          "session_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "zahls",
              "freika",
              "mock"
            ]
          },
          "purpose": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "amount": {
            "type": "integer",
            "description": "Betrag in Rappen",
            "example": 1235
          },
          "captured_amount": {
            "type": "integer",
            "description": "Belastet in Rappen",
            "example": 1235
          },
          "refunded_amount": {
            "type": "integer",
            "description": "Zurückerstattet in Rappen",
            "example": 1235
          },
          "payment_method": {
            "type": [
              "string",
              "null"
            ]
          },
          "card_masked": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "livemode",
          "session_id",
          "provider",
          "purpose",
          "status",
          "currency",
          "amount",
          "captured_amount",
          "refunded_amount",
          "payment_method",
          "card_masked",
          "created_at"
        ],
        "additionalProperties": {}
      },
      "TerminalList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Terminal"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "Terminal": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «trm_»",
            "example": "trm_6b0c2d8e1f3a5b7c"
          },
          "object": {
            "type": "string",
            "enum": [
              "terminal"
            ]
          },
          "name": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "location_id": {
            "type": "string"
          },
          "integration_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "external_terminal_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Terminal-ID bei Freika"
          },
          "paired": {
            "type": "boolean"
          },
          "online": {
            "type": "boolean"
          },
          "app_version": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_seen_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zeitpunkt (ISO 8601, UTC)",
            "example": "2026-10-25T08:30:00.000Z"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "model",
          "location_id",
          "integration_id",
          "external_terminal_id",
          "paired",
          "online",
          "app_version",
          "last_seen_at",
          "created_at"
        ],
        "additionalProperties": {}
      },
      "AccessGrantList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccessGrant"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "AccessGrant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «acc_»",
            "example": "acc_0e9d8c7b6a5f4e3d"
          },
          "object": {
            "type": "string",
            "enum": [
              "access_grant"
            ]
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "rfid_uid": {
            "type": [
              "string",
              "null"
            ]
          },
          "link_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Persönlicher Link zum Laden ohne Zahlung"
          },
          "free": {
            "type": "boolean"
          },
          "tariff_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "monthly_limit_wh": {
            "type": [
              "integer",
              "null"
            ]
          },
          "revoked": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "email",
          "rfid_uid",
          "link_url",
          "free",
          "tariff_id",
          "monthly_limit_wh",
          "revoked",
          "created_at"
        ],
        "additionalProperties": {}
      },
      "WebhookEndpointList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpoint"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «whk_»",
            "example": "whk_2f4a6c8e0b1d3f5a"
          },
          "object": {
            "type": "string",
            "enum": [
              "webhook_endpoint"
            ]
          },
          "livemode": {
            "type": "boolean"
          },
          "url": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabled": {
            "type": "boolean"
          },
          "secret": {
            "type": "string",
            "description": "Nur beim Anlegen oder Rotieren sichtbar"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "livemode",
          "url",
          "description",
          "events",
          "enabled",
          "created_at"
        ],
        "additionalProperties": {}
      },
      "EventList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Event"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "additionalProperties": {}
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID mit Präfix «evt_»",
            "example": "evt_1b3d5f7a9c0e2f4b"
          },
          "object": {
            "type": "string",
            "enum": [
              "event"
            ]
          },
          "type": {
            "type": "string"
          },
          "livemode": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "additionalProperties": {}
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "type",
          "livemode",
          "data",
          "created_at"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/v1/organization": {
      "get": {
        "operationId": "getOrganization",
        "tags": [
          "Organisation"
        ],
        "summary": "Organisation abrufen",
        "description": "Einstellungen der Organisation dieses API-Schlüssels: Name, Subdomain der Instanz, MWST, Branding, Testmodus.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Organisation abrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateOrganization",
        "tags": [
          "Organisation"
        ],
        "summary": "Organisation ändern",
        "description": "Ändert Name, Subdomain (alte Subdomain bleibt als Weiterleitung), Adresse, MWST, Akzentfarbe, Bedingungen für Fahrende oder Sichtbarkeit der Instanzseite.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "slug": {
                    "type": "string"
                  },
                  "legal_name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 200
                  },
                  "street": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 200
                  },
                  "postal_code": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 20
                  },
                  "city": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 100
                  },
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2
                  },
                  "contact_email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email"
                  },
                  "contact_phone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 40
                  },
                  "website": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri"
                  },
                  "vat_registered": {
                    "type": "boolean"
                  },
                  "vat_number": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 40
                  },
                  "vat_rate_bps": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 3000
                  },
                  "accent_color": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^#[0-9a-fA-F]{6}$"
                  },
                  "logo_url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri"
                  },
                  "welcome_text": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "de": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "fr": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "it": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "en": {
                        "type": "string",
                        "maxLength": 2000
                      }
                    }
                  },
                  "driver_terms": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "de": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "fr": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "it": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "en": {
                        "type": "string",
                        "maxLength": 2000
                      }
                    }
                  },
                  "public_page": {
                    "type": "object",
                    "properties": {
                      "showLocations": {
                        "type": "boolean"
                      },
                      "showTariffs": {
                        "type": "boolean"
                      },
                      "showMap": {
                        "type": "boolean"
                      },
                      "showContact": {
                        "type": "boolean"
                      },
                      "showOpeningHours": {
                        "type": "boolean"
                      }
                    }
                  },
                  "test_mode": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Organisation ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Organization"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations": {
      "get": {
        "operationId": "listIntegrations",
        "tags": [
          "Verbindungen"
        ],
        "summary": "Verbindungen auflisten",
        "description": "Verbundene Hersteller (Easee) und Zahlungskonten (zahls.ch, Freika). Zugangsdaten werden nie ausgegeben.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Verbindungen auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/easee": {
      "post": {
        "operationId": "connectEasee",
        "tags": [
          "Verbindungen"
        ],
        "summary": "Easee verbinden",
        "description": "Meldet sich einmal mit dem Easee-Login an. Ladehase speichert nur die Tokens (verschlüsselt), nie das Passwort, und importiert sofort alle Charger. Neue Charger sind zuerst deaktiviert.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userName": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 200
                  },
                  "password": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "userName",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Easee verbinden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/zahls": {
      "post": {
        "operationId": "connectZahls",
        "tags": [
          "Verbindungen"
        ],
        "summary": "zahls.ch-Konto verbinden",
        "description": "Verbindet das eigene zahls.ch-Konto mit Instanzname und API-Schlüssel. Das Geld fliesst direkt auf dieses Konto.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "instance": {
                    "type": "string"
                  },
                  "apiKey": {
                    "type": "string",
                    "minLength": 10,
                    "maxLength": 200
                  }
                },
                "required": [
                  "instance",
                  "apiKey"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "zahls.ch-Konto verbinden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/freika": {
      "post": {
        "operationId": "connectFreika",
        "tags": [
          "Verbindungen"
        ],
        "summary": "Freika-Konto verbinden",
        "description": "Verbindet das eigene Freika-Konto mit einem API-Schlüssel (Rechte «schreiben» und «Terminals»). Nötig für das PAX IM30.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "apiKey": {
                    "type": "string",
                    "pattern": "^fk_(live|test)_[A-Za-z0-9_-]{8,}$"
                  }
                },
                "required": [
                  "apiKey"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Freika-Konto verbinden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/test": {
      "post": {
        "operationId": "enableTestMode",
        "tags": [
          "Verbindungen"
        ],
        "summary": "Testgeräte anlegen",
        "description": "Legt simulierte Ladepunkte und Testzahlungen an. Ideal zum Ausprobieren ohne Hardware und für automatisierte Tests (Schlüssel lh_test_).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "201": {
            "description": "Testgeräte anlegen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/{id}/test": {
      "post": {
        "operationId": "testIntegration",
        "tags": [
          "Verbindungen"
        ],
        "summary": "Verbindung prüfen",
        "description": "Prüft die Zugangsdaten beim Hersteller oder Zahlungspartner und aktualisiert den Status.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Verbindung prüfen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/{id}/sync": {
      "post": {
        "operationId": "syncIntegration",
        "tags": [
          "Verbindungen"
        ],
        "summary": "Geräte importieren",
        "description": "Liest alle Geräte beim Hersteller und legt neue Standorte, Geräte, Ladepunkte und QR-Codes an.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Geräte importieren",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/{id}": {
      "delete": {
        "operationId": "disconnectIntegration",
        "tags": [
          "Verbindungen"
        ],
        "summary": "Verbindung trennen",
        "description": "Löscht die Zugangsdaten. Geräte dieses Herstellers werden deaktiviert.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Verbindung trennen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/locations": {
      "get": {
        "operationId": "listLocations",
        "tags": [
          "Standorte"
        ],
        "summary": "Standorte auflisten",
        "description": "Alle Standorte der Organisation.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Standorte auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createLocation",
        "tags": [
          "Standorte"
        ],
        "summary": "Standort anlegen",
        "description": "Neuer Standort mit Adresse und Zahlungskonto für QR-Zahlungen.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "street": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 200
                  },
                  "postal_code": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 20
                  },
                  "city": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 100
                  },
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2,
                    "default": "CH"
                  },
                  "latitude": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": -90,
                    "maximum": 90
                  },
                  "longitude": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": -180,
                    "maximum": 180
                  },
                  "time_zone": {
                    "type": "string",
                    "default": "Europe/Zurich"
                  },
                  "opening_hours": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  },
                  "payment_integration_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "is_public": {
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Standort anlegen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Location"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/locations/{id}": {
      "get": {
        "operationId": "getLocation",
        "tags": [
          "Standorte"
        ],
        "summary": "Standort abrufen",
        "description": "Ein Standort.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Standort abrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Location"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateLocation",
        "tags": [
          "Standorte"
        ],
        "summary": "Standort ändern",
        "description": "Ändert Name, Adresse, Öffnungszeiten oder das Zahlungskonto.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "street": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 200
                  },
                  "postal_code": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 20
                  },
                  "city": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 100
                  },
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2,
                    "default": "CH"
                  },
                  "latitude": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": -90,
                    "maximum": 90
                  },
                  "longitude": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": -180,
                    "maximum": 180
                  },
                  "time_zone": {
                    "type": "string",
                    "default": "Europe/Zurich"
                  },
                  "opening_hours": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  },
                  "payment_integration_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "is_public": {
                    "type": "boolean",
                    "default": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Standort ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Location"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteLocation",
        "tags": [
          "Standorte"
        ],
        "summary": "Standort löschen",
        "description": "Nur Standorte ohne Geräte.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Standort löschen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices": {
      "get": {
        "operationId": "listDevices",
        "tags": [
          "Geräte"
        ],
        "summary": "Geräte auflisten",
        "description": "Ladepunkte mit aktuellem Zustand, Tarif, Abrechnungsmodell und QR-Code-URL.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "location_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "kind",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Geräte auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/{id}": {
      "get": {
        "operationId": "getDevice",
        "tags": [
          "Geräte"
        ],
        "summary": "Gerät abrufen",
        "description": "Ein Gerät mit Zustand.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Gerät abrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Device"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateDevice",
        "tags": [
          "Geräte"
        ],
        "summary": "Gerät ändern",
        "description": "Name, Standort, Tarif, Abrechnungsmodell (reservation, prepaid, both), Reservationsgrenzen, Pakete. `enabled: true` aktiviert das Gerät und setzt beim Hersteller «Autorisierung erforderlich».",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "location_id": {
                    "type": "string"
                  },
                  "tariff_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "billing": {
                    "type": "object",
                    "properties": {
                      "model": {
                        "type": "string",
                        "enum": [
                          "reservation",
                          "prepaid",
                          "both"
                        ],
                        "default": "reservation"
                      },
                      "reservationDefault": {
                        "type": "integer",
                        "minimum": 100,
                        "default": 3000
                      },
                      "reservationMin": {
                        "type": "integer",
                        "minimum": 100,
                        "default": 1000
                      },
                      "reservationMax": {
                        "type": "integer",
                        "minimum": 100,
                        "default": 10000
                      },
                      "safetyMarginBps": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 2000,
                        "default": 300
                      },
                      "packages": {
                        "type": "array",
                        "items": {
                          "oneOf": [
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "enum": [
                                    "energy"
                                  ]
                                },
                                "id": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 40
                                },
                                "energyWh": {
                                  "type": "integer",
                                  "exclusiveMinimum": 0
                                },
                                "price": {
                                  "type": "integer",
                                  "exclusiveMinimum": 0
                                }
                              },
                              "required": [
                                "kind",
                                "id",
                                "energyWh",
                                "price"
                              ]
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "enum": [
                                    "amount"
                                  ]
                                },
                                "id": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 40
                                },
                                "amount": {
                                  "type": "integer",
                                  "exclusiveMinimum": 0
                                }
                              },
                              "required": [
                                "kind",
                                "id",
                                "amount"
                              ]
                            }
                          ]
                        },
                        "maxItems": 8,
                        "default": []
                      },
                      "prepaidRemainder": {
                        "type": "string",
                        "enum": [
                          "refund",
                          "forfeit"
                        ],
                        "default": "refund"
                      },
                      "plugTimeoutMinutes": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 60,
                        "default": 10
                      },
                      "maxDurationMinutes": {
                        "type": "integer",
                        "minimum": 10,
                        "maximum": 10080,
                        "default": 1440
                      }
                    }
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gerät ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Device"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/{id}/state": {
      "get": {
        "operationId": "getDeviceState",
        "tags": [
          "Geräte"
        ],
        "summary": "Zustand abfragen",
        "description": "Aktueller Zustand. Mit `refresh=true` wird beim Hersteller nachgefragt.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": [
                "boolean",
                "null"
              ]
            },
            "required": false,
            "name": "refresh",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Zustand abfragen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceState"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/{id}/start": {
      "post": {
        "operationId": "startDevice",
        "tags": [
          "Geräte"
        ],
        "summary": "Ladung ohne Zahlung starten",
        "description": "Gibt den Ladepunkt ohne Zahlung frei (z. B. eigenes Auto). Ladehase legt dafür eine Gratis-Sitzung an, damit die Energie erfasst wird.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "201": {
            "description": "Ladung ohne Zahlung starten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/{id}/stop": {
      "post": {
        "operationId": "stopDevice",
        "tags": [
          "Geräte"
        ],
        "summary": "Ladung am Gerät stoppen",
        "description": "Stoppt die laufende Sitzung des Geräts und rechnet ab. Ohne Sitzung wird nur der Stoppbefehl gesendet.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Ladung am Gerät stoppen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/{id}/lock": {
      "post": {
        "operationId": "lockDevice",
        "tags": [
          "Geräte"
        ],
        "summary": "Gerät sperren",
        "description": "Keine neuen Ladungen, laufende Ladung läuft weiter.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Gerät sperren",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Device"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/{id}/unlock": {
      "post": {
        "operationId": "unlockDevice",
        "tags": [
          "Geräte"
        ],
        "summary": "Gerät entsperren",
        "description": "Hebt die Sperre auf.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Gerät entsperren",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Device"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/devices/{id}/simulate": {
      "post": {
        "operationId": "controlTestDevice",
        "tags": [
          "Geräte"
        ],
        "summary": "Testgerät steuern",
        "description": "Nur Testmodus: simuliertes Auto anstecken (`plug`), abziehen (`unplug`), offline, Störung, Leistung ändern.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "plug",
                      "unplug",
                      "offline",
                      "online",
                      "error",
                      "clear_error",
                      "set_power"
                    ]
                  },
                  "vehicle_need_wh": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "power_w": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  }
                },
                "required": [
                  "action"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Testgerät steuern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceState"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs": {
      "get": {
        "operationId": "listTariffs",
        "tags": [
          "Tarife"
        ],
        "summary": "Tarife auflisten",
        "description": "Aktive Tarife mit aktueller Version.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tarife auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TariffList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createTariff",
        "tags": [
          "Tarife"
        ],
        "summary": "Tarif anlegen",
        "description": "Tarifregeln: `energyPrice` in Hundertstel-Rappen pro kWh (4500 = 45 Rappen), `startFee` und `serviceFee` in Rappen, `timeWindows` für zeitabhängige Preise, `idleFee` für die Standzeitgebühr, `maxAmount` als Höchstbetrag. Preise inkl. MWST.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  },
                  "rules": {
                    "type": "object",
                    "properties": {
                      "currency": {
                        "type": "string",
                        "enum": [
                          "CHF",
                          "EUR"
                        ],
                        "default": "CHF"
                      },
                      "energyPrice": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1000000
                      },
                      "startFee": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 0
                      },
                      "serviceFee": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 0
                      },
                      "timeWindows": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "days": {
                              "type": "array",
                              "items": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 7
                              },
                              "minItems": 1
                            },
                            "from": {
                              "type": "string",
                              "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                            },
                            "to": {
                              "type": "string",
                              "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                            },
                            "energyPrice": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 1000000
                            },
                            "label": {
                              "type": "string",
                              "maxLength": 60
                            }
                          },
                          "required": [
                            "days",
                            "from",
                            "to",
                            "energyPrice"
                          ]
                        },
                        "maxItems": 20,
                        "default": []
                      },
                      "idleFee": {
                        "type": "object",
                        "properties": {
                          "pricePerMinute": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 10000
                          },
                          "graceMinutes": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1440
                          },
                          "trigger": {
                            "type": "string",
                            "enum": [
                              "after_charging",
                              "after_start"
                            ]
                          },
                          "maxAmount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "quietHours": {
                            "type": "object",
                            "properties": {
                              "from": {
                                "type": "string",
                                "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                              },
                              "to": {
                                "type": "string",
                                "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                              }
                            },
                            "required": [
                              "from",
                              "to"
                            ]
                          }
                        },
                        "required": [
                          "pricePerMinute",
                          "graceMinutes",
                          "trigger"
                        ]
                      },
                      "maxAmount": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "timeZone": {
                        "type": "string",
                        "default": "Europe/Zurich"
                      }
                    },
                    "required": [
                      "energyPrice"
                    ]
                  }
                },
                "required": [
                  "name",
                  "rules"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tarif anlegen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tariff"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/{id}": {
      "get": {
        "operationId": "getTariff",
        "tags": [
          "Tarife"
        ],
        "summary": "Tarif abrufen",
        "description": "Ein Tarif mit Regeln der aktuellen Version.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Tarif abrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tariff"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateTariff",
        "tags": [
          "Tarife"
        ],
        "summary": "Tarif ändern",
        "description": "Neue Regeln ergeben eine neue Version. Laufende Ladungen behalten ihre Version.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  },
                  "rules": {
                    "type": "object",
                    "properties": {
                      "currency": {
                        "type": "string",
                        "enum": [
                          "CHF",
                          "EUR"
                        ],
                        "default": "CHF"
                      },
                      "energyPrice": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1000000
                      },
                      "startFee": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 0
                      },
                      "serviceFee": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 0
                      },
                      "timeWindows": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "days": {
                              "type": "array",
                              "items": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 7
                              },
                              "minItems": 1
                            },
                            "from": {
                              "type": "string",
                              "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                            },
                            "to": {
                              "type": "string",
                              "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                            },
                            "energyPrice": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 1000000
                            },
                            "label": {
                              "type": "string",
                              "maxLength": 60
                            }
                          },
                          "required": [
                            "days",
                            "from",
                            "to",
                            "energyPrice"
                          ]
                        },
                        "maxItems": 20,
                        "default": []
                      },
                      "idleFee": {
                        "type": "object",
                        "properties": {
                          "pricePerMinute": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 10000
                          },
                          "graceMinutes": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1440
                          },
                          "trigger": {
                            "type": "string",
                            "enum": [
                              "after_charging",
                              "after_start"
                            ]
                          },
                          "maxAmount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "quietHours": {
                            "type": "object",
                            "properties": {
                              "from": {
                                "type": "string",
                                "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                              },
                              "to": {
                                "type": "string",
                                "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                              }
                            },
                            "required": [
                              "from",
                              "to"
                            ]
                          }
                        },
                        "required": [
                          "pricePerMinute",
                          "graceMinutes",
                          "trigger"
                        ]
                      },
                      "maxAmount": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "timeZone": {
                        "type": "string",
                        "default": "Europe/Zurich"
                      }
                    },
                    "required": [
                      "energyPrice"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tarif ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tariff"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "archiveTariff",
        "tags": [
          "Tarife"
        ],
        "summary": "Tarif archivieren",
        "description": "Nur Tarife ohne aktive Geräte.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Tarif archivieren",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tariff"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/{id}/versions": {
      "get": {
        "operationId": "listTariffVersions",
        "tags": [
          "Tarife"
        ],
        "summary": "Versionen auflisten",
        "description": "Alle Versionen eines Tarifs.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Versionen auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/{id}/preview": {
      "post": {
        "operationId": "previewTariff",
        "tags": [
          "Tarife"
        ],
        "summary": "Tarifvorschau",
        "description": "Beispielbeträge, etwa «So viel kostet eine Ladung mit 20 kWh». Mit `rules` im Body lässt sich ein Entwurf berechnen.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rules": {
                    "type": "object",
                    "properties": {
                      "currency": {
                        "type": "string",
                        "enum": [
                          "CHF",
                          "EUR"
                        ],
                        "default": "CHF"
                      },
                      "energyPrice": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1000000
                      },
                      "startFee": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 0
                      },
                      "serviceFee": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 0
                      },
                      "timeWindows": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "days": {
                              "type": "array",
                              "items": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 7
                              },
                              "minItems": 1
                            },
                            "from": {
                              "type": "string",
                              "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                            },
                            "to": {
                              "type": "string",
                              "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                            },
                            "energyPrice": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 1000000
                            },
                            "label": {
                              "type": "string",
                              "maxLength": 60
                            }
                          },
                          "required": [
                            "days",
                            "from",
                            "to",
                            "energyPrice"
                          ]
                        },
                        "maxItems": 20,
                        "default": []
                      },
                      "idleFee": {
                        "type": "object",
                        "properties": {
                          "pricePerMinute": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 10000
                          },
                          "graceMinutes": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1440
                          },
                          "trigger": {
                            "type": "string",
                            "enum": [
                              "after_charging",
                              "after_start"
                            ]
                          },
                          "maxAmount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "quietHours": {
                            "type": "object",
                            "properties": {
                              "from": {
                                "type": "string",
                                "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                              },
                              "to": {
                                "type": "string",
                                "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                              }
                            },
                            "required": [
                              "from",
                              "to"
                            ]
                          }
                        },
                        "required": [
                          "pricePerMinute",
                          "graceMinutes",
                          "trigger"
                        ]
                      },
                      "maxAmount": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "timeZone": {
                        "type": "string",
                        "default": "Europe/Zurich"
                      }
                    },
                    "required": [
                      "energyPrice"
                    ]
                  },
                  "energy_wh": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "exclusiveMinimum": 0
                    },
                    "maxItems": 6,
                    "default": [
                      10000,
                      20000,
                      40000
                    ]
                  },
                  "power_w": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "default": 11000
                  },
                  "idle_minutes": {
                    "type": "integer",
                    "minimum": 0,
                    "default": 0
                  },
                  "start_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tarifvorschau",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/preview": {
      "post": {
        "operationId": "previewTariffDraft",
        "tags": [
          "Tarife"
        ],
        "summary": "Vorschau für Entwurf",
        "description": "Wie die Tarifvorschau, aber ohne gespeicherten Tarif (Regeln im Body).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rules": {
                    "type": "object",
                    "properties": {
                      "currency": {
                        "type": "string",
                        "enum": [
                          "CHF",
                          "EUR"
                        ],
                        "default": "CHF"
                      },
                      "energyPrice": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 1000000
                      },
                      "startFee": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 0
                      },
                      "serviceFee": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 0
                      },
                      "timeWindows": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "days": {
                              "type": "array",
                              "items": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 7
                              },
                              "minItems": 1
                            },
                            "from": {
                              "type": "string",
                              "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                            },
                            "to": {
                              "type": "string",
                              "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                            },
                            "energyPrice": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 1000000
                            },
                            "label": {
                              "type": "string",
                              "maxLength": 60
                            }
                          },
                          "required": [
                            "days",
                            "from",
                            "to",
                            "energyPrice"
                          ]
                        },
                        "maxItems": 20,
                        "default": []
                      },
                      "idleFee": {
                        "type": "object",
                        "properties": {
                          "pricePerMinute": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 10000
                          },
                          "graceMinutes": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1440
                          },
                          "trigger": {
                            "type": "string",
                            "enum": [
                              "after_charging",
                              "after_start"
                            ]
                          },
                          "maxAmount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "quietHours": {
                            "type": "object",
                            "properties": {
                              "from": {
                                "type": "string",
                                "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                              },
                              "to": {
                                "type": "string",
                                "pattern": "^(?:[01]\\d|2[0-3]):[0-5]\\d$|^24:00$"
                              }
                            },
                            "required": [
                              "from",
                              "to"
                            ]
                          }
                        },
                        "required": [
                          "pricePerMinute",
                          "graceMinutes",
                          "trigger"
                        ]
                      },
                      "maxAmount": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "timeZone": {
                        "type": "string",
                        "default": "Europe/Zurich"
                      }
                    },
                    "required": [
                      "energyPrice"
                    ]
                  },
                  "energy_wh": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "exclusiveMinimum": 0
                    },
                    "maxItems": 6,
                    "default": [
                      10000,
                      20000,
                      40000
                    ]
                  },
                  "power_w": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "default": 11000
                  },
                  "idle_minutes": {
                    "type": "integer",
                    "minimum": 0,
                    "default": 0
                  },
                  "start_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vorschau für Entwurf",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/codes": {
      "get": {
        "operationId": "listCodes",
        "tags": [
          "QR-Codes"
        ],
        "summary": "QR-Codes auflisten",
        "description": "Statische QR-Codes mit URL und Anzahl Scans.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "QR-Codes auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodeList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createCode",
        "tags": [
          "QR-Codes"
        ],
        "summary": "QR-Code anlegen",
        "description": "Für einen Ladepunkt oder einen ganzen Standort (Auswahl auf der Bezahlseite).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "target": {
                    "type": "string",
                    "enum": [
                      "connector",
                      "location"
                    ]
                  },
                  "connector_id": {
                    "type": "string"
                  },
                  "location_id": {
                    "type": "string"
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 80
                  }
                },
                "required": [
                  "target"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "QR-Code anlegen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Code"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/codes/{id}": {
      "get": {
        "operationId": "getCode",
        "tags": [
          "QR-Codes"
        ],
        "summary": "QR-Code abrufen",
        "description": "Ein QR-Code.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "QR-Code abrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Code"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateCode",
        "tags": [
          "QR-Codes"
        ],
        "summary": "QR-Code ändern",
        "description": "Bezeichnung ändern oder deaktivieren.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "disabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "QR-Code ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Code"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/codes/{id}/qr.svg": {
      "get": {
        "operationId": "getCodeSvg",
        "tags": [
          "QR-Codes"
        ],
        "summary": "QR-Code als SVG",
        "description": "Mit Bildmarke in der Mitte.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "QR-Code als SVG",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/codes/{id}/qr.png": {
      "get": {
        "operationId": "getCodePng",
        "tags": [
          "QR-Codes"
        ],
        "summary": "QR-Code als PNG",
        "description": "1024 × 1024 Pixel.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "QR-Code als PNG",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/signs/render": {
      "post": {
        "operationId": "renderSigns",
        "tags": [
          "Schilder"
        ],
        "summary": "Schilder erzeugen",
        "description": "Druckfertiges PDF (mit Beschnitt und Schnittmarken) oder SVG-Vorschau. Formate: a6, a6_landscape, a5, a5_landscape, sticker_round_80, sticker_square_100, label_front.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "maxItems": 100
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "a6",
                      "a6_landscape",
                      "a5",
                      "a5_landscape",
                      "sticker_round_80",
                      "sticker_square_100",
                      "label_front"
                    ],
                    "default": "a6"
                  },
                  "languages": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "de",
                        "fr",
                        "it",
                        "en"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 4,
                    "default": [
                      "de",
                      "fr",
                      "it",
                      "en"
                    ]
                  },
                  "show_tariff": {
                    "type": "boolean",
                    "default": true
                  },
                  "branding": {
                    "type": "boolean",
                    "default": true
                  },
                  "crop_marks": {
                    "type": "boolean",
                    "default": true
                  },
                  "output": {
                    "type": "string",
                    "enum": [
                      "pdf",
                      "svg"
                    ],
                    "default": "pdf"
                  }
                },
                "required": [
                  "code_ids"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Schilder erzeugen",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sign_products": {
      "get": {
        "operationId": "listSignProducts",
        "tags": [
          "Schilder"
        ],
        "summary": "Schildprodukte",
        "description": "Wetterfeste Schilder und Aufkleber zum Bestellen mit Preisen.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Schildprodukte",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sign_orders": {
      "get": {
        "operationId": "listSignOrders",
        "tags": [
          "Schilder"
        ],
        "summary": "Schildbestellungen",
        "description": "Bestellungen der Organisation.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Schildbestellungen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createSignOrder",
        "tags": [
          "Schilder"
        ],
        "summary": "Schilder bestellen",
        "description": "Bestellung mit Zahlungslink. Wir drucken nach Zahlungseingang und senden per Post.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "product_id": {
                          "type": "string"
                        },
                        "code_id": {
                          "type": "string"
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 50
                        },
                        "languages": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "de",
                              "fr",
                              "it",
                              "en"
                            ]
                          },
                          "minItems": 1,
                          "maxItems": 4
                        }
                      },
                      "required": [
                        "product_id",
                        "code_id",
                        "quantity",
                        "languages"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 50
                  },
                  "shipping_address": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "minLength": 2,
                        "maxLength": 120
                      },
                      "street": {
                        "type": "string",
                        "minLength": 2,
                        "maxLength": 200
                      },
                      "postal_code": {
                        "type": "string",
                        "minLength": 4,
                        "maxLength": 10
                      },
                      "city": {
                        "type": "string",
                        "minLength": 2,
                        "maxLength": 100
                      },
                      "country": {
                        "type": "string",
                        "minLength": 2,
                        "maxLength": 2,
                        "default": "CH"
                      }
                    },
                    "required": [
                      "name",
                      "street",
                      "postal_code",
                      "city"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "items",
                  "shipping_address"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Schilder bestellen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions": {
      "get": {
        "operationId": "listSessions",
        "tags": [
          "Sitzungen"
        ],
        "summary": "Sitzungen auflisten",
        "description": "Ladungen, neueste zuerst. Filter: state (kommagetrennt), device_id, location_id, access_grant_id, from, to.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "starting_after",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "state",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "device_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "location_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "access_grant_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "from",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "to",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Sitzungen auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createSession",
        "tags": [
          "Sitzungen"
        ],
        "summary": "Sitzung starten",
        "description": "Startet eine Ladung ohne Zahlung über die API (z. B. für eigene Apps oder Weiterverrechnung). Mit `access_grant_id` gilt der Sondertarif des Zugangs.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "device_id": {
                    "type": "string"
                  },
                  "access_grant_id": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "device_id"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sitzung starten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}": {
      "get": {
        "operationId": "getSession",
        "tags": [
          "Sitzungen"
        ],
        "summary": "Sitzung abrufen",
        "description": "Eine Ladung mit Beträgen, Energie und Preisaufstellung.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Sitzung abrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/stop": {
      "post": {
        "operationId": "stopSession",
        "tags": [
          "Sitzungen"
        ],
        "summary": "Sitzung stoppen",
        "description": "Stoppt die Ladung. Abgerechnet wird automatisch.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Sitzung stoppen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/events": {
      "get": {
        "operationId": "listSessionEvents",
        "tags": [
          "Sitzungen"
        ],
        "summary": "Zeitleiste einer Sitzung",
        "description": "Alle Zustandswechsel und Messwerte (Ladekurve).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Zeitleiste einer Sitzung",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sessions/{id}/refund": {
      "post": {
        "operationId": "refundSession",
        "tags": [
          "Sitzungen"
        ],
        "summary": "Rückerstatten",
        "description": "Voll oder teilweise (`amount` in Rappen).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rückerstatten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/payments": {
      "get": {
        "operationId": "listPayments",
        "tags": [
          "Zahlungen"
        ],
        "summary": "Zahlungen auflisten",
        "description": "Spiegel der Zahlungen bei zahls.ch und Freika.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "starting_after",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "zahls",
                "freika",
                "mock"
              ]
            },
            "required": false,
            "name": "provider",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Zahlungen auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/payments/{id}": {
      "get": {
        "operationId": "getPayment",
        "tags": [
          "Zahlungen"
        ],
        "summary": "Zahlung abrufen",
        "description": "Eine Zahlung.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Zahlung abrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/terminals": {
      "get": {
        "operationId": "listTerminals",
        "tags": [
          "Terminals"
        ],
        "summary": "Terminals auflisten",
        "description": "Gekoppelte PAX IM30.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Terminals auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TerminalList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createTerminal",
        "tags": [
          "Terminals"
        ],
        "summary": "Terminal anlegen",
        "description": "Neues PAX IM30 für einen Standort. Antwort enthält den Wartungs-PIN (nur einmal sichtbar).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "default": "PAX IM30"
                  },
                  "location_id": {
                    "type": "string"
                  },
                  "integration_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "external_terminal_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "maintenance_pin": {
                    "type": "string",
                    "pattern": "^\\d{4,8}$"
                  }
                },
                "required": [
                  "location_id"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Terminal anlegen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Terminal"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/terminals/available": {
      "get": {
        "operationId": "listProviderTerminals",
        "tags": [
          "Terminals"
        ],
        "summary": "Freika-Terminals",
        "description": "Terminals im verbundenen Freika-Konto zur Auswahl beim Koppeln.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Freika-Terminals",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/terminals/{id}": {
      "patch": {
        "operationId": "updateTerminal",
        "tags": [
          "Terminals"
        ],
        "summary": "Terminal ändern",
        "description": "Name, Standort, Freika-Terminal, Wartungs-PIN.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "default": "PAX IM30"
                  },
                  "location_id": {
                    "type": "string"
                  },
                  "integration_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "external_terminal_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "maintenance_pin": {
                    "type": "string",
                    "pattern": "^\\d{4,8}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Terminal ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Terminal"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTerminal",
        "tags": [
          "Terminals"
        ],
        "summary": "Terminal entfernen",
        "description": "Die App muss danach neu gekoppelt werden.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Terminal entfernen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/terminals/{id}/pairing_codes": {
      "post": {
        "operationId": "createPairingCode",
        "tags": [
          "Terminals"
        ],
        "summary": "Kopplungscode",
        "description": "Code und QR-Inhalt zum Koppeln der Terminal-App (15 Minuten gültig).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "201": {
            "description": "Kopplungscode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/access_grants": {
      "get": {
        "operationId": "listAccessGrants",
        "tags": [
          "Zugänge"
        ],
        "summary": "Zugänge auflisten",
        "description": "Personen und Ladekarten, die gratis oder zum Sondertarif laden.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Zugänge auflisten",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessGrantList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createAccessGrant",
        "tags": [
          "Zugänge"
        ],
        "summary": "Zugang anlegen",
        "description": "Ohne `tariff_id` gratis, mit `tariff_id` Sondertarif und Monatsabrechnung. Erzeugt einen persönlichen Link.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email"
                  },
                  "rfid_uid": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 64
                  },
                  "create_link": {
                    "type": "boolean",
                    "default": true
                  },
                  "valid_from": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "valid_until": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "device_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": []
                  },
                  "tariff_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "monthly_limit_wh": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "exclusiveMinimum": 0
                  },
                  "billing_integration_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "note": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Zugang anlegen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessGrant"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/access_grants/{id}": {
      "get": {
        "operationId": "getAccessGrant",
        "tags": [
          "Zugänge"
        ],
        "summary": "Zugang abrufen",
        "description": "Ein Zugang.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Zugang abrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessGrant"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateAccessGrant",
        "tags": [
          "Zugänge"
        ],
        "summary": "Zugang ändern",
        "description": "Auch `revoked` und `regenerate_link`.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email"
                  },
                  "rfid_uid": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 64
                  },
                  "create_link": {
                    "type": "boolean",
                    "default": true
                  },
                  "valid_from": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "valid_until": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "device_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": []
                  },
                  "tariff_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "monthly_limit_wh": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "exclusiveMinimum": 0
                  },
                  "billing_integration_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "note": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  },
                  "revoked": {
                    "type": "boolean"
                  },
                  "regenerate_link": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Zugang ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessGrant"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteAccessGrant",
        "tags": [
          "Zugänge"
        ],
        "summary": "Zugang widerrufen",
        "description": "Link und Berechtigung werden ungültig.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Zugang widerrufen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing_statements": {
      "get": {
        "operationId": "listBillingStatements",
        "tags": [
          "Zugänge"
        ],
        "summary": "Monatsabrechnungen",
        "description": "Abrechnungen für Zugänge mit Sondertarif.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "period",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Monatsabrechnungen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing_statements/generate": {
      "post": {
        "operationId": "generateBillingStatements",
        "tags": [
          "Zugänge"
        ],
        "summary": "Abrechnungen erstellen",
        "description": "Für einen Monat (`period` = JJJJ-MM).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "period": {
                    "type": "string"
                  }
                },
                "required": [
                  "period"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Abrechnungen erstellen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing_statements/{id}/send": {
      "post": {
        "operationId": "sendBillingStatement",
        "tags": [
          "Zugänge"
        ],
        "summary": "Abrechnung senden",
        "description": "E-Mail mit Zahlungslink über zahls.ch oder Freika.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Abrechnung senden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing_statements/{id}/paid": {
      "post": {
        "operationId": "markBillingStatementPaid",
        "tags": [
          "Zugänge"
        ],
        "summary": "Als bezahlt markieren",
        "description": "Zum Beispiel bei Barzahlung.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Als bezahlt markieren",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/reports/summary": {
      "get": {
        "operationId": "getReportSummary",
        "tags": [
          "Berichte"
        ],
        "summary": "Kennzahlen",
        "description": "Ladungen, Energie, Umsatz, MWST, Tagesreihe, pro Gerät und Kanal (Standard: letzte 30 Tage).",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "from",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "to",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "location_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "device_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "access_grant_id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Kennzahlen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/reports/export": {
      "get": {
        "operationId": "exportReport",
        "tags": [
          "Berichte"
        ],
        "summary": "Export",
        "description": "CSV, XLSX oder PDF für Buchhaltung und Weiterverrechnung.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "from",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "required": false,
            "name": "to",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "location_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "device_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "access_grant_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "csv",
                "xlsx",
                "pdf"
              ],
              "default": "csv"
            },
            "required": false,
            "name": "format",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Export",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/members": {
      "get": {
        "operationId": "listMembers",
        "tags": [
          "Team"
        ],
        "summary": "Mitglieder",
        "description": "Mitglieder und offene Einladungen.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Mitglieder",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/invitations": {
      "post": {
        "operationId": "inviteMember",
        "tags": [
          "Team"
        ],
        "summary": "Person einladen",
        "description": "Rollen: owner, admin, member.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "member"
                    ],
                    "default": "member"
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Person einladen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/invitations/{id}": {
      "delete": {
        "operationId": "cancelInvitation",
        "tags": [
          "Team"
        ],
        "summary": "Einladung zurückziehen",
        "description": "Der Link wird ungültig.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Einladung zurückziehen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/members/{id}": {
      "patch": {
        "operationId": "updateMember",
        "tags": [
          "Team"
        ],
        "summary": "Rolle ändern",
        "description": "Mindestens eine Inhaberin oder ein Inhaber bleibt.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "member"
                    ]
                  }
                },
                "required": [
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rolle ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "removeMember",
        "tags": [
          "Team"
        ],
        "summary": "Mitglied entfernen",
        "description": "Entfernt die Person aus der Organisation.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Mitglied entfernen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook_endpoints": {
      "get": {
        "operationId": "listWebhookEndpoints",
        "tags": [
          "Webhooks"
        ],
        "summary": "Webhook-Endpunkte",
        "description": "Empfänger für Ereignisse.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook-Endpunkte",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhookEndpoint",
        "tags": [
          "Webhooks"
        ],
        "summary": "Webhook anlegen",
        "description": "Signatur `Ladehase-Signature: t=…,v1=…` (HMAC-SHA256 über `t.body`). Das Geheimnis ist nur in dieser Antwort sichtbar.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 200
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "session.created",
                        "session.started",
                        "session.updated",
                        "session.stopped",
                        "session.settled",
                        "session.failed",
                        "payment.authorized",
                        "payment.captured",
                        "payment.released",
                        "payment.refunded",
                        "device.online",
                        "device.offline",
                        "device.error",
                        "terminal.online",
                        "terminal.offline",
                        "integration.error",
                        "*"
                      ]
                    },
                    "default": [
                      "*"
                    ]
                  },
                  "enabled": {
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook anlegen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook_endpoints/{id}": {
      "patch": {
        "operationId": "updateWebhookEndpoint",
        "tags": [
          "Webhooks"
        ],
        "summary": "Webhook ändern",
        "description": "Auch `rotate_secret`.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 200
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "session.created",
                        "session.started",
                        "session.updated",
                        "session.stopped",
                        "session.settled",
                        "session.failed",
                        "payment.authorized",
                        "payment.captured",
                        "payment.released",
                        "payment.refunded",
                        "device.online",
                        "device.offline",
                        "device.error",
                        "terminal.online",
                        "terminal.offline",
                        "integration.error",
                        "*"
                      ]
                    },
                    "default": [
                      "*"
                    ]
                  },
                  "enabled": {
                    "type": "boolean",
                    "default": true
                  },
                  "rotate_secret": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook ändern",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "tags": [
          "Webhooks"
        ],
        "summary": "Webhook löschen",
        "description": "Keine weiteren Zustellungen.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook löschen",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook_endpoints/{id}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "Zustellprotokoll",
        "description": "Letzte 100 Zustellungen mit Antwortcode.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Zustellprotokoll",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/events": {
      "get": {
        "operationId": "listEvents",
        "tags": [
          "Webhooks"
        ],
        "summary": "Ereignisse",
        "description": "Alle Ereignisse, neueste zuerst.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "starting_after",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "type",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Ereignisse",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventList"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/events/{id}/resend": {
      "post": {
        "operationId": "resendEvent",
        "tags": [
          "Webhooks"
        ],
        "summary": "Ereignis erneut senden",
        "description": "An alle passenden Endpunkte.",
        "security": [
          {
            "ApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "dev_7d3a9c1b0e2f4a6b"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 255,
              "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)"
            },
            "required": false,
            "description": "Wiederholbare Anfragen ohne doppelte Wirkung (24 Stunden)",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Ereignis erneut senden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Object"
                }
              }
            }
          },
          "400": {
            "description": "Anfrage ungültig",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nicht angemeldet",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Berechtigung fehlt",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Nicht gefunden",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Zustand passt nicht",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Zu viele Anfragen",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {}
}