Schnellstart
Sie benötigen einen API-Key (wird von Scout-Admins erstellt, Format scout_…). Der Key wird bei der Erstellung genau einmal angezeigt.
export SCOUT_API_KEY="scout_xxxxxxxxxxxxxxxx"
curl -s "https://hugoscout.mad.stg.sternwald.cloud/v1/search?q=Baubewilligung&limit=3" \
-H "Authorization: Bearer $SCOUT_API_KEY"
Alle Endpunkte antworten synchron mit JSON (UTF-8). Es gibt kein Streaming — die Antwort kommt vollständig, sobald sie fertig ist.
Authentifizierung
Jede REST-Anfrage an /v1/… braucht den Header Authorization: Bearer <key>. Ohne gültigen Key antwortet die API mit 401, mit deaktiviertem Key mit 403. Für KI-Assistenten gibt es zusätzlich den MCP-Zugang mit Bearer oder OAuth.
Behandeln Sie den Key wie ein Passwort: nicht in Client-Code oder Repositories einbetten, serverseitig speichern. Bei Verlust kann ein Admin den Key deaktivieren und einen neuen erstellen.
MCP-Zugang für KI-Assistenten
Über das Model Context Protocol (MCP) können Open WebUI, ChatGPT und Claude Scout direkt als Recherchewerkzeug nutzen. Voraussetzung ist ein Scout-API-Key (scout_…), erstellt unter Verwaltung → API-Schlüssel.
Server-URL
https://hugoscout.mad.stg.sternwald.cloud/mcp
Verbindungstyp: MCP / Streamable HTTP. Der Endpunkt liegt unter /mcp, nicht unter /v1/mcp. Er liefert synchrone JSON-Antworten und benötigt keine Server-Session. Die OpenAPI-Dateien beschreiben die REST-API, nicht das MCP-Protokoll.
Open WebUI: direkter Bearer-Zugang
- Unter Settings → Admin → Integrations → External Tool Servers eine Verbindung vom Typ MCP (Streamable HTTP) anlegen, nicht OpenAPI. Native MCP-Unterstützung setzt mindestens Open WebUI v0.6.31 voraus; Bezeichnungen können je nach Version abweichen.
- Die obige Server-URL eintragen und Authentifizierung Bearer wählen.
- Im Key-Feld den vollständigen Scout-API-Key eintragen, ohne zusätzliches
Bearerdavor. Keinen Open-WebUI-API-Key verwenden. - Speichern, die Verbindung im Chat aktivieren und
list_municipalitiesaufrufen.
OAuth: ChatGPT, Claude und alternativ Open WebUI
- Eine Remote-MCP-Verbindung mit obiger URL und OAuth einrichten, sofern das Konto bzw. der Workspace diese Funktion freigibt.
- Scout unterstützt dynamische Client-Registrierung und PKCE (S256). In Open WebUI OAuth 2.1 wählen, nicht „OAuth 2.1 (Static)“; Resource auf Automatic, Scope auf
scoutsetzen. Es wird kein Client-Secret benötigt – den API-Key nicht als Client-Secret eintragen. - Auf der Scout-Freigabeseite einmalig den Scout-API-Key eingeben und den Rücksprung im gleichen Browser und Client-Konto abschließen. Der Assistent erhält ein an den Key gebundenes OAuth-Token.
- Danach
list_municipalitiesausführen. Erfolgreiche Discovery allein bestätigt noch keine funktionierende Verbindung.
Die Oberfläche und Callback-URL des jeweiligen Clients sind maßgeblich. Open-WebUI-Betreiber benötigen eine korrekte öffentliche HTTPS-Adresse (WEBUI_URL) und einen stabilen WEBUI_SECRET_KEY für gespeicherte OAuth-Tokens.
Discovery: /.well-known/oauth-authorization-server und /.well-known/oauth-protected-resource. Registrierung, Freigabe und Token-Austausch liegen unter /mcp/oauth/register, /mcp/oauth/authorize und /mcp/oauth/token.
Verfügbare Tools
| Tool | Aufgabe und Parameter |
|---|---|
list_municipalities | Verfügbare Gemeinden auflisten; optional name_filter. |
find_documents | Dokumente semantisch und nach Stichworten in einem begrenzten Ranking-Fenster suchen. Pflicht: query. Optional: municipality, date_from, date_to, only_with_pdf, limit (max. 25), offset, fields. |
get_document | Gespeicherten Artikeloriginaltext oder PDF-Text mit echten Seitenbelegen lesen. Pflicht: municipality_id, article_id; optional document_id, page, text_offset, max_chars, documents_offset. Siehe Dokumentabruf. |
ask_scout | Antwort mit Quellen erstellen. Pflicht: question. Optional: municipality, date_from, date_to. Typisch 10–60 Sekunden; mindestens 120 Sekunden Client-Timeout vorsehen. |
Gemeinden als Klarnamen angeben, z. B. Neuruppin; Datumswerte als YYYY-MM-DD. Die vollständigen Parameterschemata liefert tools/list. Ergebnisse enthalten Text und bei strukturierten Ergebnissen zusätzlich structuredContent.
Für Originalbelege find_documents mit fields: ["title", "municipality_id", "article_id", "url", "attachments"] aufrufen und die IDs sowie gegebenenfalls attachments.pdfs[].document_id an get_document übergeben. Nach Veröffentlichung eines neuen Tools die gespeicherte Tool-Liste im Client aktualisieren/neu scannen; bei Workspace-Apps kann eine erneute Freigabe nötig sein.
Der fields-Default ist title, municipality, date, summary, url, scout_url, article_id; für get_document ausdrücklich municipality_id, article_id und attachments anfordern. find_documents liefert result_window mit semantic_limit (max. 50), keyword_limit (max. 100), corpus_exhaustive: false und scope: "ranked_candidates". has_more beschreibt nur weitere Treffer innerhalb dieses Ranking-Fensters, keine Vollständigkeit des Korpus; total zählt nur die aktuelle Trefferseite.
Gemeindenamen und „In Scout öffnen“
Die MCP-Textausgabe von find_documents, ask_scout und get_document enthält Quellen bereits lesbar als Gemeindename · In Scout öffnen mit klickbarem Scout-Link. Technische IDs und Navigationsdaten bleiben unverändert in structuredContent für Folgeaufrufe. Den Textblock daher nicht als JSON parsen. Die REST-Antworten bleiben unverändert JSON.
find_documents, ask_scout-Quellen und get_document liefern municipality als Klarname und scout_url als direkten Scout-Artikellink. Die REST-API und get_document liefern zusätzlich den Alias municipality_name. url bleibt die Originalquelle. Bei eigener Feldprojektion municipality und scout_url aufnehmen; nach Veröffentlichung die Tool-Liste im Client aktualisieren.
Linkformat: /articles/{municipality_id}/{article_id}. Der Artikel öffnet sich unabhängig von der aktuellen Suchliste, auch nach Neuladen. Ohne Browsersitzung erscheint zunächst der Scout-Login; das Ziel bleibt erhalten. Kein öffentlicher Freigabelink: API-Key oder MCP-OAuth ersetzen nicht die Browseranmeldung. Unbekannte, entfernte oder nicht zugängliche Artikel geben keinen Inhalt aus.
Clients sollen Gemeindename und „In Scout öffnen“ statt technischer ID-Listen anzeigen. Die Tool-Hinweise empfehlen dies, die Darstellung des externen Assistenten bleibt aber dessen Entscheidung. Die vertrauenswürdige Basisadresse ist zentral konfiguriert (PUBLIC_API_BASE_URL, reine HTTPS-Origin), nicht aus Request-Headern abgeleitet.
Technischer Verbindungstest (Bearer)
Mit dem zuvor gesetzten SCOUT_API_KEY lässt sich der MCP-Handshake prüfen:
curl -sS -X POST "https://hugoscout.mad.stg.sternwald.cloud/mcp" \
-H "Authorization: Bearer $SCOUT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"scout-check","version":"1.0"}}}'
Eine erfolgreiche Antwort enthält result.protocolVersion, result.capabilities und result.serverInfo. MCP-Clients führen anschließend notifications/initialized, tools/list und tools/call aus.
Berechtigungen und Fehlerdiagnose
Gemeinde-/Datumsbeschränkungen, Limits und Nutzungsprotokoll des Scout-Keys gelten auch über MCP. list_municipalities und get_document nutzen das Suchlimit; ask_scout und find_documents das RAG-Limit. Ein deaktivierter Key sperrt auch die daran gebundenen OAuth-Tokens.
Am MCP-Endpunkt ergeben fehlende, ungültige oder deaktivierte Zugangsdaten 401 mit WWW-Authenticate. Protokollfehler werden als JSON-RPC-Fehler zurückgegeben; Tool-Fehler und Rate-Limits können in einem Tool-Ergebnis mit isError: true stehen.
Für Support: Client-Version, Auth-Modus, Zeitpunkt, HTTP-Status und X-Request-ID nennen. Niemals API-Keys, Authorization-Header, Tokens, OAuth-Codes oder vollständige Callback-URLs weitergeben. Protokolltests mit dem offiziellen MCP-SDK ersetzen nicht die Abnahme in der konkreten Open-WebUI- oder ChatGPT-Installation.
Rate-Limits & Key-Scope
Limits gelten pro Key und Endpunkt-Klasse (Standardwerte, pro Key konfigurierbar):
| Klasse | Endpunkte | Standard-Limit |
|---|---|---|
| Suche | /v1/municipalities, /v1/search, /v1/documents/read; MCP list_municipalities, get_document | 60 Anfragen/Minute |
| RAG | /v1/rag/search, /v1/rag/ask; MCP find_documents, ask_scout | 10 Anfragen/Minute |
Bei Überschreitung: 429 mit Retry-After-Header — warten Sie die angegebene Zeit und wiederholen Sie die Anfrage.
Key-Scope
Ein Key kann auf bestimmte Gemeinden und/oder einen Datumsbereich eingeschränkt sein. Ihre Anfrage-Filter werden serverseitig mit dem Scope geschnitten (Schnittmenge): Anfragen ausserhalb des Scopes liefern schlicht keine Treffer — es gibt keinen Fehler und keinen Weg am Scope vorbei.
GET/v1/municipalitiesGemeinde-Lookup
Übersetzt Gemeinde-Nummern in Klarnamen — und umgekehrt. Die municipality_id ist der amtliche Gemeindeschlüssel (z. B. 2422 = Neuruppin). Nutzen Sie diesen Endpunkt, um die IDs für die municipality_ids-Filter der anderen Endpunkte zu finden. Ist Ihr Key auf bestimmte Gemeinden eingeschränkt, sehen Sie hier genau diese.
Query-Parameter
| Parameter | Beschreibung |
|---|---|
q | Optional: Namens-Teilstring, z. B. q=zür. |
canton | Optional: Region/Bundesland, z. B. canton=Brandenburg. |
Beispiel
curl -s "https://hugoscout.mad.stg.sternwald.cloud/v1/municipalities?q=rupp" \
-H "Authorization: Bearer $SCOUT_API_KEY"
Antwort
{
"count": 1,
"municipalities": [
{"municipality_id": 2422, "name": "Neuruppin", "canton": "Brandenburg", "district": "Ostprignitz-Ruppin"}
]
}
GET/v1/searchVolltextsuche
Durchsucht Titel, Text, KI-Metadaten, PDF-Inhalte und Bildbeschreibungen. Mehrfachwerte auf derselben Achse sind ODER-verknüpft, verschiedene Achsen UND-verknüpft.
Query-Parameter
| Parameter | Beschreibung |
|---|---|
q | Pflicht. Suchbegriff(e); Phrasen mit "…". |
limit, offset | Pagination. limit max. 100 (Default 25). |
municipality_ids | Kommagetrennte Gemeindeschlüssel (siehe /v1/municipalities), z. B. 2422. |
canton, district | Region/Bundesland (z. B. Brandenburg) bzw. Landkreis. |
date_range | YYYY-MM-DD..YYYY-MM-DD; offene Enden erlaubt (..2026-06-30). Alternativ date_from/date_to. |
source_type, author | Quellentyp bzw. Autor. |
ai_category, ai_relevance, ai_label | KI-Facetten (mehrfach angebbar). |
has_pdf=1, has_image=1 | Nur Treffer mit PDF bzw. Bild. |
image_count, document_count, word_count | Range-Filter: gt:N, lt:N, eq:N oder A-B. |
include_attachments=1 | Treffer um attachments (Dokumentreferenzen zum Lesen mit /v1/documents/read) ergänzen. |
Beispiel
curl -s "https://hugoscout.mad.stg.sternwald.cloud/v1/search?q=Baubewilligung&ai_category=Bau&date_range=2026-01-01..2026-07-01&limit=10" \
-H "Authorization: Bearer $SCOUT_API_KEY"
Antwort
{ query, total, count, offset, limit, results: [...] } — jedes Resultat enthält Artikel-Metadaten (Gemeinde, Kanton, Datum, Autor, URL), KI-Felder (Kategorie, Relevanz, Labels, Zusammenfassung) sowie Treffer-Snippets mit <mark>-Hervorhebung (title_snippet, body_snippet, ai_snippet, pdf_snippets, image_snippets).
Mit include_attachments=1 enthält jeder Treffer zusätzlich attachments mit document_count, bis zu 100 pdfs, has_more und next_documents_offset. Die Referenzen enthalten document_id, url, title, filename, page_count und availability.
POST/v1/rag/searchVektor-Retrieval
Semantische Suche über Embeddings — findet inhaltlich passende Mitteilungen auch ohne exakte Wortübereinstimmung. Liefert Treffer mit Relevanz-Score, ohne LLM-Antwort (schnell und günstig).
Request-Body (JSON)
| Feld | Beschreibung |
|---|---|
query | Pflicht. Frage oder Suchtext in natürlicher Sprache. |
top_k | Anzahl Treffer (Default 10, max. 50). |
municipality_ids | Array von Gemeinde-Nummern. |
date_from, date_to | YYYY-MM-DD. |
has_pdf | true = nur Treffer mit PDF. |
include_media | true = Bild-/PDF-Metadaten pro Treffer mitliefern. |
include_attachments | true = normalisierte Dokumentreferenzen wie bei include_attachments=1 in der Volltextsuche mitliefern. |
Beispiel
curl -s -X POST "https://hugoscout.mad.stg.sternwald.cloud/v1/rag/search" \
-H "Authorization: Bearer $SCOUT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "Was wurde zur Schulentwicklung entschieden?", "municipality_ids": [2422], "top_k": 5}'
Antwort
{ query, count, results: [...] } — Treffer mit rank (Score), Titel, Gemeinde, Datum, Lead/Body, KI-Zusammenfassung/-Entitäten und URL.
POST/v1/documents/readOriginaltext & PDF-Seiten
Gibt gespeicherten Artikeloriginaltext (Lead und Absätze) oder Text einer zugehörigen lokalen PDF-Datei zurück, keine KI-Zusammenfassung. Zuerst /v1/search mit include_attachments=1 oder /v1/rag/search mit include_attachments: true ausführen. municipality_id und article_id aus dem Treffer übernehmen; für ein PDF zusätzlich die opake 64-stellige Hex-document_id aus attachments.pdfs.
Request-Body (JSON)
| Feld | Beschreibung |
|---|---|
municipality_id, article_id | Pflicht, positive Integer. Ohne document_id wird der Artikel gelesen. |
document_id | Optional: PDF-Selektor aus attachments.pdfs oder documents (64 Hex-Zeichen). |
page, text_offset | Default 1 bzw. 0; Seiten 1–100000, Offset 0–10000000. Beim Artikeltext ist nur Seite 1 zulässig. |
max_chars | Maximale Textlänge je Antwort, Default 20000, Bereich 1–20000. |
documents_offset | Ab welcher Dokumentreferenz die Liste documents beginnt, Default 0, max. 100000. |
Synthetisches Beispiel (nur Formatillustration; nicht produktiv verifiziert)
curl -s -X POST "https://hugoscout.mad.stg.sternwald.cloud/v1/documents/read" \
-H "Authorization: Bearer $SCOUT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"municipality_id":2422,"article_id":123}'
Für ein PDF document_id aus den Referenzen und page: 1 einsetzen. Die Beispiel-IDs sind keine nachgewiesenen Produktionsbelege.
Antwort und Fortsetzung
Die Antwort enthält municipality_id, article_id, title, url, date, document_id, source_url, content_kind, status, text, page, page_count, truncated, next, documents und next_documents_offset. content_kind: article_original hat page und page_count gleich null. content_kind: pdf_extracted und status: available liefert echte 1-basierte PDF-Seiten. next enthält die nächste Kombination aus page und text_offset; bei der nächsten Seite ist der Offset 0. Dieselben IDs und diese Werte erneut senden, bis next: null ist; truncated zeigt weitere Textabschnitte an.
documents enthält maximal 100 Referenzen unabhängig von der Textpagination. Mit documents_offset: next_documents_offset weiterblättern, bis next_documents_offset: null ist. availability: stored_reference bedeutet nur einen eingetragenen PDF-Pfad, text_reference einen Legacy-Textpfad, not_stored keinen lokalen Pfad — keine Garantie für eine lesbare Datei. Die Seitenzahl in einer Referenz kann 0 sein, selbst wenn das PDF Seiten hat.
not_stored, text_unavailable, page_has_no_text, file_unreadable, pdf_unreadable_or_limit_exceeded, file_too_large oder unsafe_storage_path statt Textbeleg beachten. legacy_extracted meldet page_provenance_unavailable: nur page: 1 mit Offset, keine verlässliche PDF-Seitenzuordnung; keine Seitenzahl daraus zitieren.Artikel-url, source_url und Referenz-url werden konservativ gefiltert: Einfache öffentliche HTTP(S)-URLs bleiben erhalten. Ein Query-String ist nur zulässig mit höchstens 10 unterschiedlichen Parametern, deren Schlüssel exakt id, docId oder article_id sind und deren Werte jeweils 1–20 ASCII-Ziffern enthalten. Solche öffentlichen ID-Links bleiben unverändert (z. B. https://beispiel.de/dokument?id=123). Unbekannte, signierte oder zugangsdatenhaltige Parameter, doppelte Schlüssel, ungültige Werte oder mehr als 10 Parameter schwärzen die ganze URL. Dasselbe gilt für Fragmente, Benutzerinformationen, private/interne Hosts oder IPs, bekannte Storage-Provider-Hosts und nichtstandardmäßige Ports. Die IDs (municipality_id, article_id, document_id) bleiben trotzdem für den Abruf verwendbar; leerer Link bedeutet nicht fehlenden Inhalt. Das gilt auch für die url in MCP-find_documents-Treffern. Lokale Dateipfade bleiben auf das Gemeinde-Medienverzeichnis beschränkt. Der Key-Scope für Gemeinde und Datum gilt auch hier. Unbekannte oder nicht freigegebene Artikel/Dokumente ergeben 404, ungültige Parameter/Offsets 400. Quellen-URL und Status vor dem Zitieren prüfen.
POST/v1/rag/askFrage/Antwort mit Quellen
Vollständige RAG-Pipeline: Retrieval + LLM-Antwort mit Quellenangaben ([1]-Zitationsmarker im Markdown). Stateless — es gibt keine Server-Session; eine Gesprächshistorie können Sie optional selbst mitschicken.
Request-Body (JSON)
| Feld | Beschreibung |
|---|---|
query | Pflicht. Die Frage. |
municipality_ids, date_from, date_to, has_pdf | Filter wie bei /v1/rag/search. |
history | Optionales Array [{"role": "user"|"assistant", "content": "…"}] — die letzten max. 20 Einträge werden berücksichtigt. |
top_k | Anzahl Kontext-Artikel für das LLM (optional). |
Beispiel
curl -s -X POST "https://hugoscout.mad.stg.sternwald.cloud/v1/rag/ask" \
--max-time 120 \
-H "Authorization: Bearer $SCOUT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "Fasse die wichtigsten Bauprojekte 2026 zusammen.", "municipality_ids": [2422]}'
Antwort
{
"query": "…",
"answer": "Markdown-Antwort mit [1]-Zitationsmarkern",
"sources": [{"article_id": 123, "municipality_name": "…", "title": "…", "url": "…"}],
"articles_used": 8,
"model": "…",
"usage": {"input_tokens": 4210, "output_tokens": 640}
}
curl --max-time 120). Die Verbindung bleibt offen, bis die vollständige JSON-Antwort geliefert ist.Fehlerbehandlung
REST-Fehler unter /v1/… kommen als JSON-Umschlag: {"error": {"code": "…", "message": "…"}}. Für MCP siehe MCP-Zugang.
| Status | Code | Bedeutung |
|---|---|---|
| 400 | bad_request | Ungültige Parameter (z. B. fehlendes q/query, kaputte history). |
| 401 | unauthorized | API-Key fehlt oder ist ungültig. |
| 403 | key_disabled | Key wurde deaktiviert. |
| 429 | rate_limit_exceeded | Rate-Limit überschritten — Retry-After-Header beachten. |
| 500 | internal_error | Serverfehler — Anfrage später wiederholen. |
Jede Anfrage wird pro Key protokolliert (Endpoint, Zeitpunkt, Status, Dauer, bei RAG-ask auch Tokenverbrauch). Eine Abrechnung findet derzeit nicht statt.