{
  "openapi": "3.1.0",
  "info": {
    "title": "Overfit API for AI agents",
    "version": "1.0.0",
    "description": "Overfit (www.overfit.de) gives your user access to 190,000+ German public-tender notices (38,000+ open, as of 2026-10-05) and six free, keyless rule-engine endpoints for procurement law — EU threshold, deadlines, § 134 GWB standstill, procedure choice, UfAB bid scoring, working days — each answer citing §, date and source URL (GWB/VgV/VOB/A-EU/UVgO). MCP server: https://www.overfit.de/mcp · Full catalogue: https://www.overfit.de/agenten.md\n\nFree, no authentication required, GET only. Every calculator response carries `legal_basis`, `sources`, `as_of`, `links.human` and `next` (ready-made follow-up calls). Full documentation: https://www.overfit.de/agenten",
    "contact": {
      "email": "info@overfit.de",
      "url": "https://www.overfit.de/contact"
    },
    "termsOfService": "https://www.overfit.de/terms",
    "x-catalog-stand": "2026-10-05"
  },
  "servers": [
    {
      "url": "https://www.overfit.de",
      "description": "Overfit main site (tools / calculators)"
    }
  ],
  "tags": [
    {
      "name": "Overfit Vergabe",
      "description": "Over 190,000 German and EU public-tender notices (as of 2026-10-05: 38,000+ open, 68,938 awarded) — semantically searchable with AI summaries, deadlines, contracting authorities and geolocation. Free, no API key. Sources: EU TED, Bund, Länder, municipalities, BKM, Fraunhofer.",
      "externalDocs": {
        "url": "https://app.overfit.de/vergabe/"
      }
    },
    {
      "name": "Vergabe-Rechner",
      "description": "Six free JSON calculators replace manual procurement-law research: EU threshold (VgV/VOB/A-EU/SektVO/KonzVgV), tender and participation deadlines, § 134 GWB standstill, permitted procedure type, UfAB bid scoring and working days per federal state. Every answer cites the exact §, a verification date and a source URL — deterministic, no hallucination risk.",
      "externalDocs": {
        "url": "https://www.overfit.de/tools"
      }
    }
  ],
  "paths": {
    "/api/search": {
      "get": {
        "operationId": "vergabe_suche",
        "x-title-de": "Ausschreibungen semantisch suchen",
        "summary": "Semantic search over 106,000 German public-tender notices by natural language.",
        "description": "Returns up to 50 ranked tender notices matching a natural-language query, with AI summaries, CPV/NUTS codes, submission deadline, contracting authority and geo coordinates (Stand 05.10.2026: 106,000 notices in vector index). Use when the user wants to find tenders by topic, keyword or industry in German or English. Do not use for exact structured queries (use vergabe_liste instead) or proximity search without a Vergabe Premium account — anonymous sessions are limited to ~10 semantic queries per day per IP (429 with Retry-After). Key filter parameters: Bundesland, status, cpv, nuts, deadline_after/before, notice_type.\n\nExample user questions: \"Welche offenen Ausschreibungen gibt es für IT-Dienstleistungen in Schleswig-Holstein?\"; \"Suche Vergaben für Gebäudereinigung mit Frist nach Oktober 2026\"; \"Finde Bekanntmachungen für Straßenbau in Bayern\"; \"Gibt es aktuelle Ausschreibungen im Bereich Softwareentwicklung?\"; \"Zeig mir laufende Vergabeverfahren für medizinische Geräte\"",
        "tags": [
          "Overfit Vergabe"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Natural-language search query (German preferred), 1–500 chars.",
            "schema": {
              "type": "string",
              "example": "Reinigungsleistungen"
            }
          },
          {
            "name": "top_k",
            "in": "query",
            "required": false,
            "description": "Number of results to return (1–50).",
            "schema": {
              "type": "integer",
              "default": 10,
              "example": 10
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by notice status. Multiple values are supported by repeating the param. No default — all statuses included unless specified.",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "closed",
                "awarded",
                "cancelled",
                "unknown"
              ],
              "example": "open"
            }
          },
          {
            "name": "bundesland",
            "in": "query",
            "required": false,
            "description": "Exact German federal state name, e.g. 'Bayern', 'Schleswig-Holstein', 'Mecklenburg-Vorpommern'. Case-sensitive.",
            "schema": {
              "type": "string",
              "example": "Bayern"
            }
          },
          {
            "name": "cpv",
            "in": "query",
            "required": false,
            "description": "CPV code(s) to filter (OR logic). Repeat the param for multiple codes, e.g. cpv=72000000&cpv=72500000. Full 8-digit codes.",
            "schema": {
              "type": "string",
              "example": "72000000"
            }
          },
          {
            "name": "nuts",
            "in": "query",
            "required": false,
            "description": "NUTS region code(s) to filter (OR logic). Repeat for multiple. E.g. nuts=DEF (Schleswig-Holstein), nuts=DE21H (Landkreis München).",
            "schema": {
              "type": "string",
              "example": "DEF"
            }
          },
          {
            "name": "deadline_after",
            "in": "query",
            "required": false,
            "description": "Include only notices with submission_deadline >= this ISO date.",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-01"
            }
          },
          {
            "name": "deadline_before",
            "in": "query",
            "required": false,
            "description": "Include only notices with submission_deadline <= this ISO date.",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2027-01-01"
            }
          },
          {
            "name": "notice_type",
            "in": "query",
            "required": false,
            "description": "Filter by EU notice form type. Repeat for multiple. InvitationToTender = active tender; ContractAward = already awarded.",
            "schema": {
              "type": "string",
              "enum": [
                "InvitationToTender",
                "PriorInformation",
                "ContractAward"
              ],
              "example": "InvitationToTender"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Restrict to a specific source portal. bkm = Vergabe-Hub DE (national), ted = Vergabe-Europa (EU TED), bund = Vergabe-Bund (service.bund.de), bescha = Beschaffungsamt, fraunhofer = Fraunhofer, kommune = municipal.",
            "schema": {
              "type": "string",
              "enum": [
                "bkm",
                "ted",
                "bund",
                "bescha",
                "fraunhofer",
                "kommune"
              ],
              "example": "bkm"
            }
          },
          {
            "name": "include_dead",
            "in": "query",
            "required": false,
            "description": "Include notices whose original portal URL is unreachable (dead/soft_dead).",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "assistant_ready",
            "in": "query",
            "required": false,
            "description": "true = only notices where the document assistant is usable (open tender, deadline not expired, procurement documents on storage).",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Semantic search over 106,000 German public-tender notices by natural language.",
            "content": {
              "application/json": {
                "example": {
                  "query": "Reinigungsleistungen",
                  "model": "qwen3-embedding-4b",
                  "model_version": "2026-05-19-instruct",
                  "total_index_size": 106000,
                  "returned": 2,
                  "latency_ms": 1474,
                  "hits": [
                    {
                      "notice_id": 127478,
                      "score": 0.725,
                      "source": "bkm",
                      "source_display": "Vergabe-Hub DE",
                      "uid": "bkm:c5637fac-d4fd-442d-955d-391a4165841c",
                      "notice_type": "InvitationToTender",
                      "status": "open",
                      "practical_type": "tender",
                      "assistant_ready": false,
                      "title": "Ausschreibung Gebäudereinigung - Gemeinde Baierbrunn",
                      "authority": "Gemeinde Baierbrunn",
                      "one_line_value_prop": "Professionelle Unterhalts- und Grundreinigung für kommunale Gebäude.",
                      "summary_short": "Die Gemeinde Baierbrunn schreibt Gebäudereinigungsdienstleistungen aus.",
                      "cpv_codes": [
                        "90911200",
                        "90900000"
                      ],
                      "nuts_codes": [
                        "DE21H"
                      ],
                      "industry_tags": [
                        "Dienstleistung",
                        "Reinigung-Gebäude"
                      ],
                      "key_deliverables": [
                        "Unterhaltsreinigung für Gemeindegebäude",
                        "Grundreinigung für Gemeindegebäude"
                      ],
                      "submission_deadline": "2026-10-13T08:00:00",
                      "publication_date": "2026-09-08",
                      "detail_url": "https://oeffentlichevergabe.de/ui/de/search/details?noticeId=c5637fac-d4fd-442d-955d-391a4165841c",
                      "landkreis": "Landkreis München",
                      "bundesland": "Bayern",
                      "lat": 48.014685,
                      "lon": 11.480136,
                      "semantic_score": 0.697,
                      "completeness": 0.85
                    },
                    {
                      "notice_id": 136258,
                      "score": 0.706,
                      "source": "bund",
                      "source_display": "Vergabe-Bund",
                      "uid": "bund:eVergabe/888110",
                      "notice_type": "InvitationToTender",
                      "status": "open",
                      "practical_type": "tender",
                      "assistant_ready": false,
                      "title": "Offenes Verfahren (EU-weit) zur Vergabe von Gebäudereinigungsleistungen in München und Garching",
                      "authority": "Bundesanstalt für Immobilienaufgaben Verdingungsstelle",
                      "one_line_value_prop": "Regelmäßige Unterhalts- und Glasreinigung für Bundesliegenschaften.",
                      "summary_short": "Vergabe von Gebäudereinigungsleistungen für Liegenschaften in München und Garching.",
                      "cpv_codes": [
                        "90911200",
                        "90911300"
                      ],
                      "nuts_codes": null,
                      "submission_deadline": "2026-10-21T00:00:00",
                      "publication_date": null,
                      "detail_url": "https://www.service.bund.de/IMPORTE/Ausschreibungen/eVergabe/888110.html",
                      "landkreis": "Kreisfreie Stadt München",
                      "bundesland": "Bayern"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        },
        "servers": [
          {
            "url": "https://app.overfit.de/vergabe"
          }
        ]
      }
    },
    "/api/list": {
      "get": {
        "operationId": "vergabe_liste",
        "x-title-de": "Ausschreibungen filtern und auflisten",
        "summary": "Paginated structured list of tender notices with SQL filters, no embedding.",
        "description": "Returns a paginated list of tender notices filtered by status, Landkreis, CPV prefix, sector, authority, urgency and more — with optional keyword fulltext search (not semantic). Use when the user wants a structured listing: all open IT tenders (cpv_prefix=72), all urgent tenders in a Landkreis, all recent publications sorted by date. Do not use for natural-language topic matching (use vergabe_suche for that) or for pagination beyond offset 2000 without a logged-in account (403). Rate limit: 40 requests / 10 min, 300 / day per IP.\n\nExample user questions: \"Liste alle offenen Ausschreibungen mit Frist in den nächsten 14 Tagen\"; \"Zeig alle Vergaben aus dem Landkreis München\"; \"Welche Ausschreibungen wurden zuletzt veröffentlicht?\"; \"Alle offenen IT-Vergaben (CPV 72) sortiert nach Veröffentlichungsdatum\"; \"Liste alle Bekanntmachungen der Bundesagentur für Arbeit\"",
        "tags": [
          "Overfit Vergabe"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Notice status filter. Default: 'open' (also excludes expired deadlines).",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "closed",
                "awarded",
                "cancelled",
                "unknown",
                "non_tender",
                "all"
              ],
              "default": "open"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Keyword fulltext search over scope/purpose text and AI summaries. Not semantic — use /api/search for natural-language intent matching.",
            "schema": {
              "type": "string",
              "example": "Reinigung"
            }
          },
          {
            "name": "order_by",
            "in": "query",
            "required": false,
            "description": "'score' requires q; 'distance_asc' requires near (premium). Default: deadline_asc (soonest deadline first, nulls last).",
            "schema": {
              "type": "string",
              "enum": [
                "deadline_asc",
                "publication_desc",
                "score",
                "distance_asc"
              ],
              "default": "deadline_asc"
            }
          },
          {
            "name": "top_k",
            "in": "query",
            "required": false,
            "description": "Page size (1–2000).",
            "schema": {
              "type": "integer",
              "default": 200,
              "example": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Pagination offset. Anonymous callers: capped at 2000 (403 if exceeded).",
            "schema": {
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "landkreis",
            "in": "query",
            "required": false,
            "description": "Exact Landkreis/city name as returned by /api/options/landkreise, e.g. 'Kreisfreie Stadt München', 'Berlin, Stadt'.",
            "schema": {
              "type": "string",
              "example": "Kreisfreie Stadt München"
            }
          },
          {
            "name": "sector",
            "in": "query",
            "required": false,
            "description": "Facet sector value as returned by /api/options/sectors, e.g. 'Bauleistung'.",
            "schema": {
              "type": "string",
              "example": "Bauleistung"
            }
          },
          {
            "name": "cpv_prefix",
            "in": "query",
            "required": false,
            "description": "CPV code prefix (leading digits), e.g. '72' for all IT services, '45' for construction. Matches any CPV code starting with this string.",
            "schema": {
              "type": "string",
              "example": "72"
            }
          },
          {
            "name": "notice_type",
            "in": "query",
            "required": false,
            "description": "EU notice form type.",
            "schema": {
              "type": "string",
              "enum": [
                "InvitationToTender",
                "PriorInformation",
                "ContractAward"
              ],
              "example": "InvitationToTender"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Restrict to a specific source portal. See /api/sources for current counts.",
            "schema": {
              "type": "string",
              "enum": [
                "bkm",
                "ted",
                "bund",
                "bescha",
                "fraunhofer",
                "kommune"
              ],
              "example": "bund"
            }
          },
          {
            "name": "legal_basis",
            "in": "query",
            "required": false,
            "description": "Legal basis code, e.g. 'vgv', 'UVgO', 'sektvo', 'VOB'. See /api/options/legal-bases for full list.",
            "schema": {
              "type": "string",
              "example": "vgv"
            }
          },
          {
            "name": "authority_id",
            "in": "query",
            "required": false,
            "description": "Numeric authority ID from /api/options/authorities.",
            "schema": {
              "type": "integer",
              "example": 2999
            }
          },
          {
            "name": "urgent",
            "in": "query",
            "required": false,
            "description": "Only notices with submission_deadline within the next 14 days.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "include_dead",
            "in": "query",
            "required": false,
            "description": "Include notices with dead/soft_dead portal URL.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "assistant_ready",
            "in": "query",
            "required": false,
            "description": "true = only notices with document assistant available.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "bbox",
            "in": "query",
            "required": false,
            "description": "Bounding-box geo filter: 'lat_min,lat_max,lon_min,lon_max'.",
            "schema": {
              "type": "string",
              "example": "47.5,48.5,11.0,12.5"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated structured list of tender notices with SQL filters, no embedding.",
            "content": {
              "application/json": {
                "example": {
                  "total": 896,
                  "offset": 0,
                  "returned": 2,
                  "latency_ms": 505.3,
                  "hits": [
                    {
                      "id": 582624,
                      "uid": "ted:683444-2026",
                      "source": "ted",
                      "source_display": "Vergabe-Europa",
                      "notice_type": "InvitationToTender",
                      "status": "open",
                      "practical_type": "participation_call",
                      "title": "Deutschland – Software-Implementierung – Lieferung, Implementierung und Betrieb eines Systems für Mobilfunk- und Datenkartenmanagement",
                      "authority_name": "Oldenburgisch-Ostfriesischer Wasserverband",
                      "publication_date": "2026-10-05",
                      "submission_deadline": "2026-11-03T09:00:00",
                      "cpv_codes": [
                        "72263000",
                        "72260000"
                      ],
                      "nuts_codes": [
                        "DE935",
                        "DE94G"
                      ],
                      "detail_url": "https://ted.europa.eu/de/notice/-/detail/683444-2026",
                      "contract_type": "services",
                      "one_line_value_prop": "Zentrales Managementsystem für Mobilfunkverträge und SIM-/Datenkarten.",
                      "summary_short": "Der Oldenburgisch-Ostfriesische Wasserverband vergibt die Lieferung und Betrieb eines Systems für Mobilfunk- und Datenkartenmanagement."
                    },
                    {
                      "id": 582561,
                      "uid": "ted:683036-2026",
                      "source": "ted",
                      "source_display": "Vergabe-Europa",
                      "notice_type": "InvitationToTender",
                      "status": "open",
                      "practical_type": "tender",
                      "title": "Deutschland – Kontroll- und Überwachungsleistungen – Messdienstleistungen für die Kanalnetz-Messkampagne 2027–2028",
                      "authority_name": "Magistrat der Stadt Kassel",
                      "publication_date": "2026-10-05",
                      "submission_deadline": "2026-11-02T08:00:00",
                      "cpv_codes": [
                        "71700000",
                        "38421000",
                        "72300000"
                      ],
                      "detail_url": "https://ted.europa.eu/de/notice/-/detail/683036-2026",
                      "contract_type": "services"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        },
        "servers": [
          {
            "url": "https://app.overfit.de/vergabe"
          }
        ]
      }
    },
    "/api/notice/by-uid/{uid}": {
      "get": {
        "operationId": "vergabe_bekanntmachung",
        "x-title-de": "Ausschreibung im Detail",
        "summary": "Fetch full metadata for one notice by its stable cross-portal UID.",
        "description": "Returns full detail for one notice: title, authority (name, address, email, phone, website), all dates, CPV/NUTS codes, AI summaries (short/medium/long/plain-language), key deliverables, risk flags, eligibility summary and the original portal URL. Use after vergabe_suche or vergabe_liste to retrieve complete information for a specific notice; the uid field from those results is the required input (format: source:id, e.g. bkm:675fa09d-…, ted:427373-2026, bund:eVergabe/888110). Do not use to retrieve procurement documents (files) — use /api/notice/{id}/full for sections and document list. Rate limit: 30 requests / 10 min, 200 / day per IP.\n\nExample user questions: \"Zeig mir Details zur Ausschreibung bkm:675fa09d-5152-46c5-9967-ed104d16276b\"; \"Was sind Frist und Vergabestelle für diese Bekanntmachung?\"; \"Welche Unterlagen und Fristen hat die Ausschreibung XYZ?\"; \"Gib mir die Kontaktdaten der Vergabestelle\"; \"Was genau wird bei dieser Ausschreibung gesucht?\"",
        "tags": [
          "Overfit Vergabe"
        ],
        "parameters": [
          {
            "name": "uid",
            "in": "path",
            "required": true,
            "description": "Stable cross-portal UID in the form 'source:id'. Taken directly from the uid field in /api/search or /api/list responses. Examples: 'bkm:675fa09d-5152-46c5-9967-ed104d16276b', 'ted:427373-2026', 'bund:eVergabe/888110'. URL-encode the colon if needed.",
            "schema": {
              "type": "string",
              "example": "bkm:675fa09d-5152-46c5-9967-ed104d16276b"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch full metadata for one notice by its stable cross-portal UID.",
            "content": {
              "application/json": {
                "example": {
                  "notice_id": 171884,
                  "uid": "bkm:675fa09d-5152-46c5-9967-ed104d16276b",
                  "source": "bkm",
                  "source_display": "Vergabe-Hub DE",
                  "notice_type": "InvitationToTender",
                  "legal_basis": "32014L0024",
                  "procedure_type": "neg-w-call",
                  "status": "open",
                  "practical_type": "participation_call",
                  "title": "Rahmenvereinbarung Unterstützung im Themenbereich IT-Security",
                  "publication_date": "2026-09-27",
                  "submission_deadline": "2026-10-12T08:00:00",
                  "cpv_codes": [
                    "72000000"
                  ],
                  "nuts_codes": [
                    "DEF02"
                  ],
                  "detail_url": "https://oeffentlichevergabe.de/ui/de/search/details?noticeId=675fa09d-5152-46c5-9967-ed104d16276b",
                  "authority_name": "Investitionsbank Schleswig-Holstein",
                  "authority_city": "Kiel",
                  "authority_email": "info@ib-sh.de",
                  "authority_website": "https://www.ib-sh.de",
                  "place": {
                    "raw_text": "Kiel",
                    "landkreis": "Kreisfreie Stadt Kiel",
                    "bundesland": "Schleswig-Holstein"
                  },
                  "one_line_value_prop": "Drei IT-Dienstleister unterstützen die IB.SH bei IT-Security-Aufgaben durch flexible Mini-Wettbewerbe.",
                  "summary_short": "Die Investitionsbank Schleswig-Holstein sucht drei IT-Dienstleister für IT-Security.",
                  "summary_medium": "Die IB.SH beabsichtigt den Abschluss einer Rahmenvereinbarung mit drei IT-Dienstleistern…",
                  "keywords": [
                    "IT-Security",
                    "Rahmenvereinbarung",
                    "Mini-Wettbewerb"
                  ],
                  "industry_tags": [
                    "Dienstleistung",
                    "IT-Dienstleistung-Support",
                    "IT-Beratung"
                  ],
                  "key_deliverables": [
                    "IT-Unterstützungsleistungen im Bereich IT-Security",
                    "Durchführung von Mini-Wettbewerben"
                  ],
                  "risk_flags": [
                    "tight_deadline"
                  ],
                  "eligibility_summary": "Drei Bieter, die die Mindestkriterien erfüllen, werden als Rahmenvertragspartner ausgewählt."
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        },
        "servers": [
          {
            "url": "https://app.overfit.de/vergabe"
          }
        ]
      }
    },
    "/api/notice/{id}/full": {
      "get": {
        "operationId": "vergabe_bekanntmachung_voll",
        "x-title-de": "Ausschreibung komplett mit Unterlagen",
        "summary": "Full notice bundle: all metadata + structured sections + Q&A + facets + documents list.",
        "description": "Use when the user needs the complete picture of one tender: all fields of /api/notice/by-uid plus the AI-structured sections (description, criteria, …), a Q&A list (e.g. 'Is a security clearance required?'), topic facets, and a list of available procurement documents (filenames, sizes, MIME types, download status). Note: returns the document list metadata only — not the file content itself. Input is the numeric notice_id from search/list results (field 'notice_id' or 'id'). Rate-limited at 30 requests/10 min and 200/day per IP (same bucket as notice detail).\n\nExample user questions: \"Welche Unterlagen gibt es für diese Ausschreibung?\"; \"Gibt es eine strukturierte Zusammenfassung der Vergabeunterlagen?\"; \"Welche Fragen und Antworten sind zu dieser Ausschreibung bekannt?\"",
        "tags": [
          "Overfit Vergabe"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Numeric notice ID from the 'notice_id' or 'id' field in /api/search or /api/list responses.",
            "schema": {
              "type": "integer",
              "example": 171884
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Full notice bundle: all metadata + structured sections + Q&A + facets + documents list.",
            "content": {
              "application/json": {
                "example": {
                  "notice_id": 171884,
                  "uid": "bkm:675fa09d-5152-46c5-9967-ed104d16276b",
                  "title": "Rahmenvereinbarung Unterstützung im Themenbereich IT-Security",
                  "status": "open",
                  "submission_deadline": "2026-10-12T08:00:00",
                  "summary_short": "Die Investitionsbank Schleswig-Holstein sucht drei IT-Dienstleister für IT-Security.",
                  "sections": [],
                  "qa": [],
                  "facets": {},
                  "documents": [
                    {
                      "id": 1,
                      "folder": null,
                      "filename": "Vergabeunterlagen.pdf",
                      "size_bytes": 204800,
                      "mime": "application/pdf",
                      "download_status": "ok"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        },
        "servers": [
          {
            "url": "https://app.overfit.de/vergabe"
          }
        ]
      }
    },
    "/api/stats": {
      "get": {
        "operationId": "vergabe_statistik",
        "x-title-de": "Vergabe-Statistik",
        "summary": "Get current index size and live tender counts (open, urgent, awarded, total).",
        "description": "Returns live counts of open, urgent (deadline ≤ 14 days), awarded and total notices plus URL health distribution and semantic model name (Stand: live). Use to give the user a current overview of database size or to verify the index is reachable before making search calls. No parameters, no rate limit. Key output fields: open_count, urgent_count, awarded_count, total_count, index_size.\n\nExample user questions: \"Wie viele Ausschreibungen sind aktuell offen?\"; \"Wie aktuell ist die Vergabe-Datenbank?\"; \"Gibt es dringende Ausschreibungen mit Frist in 14 Tagen?\"",
        "tags": [
          "Overfit Vergabe"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Get current index size and live tender counts (open, urgent, awarded, total).",
            "content": {
              "application/json": {
                "example": {
                  "model": "qwen3-embedding-4b",
                  "model_version": "2026-05-19-instruct",
                  "index_size": 106000,
                  "open_count": 38766,
                  "open_reachable": 36595,
                  "urgent_count": 17489,
                  "open_stale_count": 883,
                  "awarded_count": 68938,
                  "total_count": 190366,
                  "url_health": {
                    "alive": 84279,
                    "dead": 43945,
                    "soft_dead": 4,
                    "unchecked": 50562
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        },
        "servers": [
          {
            "url": "https://app.overfit.de/vergabe"
          }
        ]
      }
    },
    "/api/sources": {
      "get": {
        "operationId": "vergabe_quellen",
        "x-title-de": "Vergabe-Quellen",
        "summary": "Per-source notice counts broken down by status (open, closed, awarded, etc.).",
        "description": "Use to explain database coverage or to verify whether a specific portal (e.g. TED EU, Vergabe-Bund) is included and how many notices it contributes. Counts match /api/list exactly (same visibility gate, same stale-deadline exclusion). No rate limit. One optional parameter.\n\nExample user questions: \"Welche Vergabeportale sind in der Suche enthalten?\"; \"Wie viele EU-Ausschreibungen sind verfügbar?\"; \"Woher kommen die Daten in der Vergabe-Suche?\"",
        "tags": [
          "Overfit Vergabe"
        ],
        "parameters": [
          {
            "name": "include_dead",
            "in": "query",
            "required": false,
            "description": "Include notices with dead portal URLs in the counts.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Per-source notice counts broken down by status (open, closed, awarded, etc.).",
            "content": {
              "application/json": {
                "example": {
                  "bkm": {
                    "open": 13398,
                    "closed": 16040,
                    "awarded": 51
                  },
                  "ted": {
                    "open": 6247,
                    "closed": 16061,
                    "awarded": 2
                  },
                  "bund": {
                    "open": 5004,
                    "closed": 9416,
                    "awarded": 2,
                    "unknown": 393
                  },
                  "bescha": {
                    "open": 1071,
                    "closed": 925
                  },
                  "fraunhofer": {
                    "open": 82,
                    "closed": 207,
                    "awarded": 128
                  },
                  "kommune": {
                    "open": 73,
                    "closed": 35,
                    "awarded": 1287,
                    "cancelled": 9
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        },
        "servers": [
          {
            "url": "https://app.overfit.de/vergabe"
          }
        ]
      }
    },
    "/api/v1/schwellenwert": {
      "get": {
        "operationId": "vergabe_schwellenwert_pruefen",
        "x-title-de": "EU-Schwellenwert prüfen",
        "summary": "Check contract value against EU procurement threshold (VgV/VOB/A-EU).",
        "description": "Returns the applicable EU threshold, the procurement regime (VgV, VOB/A-EU, SektVO, KonzVgV) and — if below threshold — sub-threshold limits for the federal government and Mecklenburg-Vorpommern (Art. 4 RL 2014/24/EU; thresholds valid 2026-01-01 to 2027-12-31). Use when the user asks whether a contract requires EU-wide publication or stays within national sub-threshold rules. Do not use to determine which procedure type applies (use verfahrenswahl_ermitteln for that). Key output fields: oberschwellig (boolean), schwelle_eur, regime, rechtsgrundlage, gueltigkeit.\n\nExample user questions: \"Liegt mein Auftrag über dem EU-Schwellenwert?\"; \"Muss ich europaweit ausschreiben?\"; \"Wie hoch ist der Schwellenwert für Liefer- und Dienstleistungen?\"; \"Ab welchem Betrag gilt die VgV?\"; \"Unterschwellenvergabe oder EU-Vergabe?\"",
        "tags": [
          "Vergabe-Rechner"
        ],
        "parameters": [
          {
            "name": "auftraggeber",
            "in": "query",
            "required": true,
            "description": "Type of contracting authority: bund=federal ministry, sonstige=state/municipality/other public body, sektoren=utilities (energy/water/transport), konzession=concession grantor.",
            "schema": {
              "type": "string",
              "enum": [
                "bund",
                "sonstige",
                "sektoren",
                "konzession"
              ],
              "example": "sonstige"
            }
          },
          {
            "name": "leistung",
            "in": "query",
            "required": true,
            "description": "Type of service: bau=construction, liefer=supply/goods, dienst=services, sozial=social and other special services.",
            "schema": {
              "type": "string",
              "enum": [
                "bau",
                "liefer",
                "dienst",
                "sozial"
              ],
              "example": "dienst"
            }
          },
          {
            "name": "wert",
            "in": "query",
            "required": true,
            "description": "Estimated contract value (net EUR). Accepts German thousands separator: 250.000 or decimal comma 250.000,50.",
            "schema": {
              "type": "number",
              "example": "250000"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Check contract value against EU procurement threshold (VgV/VOB/A-EU).",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "tool": "vergabe_schwellenwert_pruefen",
                  "input": {
                    "auftraggeber": "sonstige",
                    "leistung": "dienst",
                    "wert": 250000
                  },
                  "result": {
                    "auftraggeber": "sonstige",
                    "auftraggeber_label": "Land, Kommune, sonstiger öffentlicher Auftraggeber",
                    "leistung": "dienst",
                    "leistung_label": "Dienstleistung",
                    "wert_eur": 250000,
                    "schwelle_eur": 216000,
                    "oberschwellig": true,
                    "regime": "VgV",
                    "rechtsgrundlage": "Art. 4 lit. c RL 2014/24/EU",
                    "gueltigkeit": {
                      "von": "2026-01-01",
                      "bis": "2027-12-31"
                    }
                  },
                  "as_of": "2026-01-01"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        }
      }
    },
    "/api/v1/fristen": {
      "get": {
        "operationId": "vergabe_fristen_berechnen",
        "x-title-de": "Vergabefristen berechnen",
        "summary": "Calculate tender and participation deadlines from a notice dispatch date.",
        "description": "Returns the effective end date for the submission or participation deadline (shifted to next working day per VO 1182/71) with per-step legal reasoning for each reduction applied — electronic submission, prior information notice, urgency (§ 15–16 VgV; § 10a–10b VOB/A EU; Stand 2026-07-14). Use when the user asks on which date a submission deadline falls or whether the minimum period can be shortened. Works for VgV (services/supplies) and VOB/A Abschnitt 2 EU (construction) procedures. Do not use to compute the § 134 GWB standstill period after award (use vergabe_wartefrist for that).\n\nExample user questions: \"Bis wann müssen Angebote eingehen?\"; \"Wie lange ist die Angebotsfrist bei einem offenen Verfahren nach VgV?\"; \"Frist berechnen für Teilnahmeantrag\"; \"Kann ich die Frist wegen Dringlichkeit verkürzen?\"; \"Wann endet die Angebotsfrist wenn ich heute veröffentliche?\"",
        "tags": [
          "Vergabe-Rechner"
        ],
        "parameters": [
          {
            "name": "absendung",
            "in": "query",
            "required": true,
            "description": "Date the contract notice is dispatched (ISO 2026-10-05 or German 05.10.2026). Day 0 — not counted towards the deadline.",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-05"
            }
          },
          {
            "name": "regelwerk",
            "in": "query",
            "required": true,
            "description": "Legal framework: vgv=Vergabeverordnung (services/supplies), voba=VOB/A Abschnitt 2 EU (construction).",
            "schema": {
              "type": "string",
              "enum": [
                "vgv",
                "voba"
              ],
              "example": "vgv"
            }
          },
          {
            "name": "verfahren",
            "in": "query",
            "required": true,
            "description": "Procedure type. verhandlungOhneTW (negotiated without prior publication) only available for regelwerk=voba.",
            "schema": {
              "type": "string",
              "enum": [
                "offen",
                "nichtoffen",
                "verhandlung",
                "verhandlungOhneTW"
              ],
              "example": "offen"
            }
          },
          {
            "name": "elektronisch",
            "in": "query",
            "required": false,
            "description": "Electronic tender submission available (reduces deadline by 5 days where permitted). Default: true.",
            "schema": {
              "type": "boolean",
              "default": true,
              "example": "true"
            }
          },
          {
            "name": "vorinformation",
            "in": "query",
            "required": false,
            "description": "Prior information notice published at least 35 days before (allows shorter deadlines). Default: false.",
            "schema": {
              "type": "boolean",
              "default": false,
              "example": "false"
            }
          },
          {
            "name": "dringlichkeit",
            "in": "query",
            "required": false,
            "description": "Duly substantiated urgency applies (overrides other reductions, sets minimum deadline). Default: false.",
            "schema": {
              "type": "boolean",
              "default": false,
              "example": "false"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Calculate tender and participation deadlines from a notice dispatch date.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "tool": "vergabe_fristen_berechnen",
                  "input": {
                    "absendung": "2026-10-05",
                    "regelwerk": "vgv",
                    "verfahren": "offen",
                    "elektronisch": true,
                    "vorinformation": false,
                    "dringlichkeit": false
                  },
                  "result": {
                    "regelwerk": "vgv",
                    "verfahren": "offen",
                    "verfahren_label": "Offenes Verfahren",
                    "absendung_iso": "2026-10-05",
                    "angebotsfrist": {
                      "tage": 30,
                      "ende_iso": "2026-11-04",
                      "ende_de": "04.11.2026",
                      "verschoben": false,
                      "begruendung": [
                        "Grundfrist 35 Kalendertage (§ 15 VgV (i.V.m. § 38 Abs. 3 VgV))",
                        "Elektronische Angebotsabgabe: Kürzung um 5 Tage"
                      ],
                      "paragraf": "§ 15 VgV (i.V.m. § 38 Abs. 3 VgV)"
                    },
                    "teilnahmefrist": null
                  },
                  "as_of": "2026-07-14"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        }
      }
    },
    "/api/v1/wartefrist": {
      "get": {
        "operationId": "vergabe_wartefrist",
        "x-title-de": "Wartefrist nach § 134 GWB",
        "summary": "Calculate § 134 GWB standstill period before contract award.",
        "description": "Returns both interpretations of the § 134 GWB standstill: the strict end date (no weekend shift, per VK Bund) and the conservative one (shifted to next working day, per OLG Bremen) — electronic dispatch 10 days, postal 15 days (Stand 2026-07-14). Use when the user asks on which date they may award a contract after informing unsuccessful bidders. The BGH has not resolved the weekend-shift question; present the conservative date as the safer choice. Do not use to compute tender or participation deadlines (use vergabe_fristen_berechnen for that).\n\nExample user questions: \"Wann endet die Wartefrist nach § 134 GWB?\"; \"Ab wann darf ich den Zuschlag erteilen?\"; \"Wie lange muss ich nach der Bieterinformation warten?\"; \"10 Tage Wartefrist — wann ist das genau?\"",
        "tags": [
          "Vergabe-Rechner"
        ],
        "parameters": [
          {
            "name": "absendung",
            "in": "query",
            "required": true,
            "description": "Date the bidder information was dispatched (ISO or German format).",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-05"
            }
          },
          {
            "name": "elektronisch",
            "in": "query",
            "required": false,
            "description": "Electronic or fax dispatch (10 days); false = postal (15 days). Default: true.",
            "schema": {
              "type": "boolean",
              "default": true,
              "example": "true"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Calculate § 134 GWB standstill period before contract award.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "tool": "vergabe_wartefrist",
                  "input": {
                    "absendung": "2026-10-05",
                    "elektronisch": true
                  },
                  "result": {
                    "absendung_iso": "2026-10-05",
                    "elektronisch": true,
                    "tage": 10,
                    "fristende_iso": "2026-10-15",
                    "fristende_de": "15.10.2026",
                    "zuschlag_streng_iso": "2026-10-16",
                    "zuschlag_streng_de": "16.10.2026",
                    "zuschlag_konservativ_iso": "2026-10-16",
                    "zuschlag_konservativ_de": "16.10.2026",
                    "streitig": false,
                    "paragraf": "§ 134 Abs. 2 GWB"
                  },
                  "as_of": "2026-07-14"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        }
      }
    },
    "/api/v1/werktage": {
      "get": {
        "operationId": "werktage_berechnen",
        "x-title-de": "Werktage berechnen",
        "summary": "Count or add working days by German federal state and holiday set.",
        "description": "Returns a working-day count or a target date for any of the 16 German federal states, using the complete holiday set for that state (Gauß Easter formula; Stand 2026-08-15). Two modes: add (start + n working days → end date) and count (date range → working-day count). Use when the user asks how many working days lie between two dates or on which date a deadline falls after n working days. Do not use for procurement-law deadlines — use vergabe_fristen_berechnen, which applies calendar-day counting under VO 1182/71.\n\nExample user questions: \"Wie viele Werktage liegen zwischen zwei Terminen?\"; \"Wann ist der 10. Werktag nach dem 05.10.2026 in Bayern?\"; \"Arbeitstage zwischen zwei Daten in NRW\"; \"Frist in Werktagen berechnen\"; \"Wie viele Arbeitstage hat der Oktober in Berlin?\"",
        "tags": [
          "Vergabe-Rechner"
        ],
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "add: start + n working days → end date. count: count working days between von and bis.",
            "schema": {
              "type": "string",
              "enum": [
                "add",
                "count"
              ],
              "default": "add",
              "example": "add"
            }
          },
          {
            "name": "land",
            "in": "query",
            "required": true,
            "description": "2-letter German federal state code: BW=Baden-Württemberg, BY=Bayern, BE=Berlin, BB=Brandenburg, HB=Bremen, HH=Hamburg, HE=Hessen, MV=Mecklenburg-Vorpommern, NI=Niedersachsen, NW=Nordrhein-Westfalen, RP=Rheinland-Pfalz, SL=Saarland, SN=Sachsen, ST=Sachsen-Anhalt, SH=Schleswig-Holstein, TH=Thüringen.",
            "schema": {
              "type": "string",
              "enum": [
                "BW",
                "BY",
                "BE",
                "BB",
                "HB",
                "HH",
                "HE",
                "MV",
                "NI",
                "NW",
                "RP",
                "SL",
                "SN",
                "ST",
                "SH",
                "TH"
              ],
              "example": "BE"
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "Start date for mode=add (ISO or German format).",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-05"
            }
          },
          {
            "name": "tage",
            "in": "query",
            "required": false,
            "description": "Number of working days to add (positive = forward, negative = backward) for mode=add.",
            "schema": {
              "type": "integer",
              "example": 10
            }
          },
          {
            "name": "von",
            "in": "query",
            "required": false,
            "description": "Start of date range for mode=count.",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-05"
            }
          },
          {
            "name": "bis",
            "in": "query",
            "required": false,
            "description": "End of date range for mode=count (inclusive).",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-31"
            }
          },
          {
            "name": "samstag",
            "in": "query",
            "required": false,
            "description": "Count Saturday as a working day (for trade-law or rent-law deadlines). Default: false.",
            "schema": {
              "type": "boolean",
              "default": false,
              "example": "false"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Count or add working days by German federal state and holiday set.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "tool": "werktage_berechnen",
                  "input": {
                    "mode": "add",
                    "start": "2026-10-05",
                    "tage": 10,
                    "land": "BE",
                    "samstag": false
                  },
                  "result": {
                    "mode": "add",
                    "start_iso": "2026-10-05",
                    "tage": 10,
                    "land": "BE",
                    "land_name": "Berlin",
                    "samstag_zaehlt": false,
                    "ende_iso": "2026-10-19",
                    "ende_de": "19.10.2026"
                  },
                  "as_of": "2026-08-15"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        }
      }
    },
    "/api/v1/feiertage": {
      "get": {
        "operationId": "feiertage_liste",
        "x-title-de": "Feiertage je Bundesland",
        "summary": "List public holidays for a year and German federal state.",
        "description": "Returns the complete public holiday list for a year — nationwide or for one of the 16 German federal states including state-specific holidays (Stand 2026-08-15). Use when the user asks which holidays fall in a year in a specific state. Do not use to count working days between dates (use werktage_berechnen for that). Key output fields: datum (ISO), name (German), bundesweit (boolean).\n\nExample user questions: \"Welche Feiertage gibt es 2026 in Bayern?\"; \"Feiertage in Berlin auflisten\"; \"Welche gesetzlichen Feiertage hat Sachsen?\"; \"Gibt es im Oktober 2026 Feiertage in NRW?\"",
        "tags": [
          "Vergabe-Rechner"
        ],
        "parameters": [
          {
            "name": "jahr",
            "in": "query",
            "required": true,
            "description": "Year (2020–2040).",
            "schema": {
              "type": "integer",
              "example": 2026
            }
          },
          {
            "name": "land",
            "in": "query",
            "required": false,
            "description": "2-letter federal state code. Omit for nationwide-only holidays.",
            "schema": {
              "type": "string",
              "enum": [
                "BW",
                "BY",
                "BE",
                "BB",
                "HB",
                "HH",
                "HE",
                "MV",
                "NI",
                "NW",
                "RP",
                "SL",
                "SN",
                "ST",
                "SH",
                "TH"
              ],
              "example": "BY"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List public holidays for a year and German federal state.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "tool": "feiertage_liste",
                  "input": {
                    "jahr": 2026,
                    "land": "BY"
                  },
                  "result": {
                    "jahr": 2026,
                    "land": "BY",
                    "land_name": "Bayern",
                    "anzahl": 12,
                    "feiertage": [
                      {
                        "datum": "2026-01-01",
                        "name": "Neujahr",
                        "bundesweit": true
                      },
                      {
                        "datum": "2026-01-06",
                        "name": "Heilige Drei Könige",
                        "bundesweit": false
                      },
                      {
                        "datum": "2026-04-03",
                        "name": "Karfreitag",
                        "bundesweit": true
                      }
                    ]
                  },
                  "as_of": "2026-08-15"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        }
      }
    },
    "/api/v1/verfahrenswahl": {
      "get": {
        "operationId": "verfahrenswahl_ermitteln",
        "x-title-de": "Vergabeverfahren ermitteln",
        "summary": "Determine permitted procurement procedures for a contract value and type.",
        "description": "Returns a list of procurement procedures with status frei (available), voraussetzung (available under conditions), or nein (unavailable) and the legal basis for each (§ GWB / § VgV / UVgO; Stand 2026-08-15). Use when the user asks which procedure type is required or permissible for a given contract value, authority type and service category. Takes into account EU thresholds, sub-threshold regime (federal or state), and special-case flags (sole source, urgency, prior call with no tenders). Do not use to compute deadlines or evaluate bids (use vergabe_fristen_berechnen and wertungsmatrix_berechnen for those).\n\nExample user questions: \"Welche Verfahrensart darf ich wählen?\"; \"Ist ein Verhandlungsverfahren zulässig?\"; \"Darf ich freihändig vergeben?\"; \"Wann ist ein Direktauftrag erlaubt?\"; \"Offenes oder nicht offenes Verfahren?\"",
        "tags": [
          "Vergabe-Rechner"
        ],
        "parameters": [
          {
            "name": "auftraggeber",
            "in": "query",
            "required": true,
            "description": "Type of contracting authority (same as in schwellenwert).",
            "schema": {
              "type": "string",
              "enum": [
                "bund",
                "sonstige",
                "sektoren",
                "konzession"
              ],
              "example": "sonstige"
            }
          },
          {
            "name": "leistungsart",
            "in": "query",
            "required": true,
            "description": "Type of service (same as in schwellenwert).",
            "schema": {
              "type": "string",
              "enum": [
                "bau",
                "liefer",
                "dienst",
                "sozial"
              ],
              "example": "dienst"
            }
          },
          {
            "name": "wert",
            "in": "query",
            "required": true,
            "description": "Estimated contract value (net EUR).",
            "schema": {
              "type": "number",
              "example": "250000"
            }
          },
          {
            "name": "regelwerk",
            "in": "query",
            "required": false,
            "description": "Sub-threshold framework: mv=Mecklenburg-Vorpommern, bund=federal, anders=other state (shows generic guidance). Only relevant if below EU threshold.",
            "schema": {
              "type": "string",
              "enum": [
                "mv",
                "bund",
                "anders"
              ],
              "default": "anders",
              "example": "bund"
            }
          },
          {
            "name": "alleinstellung",
            "in": "query",
            "required": false,
            "description": "Only one company can provide the service (sole source / exclusive rights).",
            "schema": {
              "type": "boolean",
              "default": false,
              "example": "false"
            }
          },
          {
            "name": "dringlichkeit",
            "in": "query",
            "required": false,
            "description": "Extreme, not self-caused urgency.",
            "schema": {
              "type": "boolean",
              "default": false,
              "example": "false"
            }
          },
          {
            "name": "keineAngebote",
            "in": "query",
            "required": false,
            "description": "Prior call for competition yielded no (acceptable) tenders.",
            "schema": {
              "type": "boolean",
              "default": false,
              "example": "false"
            }
          },
          {
            "name": "nichtBeschreibbar",
            "in": "query",
            "required": false,
            "description": "Service cannot be specified sufficiently / requires conceptual or innovative solutions.",
            "schema": {
              "type": "boolean",
              "default": false,
              "example": "false"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Determine permitted procurement procedures for a contract value and type.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "tool": "verfahrenswahl_ermitteln",
                  "input": {
                    "auftraggeber": "sonstige",
                    "leistungsart": "dienst",
                    "wert": 250000,
                    "regelwerk": "bund"
                  },
                  "result": {
                    "oberschwellig": true,
                    "schwelle": 216000,
                    "regime": "Vergabeverordnung (VgV)",
                    "optionen": [
                      {
                        "verfahren": "Offenes Verfahren",
                        "status": "frei",
                        "rechtsgrundlage": "§ 119 Abs. 2 GWB, § 14 Abs. 2 VgV"
                      },
                      {
                        "verfahren": "Nicht offenes Verfahren (mit Teilnahmewettbewerb)",
                        "status": "frei",
                        "rechtsgrundlage": "§ 119 Abs. 2 GWB, § 14 Abs. 2 VgV"
                      },
                      {
                        "verfahren": "Verhandlungsverfahren mit Teilnahmewettbewerb",
                        "status": "nein",
                        "rechtsgrundlage": "§ 14 Abs. 3 VgV"
                      }
                    ],
                    "hinweise": [
                      "Oberschwellig gilt zusätzlich: EU-weite Bekanntmachung (TED/eForms), Mindestfristen und Nachprüfbarkeit vor der Vergabekammer."
                    ]
                  },
                  "as_of": "2026-08-15"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        }
      }
    },
    "/api/v1/wertungsmatrix": {
      "get": {
        "operationId": "wertungsmatrix_berechnen",
        "x-title-de": "Angebote werten (UfAB)",
        "summary": "Score procurement bids by price and quality using all three UfAB methods.",
        "description": "Returns the winner and full ranking under all three UfAB scoring methods — einfach (L/P ratio), erweitert (leading-group decision), gewichtet (weighted normalisation) — plus a sensitivity analysis showing how much the winner’s price must rise before another bidder takes the lead (§ 127 GWB, § 58 VgV; UfAB-Richtwertmethoden Stand 2016). Use when the user has bid prices and quality scores and needs to identify the most economically advantageous tender. Do not use if the evaluation committee has not yet assigned quality scores — this tool scores, it does not assess quality. Key output fields: winner, ranking[], sensitivity[], legal_basis.\n\nExample user questions: \"Welches Angebot gewinnt nach Preis-Leistungs-Verhältnis?\"; \"Wertungsmatrix nach UfAB berechnen\"; \"Zuschlag auf das wirtschaftlichste Angebot ermitteln\"; \"Sensitivitätsanalyse der Angebotswertung\"; \"Führungsgruppe nach erweiterter Richtwertmethode\"",
        "tags": [
          "Vergabe-Rechner"
        ],
        "parameters": [
          {
            "name": "angebote",
            "in": "query",
            "required": true,
            "description": "Semicolon-separated list of bids in format 'Name:Price:Points'. Name may contain spaces. Price must be > 0; Points >= 0. Minimum 2 bids.",
            "schema": {
              "type": "string",
              "example": "Firma A:120000:85;Firma B:110000:70;Firma C:130000:95"
            }
          },
          {
            "name": "methode",
            "in": "query",
            "required": false,
            "description": "Scoring method: einfach=simple ratio, erweitert=extended with leading group, gewichtet=weighted normalization.",
            "schema": {
              "type": "string",
              "enum": [
                "einfach",
                "erweitert",
                "gewichtet"
              ],
              "default": "einfach",
              "example": "gewichtet"
            }
          },
          {
            "name": "gewichtLeistung",
            "in": "query",
            "required": false,
            "description": "Weight of quality score in % for methode=gewichtet (0–100). Price weight = 100 minus this value.",
            "schema": {
              "type": "integer",
              "default": 60,
              "example": 60
            }
          },
          {
            "name": "schwankungsbreite",
            "in": "query",
            "required": false,
            "description": "Leading-group bandwidth in % for methode=erweitert (1–50).",
            "schema": {
              "type": "integer",
              "default": 10,
              "example": 10
            }
          },
          {
            "name": "entscheidung",
            "in": "query",
            "required": false,
            "description": "Tie-breaking criterion within the leading group for methode=erweitert.",
            "schema": {
              "type": "string",
              "enum": [
                "leistung",
                "preis"
              ],
              "default": "leistung",
              "example": "leistung"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Score procurement bids by price and quality using all three UfAB methods.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "tool": "wertungsmatrix_berechnen",
                  "input": {
                    "angebote": "Firma A:120000:85;Firma B:110000:70;Firma C:130000:95",
                    "methode": "gewichtet",
                    "gewichtLeistung": 60
                  },
                  "result": {
                    "methode": "gewichtet",
                    "optionen": {
                      "gewichtLeistung": 60,
                      "schwankungsbreite": 10,
                      "entscheidung": "leistung"
                    },
                    "ergebnis": {
                      "sieger": "Firma C",
                      "erlaeuterung": "Gewichtung 60 % Leistung : 40 % Preis; normiert auf das leistungsstärkste (95 Punkte) bzw. günstigste Angebot.",
                      "zeilen": [
                        {
                          "index": 2,
                          "name": "Firma C",
                          "preis": 130000,
                          "punkte": 95,
                          "kennzahl": 93.85,
                          "rang": 1
                        },
                        {
                          "index": 0,
                          "name": "Firma A",
                          "preis": 120000,
                          "punkte": 85,
                          "kennzahl": 90.35,
                          "rang": 2
                        },
                        {
                          "index": 1,
                          "name": "Firma B",
                          "preis": 110000,
                          "punkte": 70,
                          "kennzahl": 84.21,
                          "rang": 3
                        }
                      ]
                    },
                    "sensitivitaet": {
                      "siegerKipptBei": 11.6,
                      "verfolgerGewinntBei": 8.8,
                      "verfolgerName": "Firma A"
                    }
                  },
                  "as_of": "2026-08-15"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters. Response body includes `expected` (parameter name → explanation) and `example` (a working URL for self-repair)."
          },
          "429": {
            "description": "Rate limit exceeded. Check the `Retry-After` response header."
          }
        }
      }
    }
  }
}