LLARS v1 Konferenz-Manager API¶
Version: 1.0 | Stand: Oktober 2026
Programmatische REST-API für den Konferenz-Manager: Forschungsgruppen lesen,
Konferenzserien und Editionen pflegen (bestätigte Termine und geschätzte
Zeitfenster), Paper samt Autoren, arXiv-/DOI-Links und Einreichungs-Historie
verwalten und die KI-Aktualisierung starten, beobachten und abbrechen. Alle
Endpunkte liegen unter /api/v1/conference-manager/*.
Authentifizierung¶
Identisch zur Scenario-API: X-API-Key (persönlich oder System) oder
OAuth Bearer. Siehe v1 Scenario API.
Persönliche Keys legst du unter Einstellungen → API-Keys an und wählst dort
die Scopes conference:read und/oder conference:write.
Scopes¶
| Scope | Erlaubt | RBAC-Fallback (OAuth, Keys ohne Scopes) |
|---|---|---|
conference:read |
alle GET-Endpunkte unter /api/v1/conference-manager/* |
feature:conference_manager:view |
conference:write |
alle POST / PATCH / PUT / DELETE, inklusive Start und Abbruch der KI-Aktualisierung; schließt Lesen ein |
feature:conference_manager:edit |
admin:* |
überschreibt alles | admin:permissions:manage |
Die Konferenz-Scopes sind strikt von scenario:* und chatbot:* getrennt.
Scope und Recht zusammen: Ein Scope schränkt einen Key ein, er erweitert
ihn nie. Zusätzlich zum Scope muss das Konto, dem der Key gehört, das passende
Feature-Recht haben (feature:conference_manager:view zum Lesen,
…:edit zum Schreiben; Admins immer). Wird einem Konto das Recht entzogen,
funktionieren seine Konferenz-Keys sofort nicht mehr (403).
Forschungsgruppen und Sichtbarkeit¶
Jede Serie, Edition, jedes Paper und jeder KI-Lauf gehört zu genau einer Forschungsgruppe. Jeder Aufruf wird gegen die Gruppe geprüft:
| Situation | Antwort |
|---|---|
Du bist Mitglied (Rolle owner oder member) |
Lesen und Schreiben |
Du bist Mitglied mit Rolle viewer |
Lesen; Schreiben → 403 |
| Du bist kein Mitglied | 404 — exakt wie bei einer nicht existierenden ID |
| Admin / System-Key | alle Gruppen |
Die 404 bei fremden Gruppen ist Absicht: So lässt sich nicht per Statuscode
abtasten, welche IDs es in anderen Gruppen gibt. Verweise im Body
(series_id, conference_id) müssen in derselben Gruppe liegen wie das
Objekt, sonst ebenfalls 404. Ältere Datensätze ohne Gruppe sieht nur ein Admin;
die API legt nie Datensätze ohne Gruppe an (group_id ist beim Anlegen Pflicht
und lässt sich später nicht ändern).
Antwort- und Fehlerformat¶
Erfolgreiche Antworten tragen "success": true und das Objekt unter seinem
Namen (conference, series, paper, run, research_group). Listen sind
paginiert:
limit ist höchstens 200 (größere Werte werden gekappt, Standard 50),
offset beginnt bei 0. Fehler kommen einheitlich:
{
"success": false,
"error": "Invalid request body — Value error, submission_window_start must be on or before submission_window_end",
"error_type": "validation_error",
"details": { "errors": [ { "loc": [], "msg": "...", "type": "value_error" } ] }
}
| Status | Bedeutung |
|---|---|
200 / 201 |
gelesen bzw. angelegt |
202 |
KI-Lauf angenommen (läuft im Hintergrund) |
400 |
ungültiger Body oder Query-Parameter (unbekanntes Feld, falsches Datum, Fenster mit start > end, ungültige DOI …) |
401 |
kein oder ungültiger Key |
403 |
Scope fehlt, Feature-Recht fehlt oder Gruppe nur lesbar (viewer) |
404 |
existiert nicht oder gehört zu einer fremden Gruppe |
409 |
Konflikt: Edition (acronym, year) oder Serien-Kürzel existiert schon; in der Gruppe läuft bereits ein KI-Lauf |
503 |
KI-Aktualisierung auf diesem Server nicht verfügbar |
Termine: bestätigt oder geschätzt¶
Jede Edition hat drei Meilensteine. Jeder kann einen exakten Termin (bestätigt) und/oder ein Zeitfenster (geschätzt) haben:
| Meilenstein | Exakter Termin | Zeitfenster |
|---|---|---|
| Einreichung | submission_deadline |
submission_window_start, submission_window_end |
| Autoren-Benachrichtigung | notification_date |
notification_window_start, notification_window_end |
| Konferenz | start_date, end_date |
conference_window_start, conference_window_end |
- Formate: Exakte Termine sind naive ISO-Datetimes
YYYY-MM-DDTHH:MM:SS(in der Antwort immer so). Beim Schreiben ist auch ein reines Datum (2027-05-15→00:00:00) oder ein Offset (Z,+02:00) erlaubt; ein Offset wird nach UTC umgerechnet und dann entfernt. Fenstergrenzen sind reine DatenYYYY-MM-DD— eine Uhrzeit ist hier ein 400. - Regeln:
start ≤ endje Fenster undstart_date ≤ end_date, sonst 400. Ein PATCH, der nur eine Grenze ändert, wird gegen den gespeicherten Gegenwert geprüft. Unparsebare Werte sind immer ein 400 — nie ein stilles Löschen. - Der exakte Termin gewinnt: Kommt der echte Termin, setzt du ihn per PATCH. Das Fenster bleibt als Historie stehen, der Meilenstein gilt ab dann als bestätigt.
- Abgeleitete Felder in der Antwort:
milestonesje Meilenstein mitstatus(confirmed|estimated|unknown),datebzw.start/endundwindow_start/window_end;is_estimatedisttrue, sobald ein Meilenstein nur geschätzt ist.estimation_basis(Freitext, z. B. „abgeleitet aus 2023–2026") undestimation_confidence(low|medium|high) erklären die Schätzung. Dazu kommencore_url(CORE-Portal),maps_url(Google Maps),last_refreshed_atundlast_refresh_summary.
PATCH-Semantik (überall): Nur gesendete Felder werden geändert. Ein
explizites null leert ein optionales Feld (z. B. "notes": null).
Pflichtfelder (name, acronym, year, title) und core_ranking einer
Edition dürfen nicht null werden — zum Entfernen des Rankings "Unranked"
senden. Unbekannte Felder sind ein 400.
Endpunkte¶
Forschungsgruppen¶
| Methode | Pfad | Scope | Zweck |
|---|---|---|---|
GET |
/api/v1/conference-manager/research-groups |
conference:read |
Eigene Gruppen mit user_role (Admins: alle) |
GET |
/api/v1/conference-manager/research-groups/{id} |
conference:read |
Gruppe mit user_role, stats und members |
Gruppen und Mitgliedschaften verwaltest du in der Oberfläche; die v1 legt keine Gruppen an.
Serien¶
| Methode | Pfad | Scope | Zweck |
|---|---|---|---|
GET |
/api/v1/conference-manager/series?group_id=&search= |
conference:read |
Serien (ohne group_id: alle zugänglichen Gruppen) |
POST |
/api/v1/conference-manager/series |
conference:write |
Serie anlegen (group_id, name, acronym, optional core_ranking, website_url, keywords, notes) |
GET |
/api/v1/conference-manager/series/find?acronym=&group_id= |
conference:read |
Serie per Kürzel (Groß-/Kleinschreibung egal); series: null, wenn keine passt |
GET |
/api/v1/conference-manager/series/{id} |
conference:read |
Serie mit ihren Editionen |
PATCH |
/api/v1/conference-manager/series/{id} |
conference:write |
Teil-Update |
DELETE |
/api/v1/conference-manager/series/{id} |
conference:write |
Löschen; Editionen bleiben, verlieren nur den Serien-Bezug |
Serien-Kürzel sind serverweit eindeutig — ein vergebenes Kürzel ergibt 409.
Konferenzen (Editionen)¶
| Methode | Pfad | Scope | Zweck |
|---|---|---|---|
GET |
/api/v1/conference-manager/conferences |
conference:read |
Editionen (Filter siehe unten) |
POST |
/api/v1/conference-manager/conferences |
conference:write |
Edition anlegen (group_id, name, acronym, year + beliebige Felder aus dem Abschnitt „Termine") |
GET |
/api/v1/conference-manager/conferences/{id} |
conference:read |
Edition lesen |
PATCH |
/api/v1/conference-manager/conferences/{id} |
conference:write |
Teil-Update aller Felder inkl. Fenster |
DELETE |
/api/v1/conference-manager/conferences/{id} |
conference:write |
Löschen; Paper bleiben, verlieren nur den Konferenz-Bezug |
GET |
/api/v1/conference-manager/conferences/{id}/papers |
conference:read |
Paper dieser Edition |
Weitere Felder einer Edition: series_id, core_ranking (A*, A, B, C,
Unranked), city, country, website_url (nur http(s)://), keywords
(≤ 50), notes. (acronym, year) ist serverweit eindeutig → 409.
Filter für GET /conferences (alle optional, kombinierbar):
| Parameter | Wirkung |
|---|---|
group_id |
nur diese Gruppe (fremde Gruppe → 404); ohne: alle zugänglichen |
year |
Jahrgang der Edition |
search |
Teilstring in Name, Kürzel, Stadt oder Land |
estimated |
true: nur Editionen mit mindestens einem geschätzten Meilenstein; false: keine solchen |
from, to |
YYYY-MM-DD; eine Edition passt, wenn sich ihr Gesamtzeitraum (alle Termine und Fenster) mit [from, to] überschneidet. Editionen ganz ohne Termin fallen dann heraus. |
core_ranking |
A*, A, B, C, Unranked |
Sortiert wird nach Einreichungsfrist (bei geschätzten Editionen nach dem Fensterbeginn), Editionen ohne beides am Ende.
Paper, Autoren, Einreichungen¶
| Methode | Pfad | Scope | Zweck |
|---|---|---|---|
GET |
/api/v1/conference-manager/papers?group_id=&conference_id=&status=&search= |
conference:read |
Paper (Suche in Titel und Beschreibung) |
POST |
/api/v1/conference-manager/papers |
conference:write |
Paper anlegen |
GET |
/api/v1/conference-manager/papers/{id} |
conference:read |
Paper mit Autoren, Einreichungen, Konferenz |
PATCH |
/api/v1/conference-manager/papers/{id} |
conference:write |
Teil-Update; authors ersetzt die Liste |
DELETE |
/api/v1/conference-manager/papers/{id} |
conference:write |
Löschen inkl. Autoren und Einreichungen |
PUT |
/api/v1/conference-manager/papers/{id}/authors |
conference:write |
Autorenliste komplett ersetzen |
POST |
/api/v1/conference-manager/papers/{id}/submissions |
conference:write |
Einreichung anhängen |
PATCH |
/api/v1/conference-manager/papers/{id}/submissions/{sid} |
conference:write |
Einreichung ändern |
DELETE |
/api/v1/conference-manager/papers/{id}/submissions/{sid} |
conference:write |
Einreichung löschen |
- Felder:
group_id,title,status(planning,in_progress,submitted,accepted,rejected,published),conference_id,overleaf_url,external_url,arxiv_url,doi,keywords,description,notes,authors. - arXiv und DOI:
arxiv_urlnimmtarXiv:2401.12345,2401.12345oder einen arxiv.org-Link und speicherthttps://arxiv.org/abs/<id>.doinimmtdoi:10.…,https://doi.org/10.…oder die nackte DOI und speichert die nackte DOI. Die Antwort enthält zusätzlicharxiv_idunddoi_url(https://doi.org/<doi>). Ungültige Werte sind ein 400. - Autoren: Liste in Reihenfolge, je Eintrag genau eines von
user_id,username(LLARS-Konto) oderexternal_name(externe Person), optionalauthor_order(Standard: Listenposition) undis_corresponding. Unbekannte oder doppelt genannte Konten sind ein 400; höchstens 50 Autoren. - Einreichungen:
conference_id,status(submitted,accepted,rejected,withdrawn),submitted_at,decided_at(exakte Termine),notes. Das Paper übernimmt Konferenz und Status der neuesten Einreichung. Eine Einreichung ist nur über ihr eigenes Paper erreichbar — eine fremdesidim Pfad ergibt 404.
KI-Aktualisierung¶
| Methode | Pfad | Scope | Zweck |
|---|---|---|---|
POST |
/api/v1/conference-manager/conferences/refresh |
conference:write |
Lauf für eine Gruppe starten → 202 |
POST |
/api/v1/conference-manager/conferences/{id}/refresh |
conference:write |
Lauf für genau diese Edition → 202 |
GET |
/api/v1/conference-manager/refresh-runs?group_id=&limit= |
conference:read |
Letzte Läufe der Gruppe, neueste zuerst, ohne progress (group_id Pflicht, limit ≤ 100, Standard 20) |
GET |
/api/v1/conference-manager/refresh-runs/{id} |
conference:read |
Ein Lauf mit progress je Edition |
POST |
/api/v1/conference-manager/refresh-runs/{id}/cancel |
conference:write |
Abbruch anfordern |
POST |
/api/v1/conference-manager/refresh-runs/{id}/resume |
conference:write |
Abgebrochenen oder fehlgeschlagenen Lauf fortsetzen → 202 |
Start: Body {"group_id": 1, "conference_ids": [12, 13], "include_past_months": 3}.
Ohne conference_ids nimmt der Lauf alle Editionen der Gruppe, deren letzter
bekannter Termin (exakt oder Fenster) höchstens include_past_months Monate
zurückliegt (0–36, Standard 3), plus Editionen ganz ohne Termin. Mit
conference_ids genau diese (höchstens 200; sie müssen zur Gruppe gehören,
sonst 404). Läuft in der Gruppe schon ein Lauf, kommt 409 mit
details.run_id des laufenden Laufs. Die KI arbeitet nie von selbst — jeder
Lauf wird manuell gestartet.
Lebenszyklus: queued → running → done | failed | cancelled.
Die Editionen werden nacheinander bearbeitet (Websuche, Seiten lesen,
LLM-Abgleich mit dem Bestand). Nur Werte, die die KI als bestätigt mit Quelle
findet, überschreiben bestätigte Termine; Schätzungen füllen nur leere Fenster.
Bei der Serie ARR legt der Lauf fehlende Zyklen (mit bestätigter
Einreichungsfrist) als neue Editionen an.
Lauf-Objekt:
{
"id": 7, "group_id": 1, "scope": "all", "conference_ids": [12, 13],
"status": "running", "is_active": true, "started_by": "alice",
"model_id": "Global/Mistral/Mistral-Small-3.2-24B-Instruct-2506",
"started_at": "2026-10-02T09:15:00", "finished_at": null, "cancel_requested": false,
"summary": { "total": 2, "done": 1, "changed": 1, "no_change": 0, "errors": 0 },
"open_conference_ids": [],
"progress": {
"12": {
"status": "done", "step": "…", "acronym": "EMNLP", "year": 2027, "name": "…",
"sources": ["https://2027.emnlp.org/calls/main_conference_papers/"],
"changes": [
{ "field": "submission_deadline", "old": null, "new": "2027-05-19T23:59:00",
"confidence": "confirmed", "source_url": "https://2027.emnlp.org/…",
"evidence": "Paper submission deadline: May 19, 2027" }
],
"error": null, "started_at": "…", "finished_at": "…", "updated_at": "…"
},
"13": { "status": "searching", "step": "…", "sources": [], "changes": [], "error": null }
}
}
progress[...].status je Edition: queued, searching, reading,
analyzing, done (mit Änderungen), no_change, error, skipped. Ein
API-Client fragt GET /refresh-runs/{id} alle paar Sekunden ab, bis
is_active false ist (die Oberfläche bekommt dieselben Schritte live per
Socket.IO).
Abbruch: setzt cancel_requested; der Lauf endet nach der Edition, an der
er gerade arbeitet, und übrige Editionen werden skipped. Ein bereits
beendeter Lauf bleibt unverändert, die Antwort ist dann sein Endzustand.
Fortsetzen: Ein Lauf kann auch ohne Abbruch enden, etwa wenn der Server
bei einem Deploy oder Neustart den Prozess beendet; er steht dann auf
failed (summary.error z. B. "Worker beendet"). open_conference_ids
listet bei failed und cancelled die Editionen, die noch offen sind:
mit Fehler (error) oder übersprungen (skipped), aber nicht gelöscht. Bei
allen anderen Status ist die Liste leer. POST /refresh-runs/{id}/resume
startet über genau diese Editionen einen neuen Lauf mit demselben scope
und antwortet mit 202 und {"success": true, "run": {…}}. Der alte Lauf
bleibt als Verlauf unverändert. Ist der Lauf nicht failed oder cancelled
oder läuft in der Gruppe schon ein Lauf, kommt 409; ist nichts mehr
offen, 400. Fremde Läufe ergeben 404 und ein Viewer bekommt 403.
Beispiele¶
export LLARS=https://llars.example.org
export K=llars_… # persönlicher Key mit conference:write
# Eigene Forschungsgruppen
curl -s -H "X-API-Key: $K" "$LLARS/api/v1/conference-manager/research-groups"
# Serie anlegen
curl -s -X POST -H "X-API-Key: $K" -H "Content-Type: application/json" \
-d '{"group_id":1,"name":"Empirical Methods in NLP","acronym":"EMNLP","core_ranking":"A*"}' \
"$LLARS/api/v1/conference-manager/series"
# Geschätzte Edition (nur Zeitfenster)
curl -s -X POST -H "X-API-Key: $K" -H "Content-Type: application/json" \
-d '{
"group_id": 1, "series_id": 3, "name": "EMNLP 2027", "acronym": "EMNLP", "year": 2027,
"submission_window_start": "2027-05-10", "submission_window_end": "2027-05-25",
"notification_window_start": "2027-08-15", "notification_window_end": "2027-08-31",
"conference_window_start": "2027-10-25", "conference_window_end": "2027-11-15",
"estimation_basis": "abgeleitet aus 2023-2026", "estimation_confidence": "medium"
}' \
"$LLARS/api/v1/conference-manager/conferences"
# Termin steht fest: exakten Wert setzen (Fenster bleibt als Historie)
curl -s -X PATCH -H "X-API-Key: $K" -H "Content-Type: application/json" \
-d '{"submission_deadline":"2027-05-19T23:59:00"}' \
"$LLARS/api/v1/conference-manager/conferences/12"
# Alle noch geschätzten Editionen ab Januar 2027
curl -s -H "X-API-Key: $K" \
"$LLARS/api/v1/conference-manager/conferences?group_id=1&estimated=true&from=2027-01-01"
# Paper mit DOI, arXiv und Autoren
curl -s -X POST -H "X-API-Key: $K" -H "Content-Type: application/json" \
-d '{
"group_id": 1, "title": "Our Paper", "status": "published", "conference_id": 12,
"doi": "doi:10.18653/v1/2024.acl-long.1", "arxiv_url": "arXiv:2401.12345",
"authors": [{"username": "alice", "is_corresponding": true}, {"external_name": "Jane Doe"}]
}' \
"$LLARS/api/v1/conference-manager/papers"
# Einreichung anhängen
curl -s -X POST -H "X-API-Key: $K" -H "Content-Type: application/json" \
-d '{"conference_id":12,"status":"submitted","submitted_at":"2027-05-19T20:00:00"}' \
"$LLARS/api/v1/conference-manager/papers/5/submissions"
# KI-Aktualisierung starten, beobachten, abbrechen
curl -s -X POST -H "X-API-Key: $K" -H "Content-Type: application/json" \
-d '{"group_id":1}' "$LLARS/api/v1/conference-manager/conferences/refresh"
curl -s -H "X-API-Key: $K" "$LLARS/api/v1/conference-manager/refresh-runs/7"
curl -s -X POST -H "X-API-Key: $K" "$LLARS/api/v1/conference-manager/refresh-runs/7/cancel"
# … und später die offenen Editionen in einem neuen Lauf fortsetzen
curl -s -X POST -H "X-API-Key: $K" "$LLARS/api/v1/conference-manager/refresh-runs/7/resume"
Sicherheit / Hardening¶
- IDOR-Maskierung (M1): Objekte fremder Gruppen antworten mit 404, nicht
403 — keine ID-Existenz-Lecks. Querverweise (
series_id,conference_id) dürfen die Gruppe nicht verlassen. - Scope ∧ Recht: Ein Key wirkt nur, solange sein Konto das Feature-Recht hat.
- Strikte Schemas: unbekannte Felder, ungültige Daten und Nicht-http(s)-Links sind ein 400 statt still verworfen.
- Mengen-Grenzen:
keywords≤ 50,authors≤ 50,conference_ids≤ 200,limit≤ 200. - Konflikte (Duplikate, laufender KI-Lauf) sind 409 statt 500.
Nicht enthalten¶
- Forschungsgruppen und Mitgliedschaften anlegen oder ändern (nur in der Oberfläche)
- Datensätze zwischen Gruppen verschieben
- KI-Läufe löschen oder automatisch planen (die KI läuft nur auf Anforderung)