{
  "openapi": "3.0.3",
  "info": {
    "title": "AmtsGuide Facts API",
    "version": "1.0.0",
    "description": "Structured facts about German bureaucratic processes, including generic topic data, supplier contact records, Halteverbot processing times, and Jagdschein costs, training, and exam data.",
    "contact": {
      "name": "AmtsGuide",
      "url": "https://amtsguide.de",
      "email": "info@amtsguide.de"
    }
  },
  "servers": [
    {
      "url": "https://api.amtsguide.de/api/v1",
      "description": "Canonical API host after DNS activation"
    },
    {
      "url": "https://amtsguide.de/api/v1",
      "description": "Current production web host"
    }
  ],
  "paths": {
    "/": {
      "get": {
        "summary": "List all endpoints",
        "operationId": "listEndpoints",
        "responses": {
          "200": {
            "description": "Endpoint index"
          }
        }
      }
    },
    "/topics/{topic}/facts/": {
      "get": {
        "summary": "Generic topic facts",
        "operationId": "getTopicFacts",
        "description": "Government facts, authority data, and metadata for any file-backed topic.",
        "parameters": [
          {
            "name": "topic",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "aevo-ausbilderschein",
                "balkonkraftwerk",
                "bussgeldverfahren",
                "e-auto-foerderung",
                "erbschein",
                "gmbh-gruendung",
                "halteverbot",
                "heilpraktiker",
                "hundefuehrerschein",
                "jagdschein",
                "kaminofen",
                "kfz-zulassung",
                "ladesaule-foerderung",
                "meisterpruefung",
                "sachkundepruefung-34a",
                "waermepumpe"
              ]
            },
            "description": "File-backed topic slug, e.g. heilpraktiker, e-auto-foerderung, or kfz-zulassung"
          }
        ],
        "responses": {
          "200": {
            "description": "Topic facts and metadata"
          },
          "404": {
            "description": "Topic not found, returns available topics"
          }
        }
      }
    },
    "/topics/{topic}/facts/{state}/": {
      "get": {
        "summary": "Generic topic facts by state",
        "operationId": "getTopicFactsByState",
        "description": "Authority records for a topic in a single state.",
        "parameters": [
          {
            "name": "topic",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "aevo-ausbilderschein",
                "balkonkraftwerk",
                "bussgeldverfahren",
                "e-auto-foerderung",
                "erbschein",
                "gmbh-gruendung",
                "halteverbot",
                "heilpraktiker",
                "hundefuehrerschein",
                "jagdschein",
                "kaminofen",
                "kfz-zulassung",
                "ladesaule-foerderung",
                "meisterpruefung",
                "sachkundepruefung-34a",
                "waermepumpe"
              ]
            },
            "description": "File-backed topic slug"
          },
          {
            "name": "state",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "State name as stored in topic authority records"
          }
        ],
        "responses": {
          "200": {
            "description": "Topic authority records for the state"
          },
          "404": {
            "description": "Topic or state not found"
          }
        }
      }
    },
    "/topics/{topic}/suppliers/": {
      "get": {
        "summary": "Generic topic suppliers",
        "operationId": "getTopicSuppliers",
        "description": "Contact-first supplier records for a topic, optionally filtered by city or state.",
        "parameters": [
          {
            "name": "topic",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Topic slug"
          },
          {
            "name": "city",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Return suppliers in this city plus nationwide suppliers"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Return suppliers in this state plus nationwide suppliers"
          }
        ],
        "responses": {
          "200": {
            "description": "Topic supplier records"
          },
          "404": {
            "description": "Topic not found, returns available topics"
          }
        }
      }
    },
    "/jagdschein/facts/": {
      "get": {
        "summary": "All hunting license facts",
        "operationId": "getJagdscheinFacts",
        "description": "Training, exam, and application data for all 16 German states.",
        "responses": {
          "200": {
            "description": "All states"
          }
        }
      }
    },
    "/jagdschein/facts/{state}/": {
      "get": {
        "summary": "Single state facts",
        "operationId": "getJagdscheinFactsByState",
        "parameters": [
          {
            "name": "state",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "State slug (e.g., bayern, berlin)"
          }
        ],
        "responses": {
          "200": {
            "description": "State facts"
          },
          "404": {
            "description": "State not found, returns available states"
          }
        }
      }
    },
    "/jagdschein/detail/": {
      "get": {
        "summary": "Full detail data for all states",
        "operationId": "getJagdscheinDetail",
        "description": "Comprehensive data: costs per license type, documents, application methods, special rules.",
        "responses": {
          "200": {
            "description": "All states detail"
          }
        }
      }
    },
    "/jagdschein/detail/{state}/": {
      "get": {
        "summary": "Single state detail",
        "operationId": "getJagdscheinDetailByState",
        "parameters": [
          {
            "name": "state",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "State detail"
          },
          "404": {
            "description": "State not found"
          }
        }
      }
    },
    "/calculator/halteverbot/": {
      "get": {
        "summary": "Halteverbot location data",
        "operationId": "getHalteverbotLocations",
        "description": "Processing times and costs for 24 locations (11 cities + 13 Berlin districts).",
        "responses": {
          "200": {
            "description": "All locations"
          }
        }
      }
    },
    "/calculator/halteverbot/results/": {
      "get": {
        "summary": "All 576 pre-computed pair results",
        "operationId": "getHalteverbotResults",
        "description": "Pre-computed lead time calculations for every origin/destination combination.",
        "responses": {
          "200": {
            "description": "576 pair results"
          }
        }
      }
    },
    "/calculator/halteverbot/results/{von}/{nach}/": {
      "get": {
        "summary": "Single pair result",
        "operationId": "getHalteverbotPairResult",
        "parameters": [
          {
            "name": "von",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Origin location slug"
          },
          {
            "name": "nach",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Destination location slug"
          },
          {
            "name": "datum",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Optional moving date (YYYY-MM-DD) for urgency and schedule fields"
          }
        ],
        "responses": {
          "200": {
            "description": "Pair result with max_days, location ordering, costs, and optional date urgency fields"
          },
          "404": {
            "description": "Location not found"
          }
        }
      }
    },
    "/calculator/jagdschein/results/": {
      "get": {
        "summary": "All states pre-computed results",
        "operationId": "getJagdscheinResults",
        "description": "Cost estimates, training durations, and exam info for all 16 states.",
        "responses": {
          "200": {
            "description": "16 state results"
          }
        }
      }
    },
    "/calculator/jagdschein/results/{state}/": {
      "get": {
        "summary": "Single state result",
        "operationId": "getJagdscheinStateResult",
        "parameters": [
          {
            "name": "state",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "State result with costs, training, exam, application data"
          },
          "404": {
            "description": "State not found"
          }
        }
      }
    },
    "/calculator/e-auto/results/": {
      "get": {
        "summary": "All E-Auto subsidy results",
        "operationId": "getEAutoResults",
        "description": "Subsidy entitlement estimates for all BEV/PHEV, income-bracket, and children combinations.",
        "responses": {
          "200": {
            "description": "24 E-Auto subsidy combinations"
          }
        }
      }
    },
    "/calculator/e-auto/results/{fahrzeugtyp}/{bracket}/{kinder}/": {
      "get": {
        "summary": "Single E-Auto subsidy result",
        "operationId": "getEAutoResult",
        "parameters": [
          {
            "name": "fahrzeugtyp",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "BEV",
                "PHEV"
              ]
            }
          },
          {
            "name": "bracket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 3
            },
            "description": "Income bracket index"
          },
          {
            "name": "kinder",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 2
            },
            "description": "Children index: 0, 1, or 2 for 2+"
          }
        ],
        "responses": {
          "200": {
            "description": "Subsidy entitlement, amount, note, and checklist"
          },
          "404": {
            "description": "Vehicle type, income bracket, or children index not found"
          }
        }
      }
    },
    "/calculator/wallbox/results/": {
      "get": {
        "summary": "All Wallbox baseline cost results",
        "operationId": "getWallboxResults",
        "description": "Baseline cost estimates for every supported property type, parking-space count, wallbox type, and cable-distance combination, without PLZ-specific Stadtwerk lookup.",
        "responses": {
          "200": {
            "description": "4,050 Wallbox baseline combinations"
          }
        }
      }
    },
    "/calculator/wallbox/results/{immobilientyp}/{stellplaetze}/{wallboxTyp}/{entfernung}/": {
      "get": {
        "summary": "Single Wallbox cost result",
        "operationId": "getWallboxResult",
        "parameters": [
          {
            "name": "immobilientyp",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "efh",
                "mfh",
                "tiefgarage"
              ]
            }
          },
          {
            "name": "stellplaetze",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "enum": [
                1,
                2,
                3,
                5,
                10,
                15,
                20,
                30,
                50
              ]
            }
          },
          {
            "name": "wallboxTyp",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "11kw",
                "22kw",
                "bidirektional"
              ]
            }
          },
          {
            "name": "entfernung",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            },
            "description": "Cable distance in meters"
          },
          {
            "name": "plz",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{5}$"
            },
            "description": "Optional German postal code for Stadtwerk subsidy lookup"
          }
        ],
        "responses": {
          "200": {
            "description": "Wallbox hardware, installation, subsidy, Stadtwerk, gross, and net-cost estimate"
          },
          "400": {
            "description": "Invalid PLZ"
          },
          "404": {
            "description": "Property type, parking-space count, wallbox type, or distance not found"
          }
        }
      }
    },
    "/calculator/balkonkraftwerk/results/": {
      "get": {
        "summary": "All Balkonkraftwerk baseline payback results",
        "operationId": "getBalkonkraftwerkResults",
        "description": "Default-price/default-electricity payback estimates for active subsidy cities plus the no-city baseline.",
        "responses": {
          "200": {
            "description": "Balkonkraftwerk baseline city and system-size combinations"
          }
        }
      }
    },
    "/calculator/balkonkraftwerk/results/{city}/{leistung}/": {
      "get": {
        "summary": "Single Balkonkraftwerk payback result",
        "operationId": "getBalkonkraftwerkResult",
        "parameters": [
          {
            "name": "city",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Active subsidy city slug, or 'none' for the no-city baseline"
          },
          {
            "name": "leistung",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "300w",
                "600w",
                "800w",
                "1600w"
              ]
            }
          },
          {
            "name": "preis",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "minimum": 199,
              "maximum": 2000
            },
            "description": "Optional set price override in EUR"
          },
          {
            "name": "strom",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "minimum": 0.2,
              "maximum": 0.5
            },
            "description": "Optional electricity price override in EUR/kWh"
          }
        ],
        "responses": {
          "200": {
            "description": "Balcony solar purchase price, subsidy, effective price, yearly savings, payback, and ten-year savings"
          },
          "400": {
            "description": "Invalid price or electricity-price override"
          },
          "404": {
            "description": "City or system size not found"
          }
        }
      }
    },
    "/calculator/gmbh/results/": {
      "get": {
        "summary": "All GmbH founding-cost results",
        "operationId": "getGmbhResults",
        "description": "Founding-cost estimates for every supported city and contract type. Totals exclude statutory Stammkapital and annual IHK contributions.",
        "responses": {
          "200": {
            "description": "GmbH city and contract-type combinations"
          }
        }
      }
    },
    "/calculator/gmbh/results/{city}/{gesellschaftsvertrag}/": {
      "get": {
        "summary": "Single GmbH founding-cost result",
        "operationId": "getGmbhResult",
        "parameters": [
          {
            "name": "city",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "gesellschaftsvertrag",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "muster",
                "individuell"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gewerbeamt, notary, handelsregister, Stammkapital, processing, online, and IHK context"
          },
          "404": {
            "description": "City or contract type not found"
          }
        }
      }
    },
    "/calculator/sachkunde34a/results/": {
      "get": {
        "summary": "All Sachkunde 34a cost results",
        "operationId": "getSachkunde34aResults",
        "description": "Cost estimates for every supported city and the three Sachkunde preparation-cost formats.",
        "responses": {
          "200": {
            "description": "Sachkunde 34a city and course-format combinations"
          }
        }
      }
    },
    "/calculator/sachkunde34a/results/{city}/": {
      "get": {
        "summary": "Single Sachkunde 34a cost result",
        "operationId": "getSachkunde34aResult",
        "parameters": [
          {
            "name": "city",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "City slug or 5-digit PLZ for simple PLZ-prefix lookup"
          },
          {
            "name": "kursformat",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "guenstig",
                "median",
                "intensiv"
              ],
              "default": "median"
            },
            "description": "Preparation-cost estimate format"
          }
        ],
        "responses": {
          "200": {
            "description": "IHK exam fee, preparation estimate, total cost, and resolved IHK context"
          },
          "404": {
            "description": "City, PLZ prefix, or course format not found"
          }
        }
      }
    },
    "/calculator/aevo/results/": {
      "get": {
        "summary": "All AEVO cost results",
        "operationId": "getAevoResults",
        "description": "AEVO course, IHK, learning material, and total-cost estimates for every scraped city and course format. Cities with incomplete IHK fee data return partial estimates with null totals.",
        "responses": {
          "200": {
            "description": "AEVO city and course-format combinations"
          }
        }
      }
    },
    "/calculator/aevo/results/{city}/{kursformat}/": {
      "get": {
        "summary": "Single AEVO cost result",
        "operationId": "getAevoResult",
        "parameters": [
          {
            "name": "city",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kursformat",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "guenstig",
                "median",
                "intensiv"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "AEVO course, IHK, learning material, and total-cost estimate. Totals can be null when IHK fee data is incomplete."
          },
          "404": {
            "description": "City or course format not found"
          }
        }
      }
    },
    "/calculator/waermepumpe/results/": {
      "get": {
        "summary": "All heat pump subsidy results",
        "operationId": "getWaermepumpeResults",
        "description": "Heat pump grant, own-contribution, permit, and GEG deadline estimates for configured pump types, population classes, and bonus combinations.",
        "responses": {
          "200": {
            "description": "Heat pump subsidy combinations"
          }
        }
      }
    },
    "/calculator/waermepumpe/results/{pumpType}/{populationClass}/": {
      "get": {
        "summary": "Single heat pump subsidy result",
        "operationId": "getWaermepumpeResult",
        "parameters": [
          {
            "name": "pumpType",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "luft_wasser",
                "sole_wasser_erdkollektor",
                "sole_wasser_erdsonde",
                "wasser_wasser"
              ]
            }
          },
          {
            "name": "populationClass",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "over_100k",
                "under_100k",
                "heat_plan_designated"
              ]
            }
          },
          {
            "name": "kosten",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "minimum": 5000,
              "maximum": 60000
            },
            "description": "Optional total project cost in EUR. Values outside the configured range are clamped to the nearest supported calculator value."
          },
          {
            "name": "selbstnutzer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Whether the owner uses the home themselves"
          },
          {
            "name": "alteHeizung",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Whether a functioning old heating system is being replaced"
          },
          {
            "name": "einkommenUnter40000",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "Whether household income is at or below EUR 40,000"
          }
        ],
        "responses": {
          "200": {
            "description": "Grant, own contribution, permit path, GEG deadline, and bonus details"
          },
          "400": {
            "description": "Invalid non-numeric project cost"
          },
          "404": {
            "description": "Pump type or population class not found"
          }
        }
      }
    },
    "/calculator/kfz/results/": {
      "get": {
        "summary": "All vehicle registration results",
        "operationId": "getKfzResults",
        "description": "Vehicle registration fee, document, wait-time, authority, and i-Kfz estimates for every supported city and process.",
        "responses": {
          "200": {
            "description": "Vehicle registration city and process combinations"
          }
        }
      }
    },
    "/calculator/kfz/results/{city}/{vorgang}/": {
      "get": {
        "summary": "Single vehicle registration result",
        "operationId": "getKfzResult",
        "parameters": [
          {
            "name": "city",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Supported city slug, e.g. berlin or hamburg"
          },
          {
            "name": "vorgang",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "neuzulassung",
                "halterwechsel",
                "ummeldung",
                "abmeldung",
                "wiederzulassung"
              ]
            },
            "description": "Vehicle registration process"
          }
        ],
        "responses": {
          "200": {
            "description": "Vehicle registration fees, required documents, wait time, authority, and links"
          },
          "404": {
            "description": "City or process not found"
          }
        }
      }
    }
  }
}