# NSCT — API-Referenz > **Hinweis:** Diese API-Referenz beschreibt den aktuellen Stand (Stage 22). ## Server-Adresse ``` http://localhost:8080 ``` Nach `docker compose up`. --- ## System-Endpunkte ### GET /health **Beschreibung:** Basic health check — gibt den Status und die Version zurück. Wird von Docker Healthchecks und Load Balancern verwendet. **Request:** ``` GET /health ``` **Response (200 OK):** ```json { "status": "ok", "version": "0.1.0" } ``` --- ### GET /ready **Beschreibung:** Readiness check — prüft die Erreichbarkeit von Downstream-Services (LLM-Provider, ggf. Datenbank). **Request:** ``` GET /ready ``` **Response (200 OK):** Wenn bereit: ```json { "status": "ready", "llm": "ok", "database": "unknown", "llm_model": "Qwen3.6-35B" } ``` Wenn nicht bereit: ```json { "status": "not_ready", "llm": "error:Connection refused", "database": "unknown" } ``` **Mögliche `status`-Werte:** - `ready` — Alle geprüften Services sind erreichbar - `not_ready` — Mindestens ein Service ist nicht erreichbar --- ### GET /providers **Beschreibung:** Listet die konfigurierten Provider ohne Secrets. **Request:** ``` GET /providers ``` **Response (200 OK):** ```json { "llm": { "available": true, "model": "Qwen3.6-35B", "max_concurrency": 3 }, "vision": { "available": true, "model": "Qwen2.5-VL-3B" }, "audio": { "available": true, "model": "default" } } ``` **Falls kein Provider konfiguriert:** ```json { "llm": { "available": false }, "vision": { "available": false }, "audio": { "available": false } } ``` **Wichtig:** Dieser Endpoint gibt **keinerlei** Secrets, API-Keys oder sensible Konfigurationswerte zurück. --- ## Research API (Stage 14+) Alle Research-Endpoints haben das Präfix `/v1/research`. --- ### POST /v1/research **Beschreibung:** Startet eine neue Recherche asynchron (Background-Pipeline). Die Antwort kommt sofort — das eigentliche Ergebnis ist über `GET /v1/research/{id}/report` abrufbar. **Request:** ```json { "query": "Welche wesentlichen Fortschritte gab es im letzten Jahr bei Kernfusion?", "language": "de", "depth": "normal", "extra_queries": ["Fusion breakthroughs 2025", "commercial fusion progress"] } ``` **Parameter:** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `query` | string | yes | — | Forschungsfrage (1–2000 Zeichen) | | `language` | string | no | `"de"` | Sprachcode (z.B. `"de"`, `"en"`) | | `depth` | string | no | `"normal"` | Suchtiefe: `"quick"`, `"normal"`, `"deep"` | | `extra_queries` | string[] | no | `null` | Optionale zusätzliche Suchanfragen | **Depth-Konfiguration:** | Tiefe | max_search_queries | max_sources | max_llm_requests | max_duration | max_context | |-------|--------------------|-------------|-------------------|--------------|-------------| | `quick` | 10 | 15 | 15 | 300s | 16k | | `normal` | 20 | 30 | 30 | 300s | 24k | | `deep` | 40 | 60 | 60 | 600s | 32k | **Response (200 OK):** ```json { "research_id": "uuid-...", "status": "pending", "query": "Welche Fortschritte bei Kernfusion?", "depth": "normal", "state": "created" } ``` **Error (400):** ```json { "detail": "Ungültige Tiefe 'ultra'. Gültig: 'quick', 'normal', 'deep'." } ``` --- ### GET /v1/research **Beschreibung:** Liste aller Research-Runs (paginiert). **Query-Parameter:** | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `limit` | int | 10 | Max Anzahl Ergebnisse | | `offset` | int | 0 | Offset für Pagination | **Response (200 OK):** ```json { "total": 5, "limit": 10, "offset": 0, "items": [ { "research_id": "uuid-...", "query": "Kernfusion", "depth": "normal", "state": "completed", "created_at": "2025-01-01T00:00:00+00:00", "source_count": 5, "claim_count": 12 } ] } ``` --- ### GET /v1/research/{id} **Beschreibung:** Metadaten eines Research-Runs. **Path-Parameter:** | Parameter | Type | Description | |-----------|------|-------------| | `id` | string | UUID des Research-Runs | **Response (200 OK):** ```json { "research_id": "uuid-...", "query": "Kernfusion 2025", "depth": "normal", "state": "completed", "created_at": "2025-01-01T00:00:00+00:00", "updated_at": "2025-01-01T00:05:00+00:00", "search_count": 20, "source_count": 5, "claim_count": 12, "is_completed": true, "is_running": false } ``` --- ### GET /v1/research/{id}/status **Beschreibung:** State-Machine Status eines Research-Runs. Identisch zu `GET /v1/research/{id}` — gleicher Response. --- ### GET /v1/research/{id}/sources **Beschreibung:** Quellen für einen Research-Run. **Response (200 OK):** ```json { "research_id": "uuid-...", "sources": [ { "id": "s1", "url": "https://example.com/1", "title": "Beispiel Quelle", "domain": "example.com", "source_type": "primary", "retrieved_at": "2025-01-01T00:01:00+00:00" } ], "total": 1 } ``` --- ### GET /v1/research/{id}/claims **Beschreibung:** Claims (Behauptungen) für einen Research-Run. **Response (200 OK):** ```json { "research_id": "uuid-...", "claims": [ { "id": "c1", "research_run_id": "uuid-...", "source_id": "s1", "claim_text": "Behauptung A", "evidence_span": "Quelle 1, Abschnitt 2", "claim_type": "factual", "confidence": 0.85 } ], "total": 1 } ``` --- ### GET /v1/research/{id}/evidence **Beschreibung:** Evidence-Scores (6-dimensional) für einen Research-Run. **Response (200 OK):** ```json { "research_id": "uuid-...", "evidence": [ { "claim_id": "c1", "research_run_id": "uuid-...", "evidence_type": "primary_report", "source_independence_score": 0.9, "primary_source_proximity": 0.95, "cross_source_support": 0.7, "contradiction_level": 0.2, "evidence_directness": 0.88, "date_relevance_score": 0.95 } ], "total": 1 } ``` --- ### GET /v1/research/{id}/report **Beschreibung:** Synthese-Bericht (finaler Research Report). **Response (200 OK):** ```json { "research_id": "uuid-...", "query": "Kernfusion 2025", "summary": "Zusammenfassung der Recherche...", "findings": [ { "text": "Fundamentale Erkenntnis A", "confidence": 0.85, "source_ids": ["s1", "s2"] } ], "disagreements": [ { "claim": "Behauptung X", "positions": [ {"source": "Quelle 1", "view": "Für X"}, {"source": "Quelle 2", "view": "Gegen X"} ] } ], "uncertainties": ["Nicht ausreichend belegte Behauptung Y"], "source_statistics": { "total_sources": 5, "primary_sources": 2, "secondary_sources": 3 }, "methodology": "NSCT Evidence Pipeline — Search, Extract, Claim, Compare, Synthesize", "generated_at": "2025-01-01T00:00:00+00:00" } ``` --- ### DELETE /v1/research/{id} **Beschreibung:** Verschiebt einen Research-Run (auch einen abgeschlossenen) als Soft Delete in den Papierkorb. Der Run ist anschließend in normalen Listen und Abrufen nicht mehr sichtbar. Bei aktivem Löschschutz muss das Passwort im Body übergeben werden; Administratoren benötigen es nicht. **Response (200 OK):** ```json { "status": "hidden", "research_id": "uuid-..." } ``` ### PUT /v1/research/{id}/deletion-protection Setzt einen Löschschutz mit einem Passwort von mindestens acht Zeichen. Das Passwort wird ausschließlich als scrypt-Hash gespeichert und nie ausgegeben. Bei einer Änderung eines bestehenden Schutzes ist `current_password` nötig. ### GET /v1/admin/research/deleted Administrator-Endpunkt für den Papierkorb. Die Administratorrolle wird lokal mit `nsct-api-key grant-admin ` vergeben. ### DELETE /v1/admin/research/{id} Endgültiges Löschen eines bereits ausgeblendeten Eintrags. Sowohl Soft Delete als auch Purge werden in `research_deletion_audit` protokolliert. --- ## Prometheus Metrics ### GET /metrics **Response:** Prometheus Text Format mit allen Metriken: - `search_queries_total` - `sources_discovered_total` - `sources_fetched_total` - `sources_rejected_total` - `claims_extracted_total` - `duplicate_sources_total` - `contradictions_detected_total` - `llm_requests_total` - `llm_tokens_input_total` - `llm_tokens_output_total` - `research_duration_seconds` - `research_completed_total` - `research_failed_total` - `active_research_runs` --- ## Error Response Format Alle Fehler folgen einem konsistenten Format: ```json { "detail": "Fehlerbeschreibung" } ``` --- ## Authentifizierung Stage 22: Keine Authentifizierung. Dies kann in späteren Stages hinzugefügt werden (API-Key, OAuth, etc.).