Zum Hauptinhalt springen

Projekte über die API

Premium-Funktion

Die Einheit einer Unterhaltung in BasePeak.AI ist das Projekt, nicht der nackte Agent. Ein Projekt bündelt einen geteilten Arbeitsbereich, eigene Aufgaben, projektbezogene Anmeldedaten und eigene Modelleinstellungen – all das, was eine Unterhaltung im Browser von einer über /api/invoke/{id} gestarteten unterscheidet.

POST /api/projects/{project_id}/invoke hängt den neuen Thread an das Projekt: derselbe Elternbezug, den auch die Oberfläche setzt. Ab diesem Zeitpunkt ist es dieselbe Unterhaltung, die auch im Browser erscheint – nicht nur eine ähnliche.

Kommt vom ProjektBei /api/invoke/{id}
Geteilter Arbeitsbereich (Dateien)fehlt – nur der Arbeitsbereich des Agenten oder des Threads ist erreichbar
Aufgaben des Projekts als Werkzeugefehlen vollständig
Projektbezogene Anmeldedaten-Kontextefehlen
Modelleinstellungen und Wissenssammlungen des Projektsfehlen
agent:chat auf /api/invoke/{id} bleibt die schlankere Oberfläche

Das ist kein Fehler, den diese Seite behebt – /api/invoke/{id} bleibt der richtige Weg für Kopfstand-Agenten (headless) und System-Agenten, die an keinem Projekt hängen. Er ist nur dünner: er spricht mit dem nackten Agenten, nicht mit der Unterhaltung, die der Browser führt. Adressieren Sie das Projekt, wenn Sie dessen Kontext brauchen; adressieren Sie den Agenten, wenn Sie ihn nicht brauchen.

Ein Projekt wird über seine Projekt-ID angesprochen, an der einheitlichen Kennung p1… zu erkennen – überall, für die Unterhaltung wie für jeden Inhalt des Projekts. Die im Browser verwendete Adressierung über den Agenten-Pfad (/api/assistants/{id}/projects/{project_id}/…) bleibt der Browser-Sitzung vorbehalten; ein Schlüssel erreicht ausschließlich /api/projects/{project_id}/….

# Konversation in einem Projekt starten.
curl -X POST https://<host>/api/projects/p1abc/invoke \
-H "Authorization: Bearer $BPAI_TOKEN" \
-H "Content-Type: text/plain" \
--data 'Summarise the files in this project'

# Eine Datei hochladen, die die nächste Unterhaltung in diesem Projekt lesen kann.
curl -X POST https://<host>/api/projects/p1abc/files/report.csv \
-H "Authorization: Bearer $BPAI_TOKEN" \
--data-binary @report.csv

Eine Konversation im Projekt führen

POST /api/projects/{project_id}/invoke
POST /api/projects/{project_id}/invoke/thread/{thread_id}
POST /api/projects/{project_id}/invoke/threads/{thread_id}

Scope: project:chat:<project_id>.

Beide Routen verhalten sich wie ihr Gegenstück auf /api/invoke/{id}: derselbe Antwortkörper, derselbe Antwort-Header X-BPAI-Thread-Id, dieselben Accept-Varianten (Streaming/JSON/reiner Text) und dasselbe ?async=true. Ein Client, der bereits gegen /api/invoke/{id} spricht, ändert nur die URL.

# Neue Unterhaltung im Projekt.
curl -sS -X POST \
https://your-instance.platform.basepeak.ai/api/projects/p1abc/invoke \
-H "Authorization: Bearer sk-bpai-1-42-…" \
-H "Accept: application/json" \
-H "Content-Type: text/plain" \
--data 'Fasse die Dateien in diesem Projekt zusammen.'

# Dieselbe Unterhaltung fortsetzen.
curl -sS -X POST \
https://your-instance.platform.basepeak.ai/api/projects/p1abc/invoke/thread/t1abcde \
-H "Authorization: Bearer sk-bpai-1-42-…" \
-H "Accept: application/json" \
--data 'Und was folgt daraus für Q4?'

# Ohne auf die Antwort zu warten.
curl -sS -X POST \
'https://your-instance.platform.basepeak.ai/api/projects/p1abc/invoke?async=true' \
-H "Authorization: Bearer sk-bpai-1-42-…" \
--data 'Erstelle den Monatsbericht.'

Der Agent kommt dabei aus dem Projekt – Sie nennen ihn nirgends. Ein {thread_id}, das zu einem anderen Projekt gehört, wird nie stillschweigend übernommen: die Route antwortet dann mit 403. Siehe Threads für Fortsetzen, Abfragen und async im Detail; das gilt hier unverändert.

Eine gewöhnliche Unterhaltung, kein Sonderfall

Ein über diese Route erzeugter Thread ist ein ganz normaler Chat-Thread. Die bestehenden flachen Thread-Routen (GET /api/threads/{id}, /events, /files, POST .../abort) funktionieren für ihn unverändert. Nur das Projekt selbst – der Eltern-Thread – bleibt dort unerreichbar; sein eigener Arbeitsbereich hat eigene Scopes, siehe unten.

Zum Zurücklesen dieser Unterhaltungen ist project:threads:<p> die erste Wahl: Der Scope deckt Auflisten, Abrufen und erneutes Abspielen ausschließlich für die Unterhaltungen dieses Projekts ab. Der agentengebundene thread:read:<agent> funktioniert ebenfalls, erlaubt aber jede Unterhaltung des Projekt-Agenten – über alle Projekte hinweg, die er bedient, und damit weiter als das Projekt, an das Sie anbinden. /files bleibt an den Agenten gebunden (thread:files), POST .../abort an agent:chat. Siehe Unterhaltungen.

Dateien: der geteilte Arbeitsbereich des Projekts

GET    /api/projects/{project_id}/files
GET /api/projects/{project_id}/file[s]/{file}
POST /api/projects/{project_id}/file[s]/{file}
DELETE /api/projects/{project_id}/file[s]/{file}

Scope: project:files:<project_id> (lesend) oder project:files-write:<project_id> (lesend und schreibend – -write ist eine strikte Erweiterung von project:files, ein Schlüssel braucht nie beide).

Das ist derselbe geteilte Arbeitsbereich, den die Oberfläche als Projekt-Dateien zeigt – nicht der Arbeitsbereich eines einzelnen Threads. Jede Unterhaltung, die im Projekt beginnt, sieht ihn.

# Auflisten.
curl -sS https://your-instance.platform.basepeak.ai/api/projects/p1abc/files \
-H "Authorization: Bearer sk-bpai-1-42-…"

# Hochladen – rohe Bytes, kein Multipart-Formular.
curl -sS -X POST \
https://your-instance.platform.basepeak.ai/api/projects/p1abc/files/report.csv \
-H "Authorization: Bearer sk-bpai-1-42-…" \
--data-binary @report.csv

# Herunterladen.
curl -sS https://your-instance.platform.basepeak.ai/api/projects/p1abc/files/report.csv \
-H "Authorization: Bearer sk-bpai-1-42-…" -o report.csv

# Löschen.
curl -sS -X DELETE \
https://your-instance.platform.basepeak.ai/api/projects/p1abc/files/report.csv \
-H "Authorization: Bearer sk-bpai-1-42-…"

Ein mit project:files-write hochgeladenes Dokument liest die nächste Unterhaltung im selben Projekt automatisch mit – dieselbe Zusicherung, die Dateien für den geteilten Arbeitsbereich beschreibt.

Wissen: Hochladen, dann auf den Status pollen

GET    /api/projects/{project_id}/knowledge
GET /api/projects/{project_id}/knowledge/{file}
POST /api/projects/{project_id}/knowledge/{file}
DELETE /api/projects/{project_id}/knowledge/{file}

Scope: project:knowledge:<project_id> (lesend) oder project:knowledge-write:<project_id> (lesend und schreibend – ebenfalls eine strikte Erweiterung).

Es gibt keine separate Status-Route. GET /api/projects/{project_id}/knowledge liefert für jede Datei state, error sowie Start- und Endzeit der Einlese-Verarbeitung – derselbe Weg, den die Oberfläche selbst geht: hochladen, dann die Liste abfragen, bis state den Endzustand erreicht.

# Hochladen.
curl -sS -X POST \
https://your-instance.platform.basepeak.ai/api/projects/p1abc/knowledge/handbuch.pdf \
-H "Authorization: Bearer sk-bpai-1-42-…" \
-H "Content-Type: application/pdf" \
--data-binary @handbuch.pdf

# Pollen, bis die Datei eingelesen ist.
curl -sS https://your-instance.platform.basepeak.ai/api/projects/p1abc/knowledge \
-H "Authorization: Bearer sk-bpai-1-42-…"
import httpx, time

http = httpx.Client(base_url=BASE, headers={"Authorization": f"Bearer {TOKEN}"})

with open("handbuch.pdf", "rb") as f:
http.post("/api/projects/p1abc/knowledge/handbuch.pdf",
headers={"Content-Type": "application/pdf"},
content=f.read())

while True:
files = http.get("/api/projects/p1abc/knowledge").json()["items"]
entry = next((f for f in files if f["fileName"] == "handbuch.pdf"), None)
if entry and entry["state"] not in ("pending", "ingesting"):
break
time.sleep(2)
425 Too Early, solange die Wissenssammlung noch nicht existiert

Ein neu angelegtes Projekt erhält seine Wissenssammlung asynchron. Laden Sie unmittelbar danach hoch, antworten POST und DELETE auf dieser Route mit 425 Too Early, bis sie bereitsteht. Ein Client, der ein Skript unmittelbar nach dem Anlegen des Projekts startet, trifft das zuverlässig – behandeln Sie 425 wie ein "noch nicht", nicht wie einen Fehler, und wiederholen Sie den Aufruf.

Aufgaben: Erstellen existiert nur hier

POST   /api/projects/{project_id}/tasks
GET /api/projects/{project_id}/tasks
GET /api/projects/{project_id}/tasks/{id}
PUT /api/projects/{project_id}/tasks/{id}
DELETE /api/projects/{project_id}/tasks/{id}
POST /api/projects/{project_id}/tasks/{id}/run
POST /api/projects/{project_id}/tasks/{id}/runs/{run_id}/steps/{step_id}/run
GET /api/projects/{project_id}/tasks/{id}/runs
GET /api/projects/{project_id}/tasks/{id}/runs/{run_id}
DELETE /api/projects/{project_id}/tasks/{id}/runs/{run_id}
POST /api/projects/{project_id}/tasks/{id}/runs/{run_id}/abort

Scope: project:tasks:<project_id> – unaufgeteilt, deckt Lesen, Schreiben und Ausführen gleichermaßen ab.

# Aufgabe anlegen.
curl -sS -X POST https://your-instance.platform.basepeak.ai/api/projects/p1abc/tasks \
-H "Authorization: Bearer sk-bpai-1-42-…" \
-H "Content-Type: application/json" \
-d '{"name": "Wöchentlicher Report", "steps": [{"step": "Fasse die Woche zusammen"}]}'

# Ausführen.
curl -sS -X POST \
https://your-instance.platform.basepeak.ai/api/projects/p1abc/tasks/w1abc123/run \
-H "Authorization: Bearer sk-bpai-1-42-…" \
-H "Content-Type: application/json" -d '{}'

# Läufe lesen.
curl -sS https://your-instance.platform.basepeak.ai/api/projects/p1abc/tasks/w1abc123/runs \
-H "Authorization: Bearer sk-bpai-1-42-…"
Es gibt kein flaches POST /api/tasks

Aufgaben anlegen funktioniert ausschließlich über diese projektbezogene Route. Die flache Oberfläche unter Management-API kann eine bestehende Aufgabe lesen, ändern und ausführen (Scope task:manage), aber nie eine neue erzeugen.

task:manage und project:tasks sind kein Ober-/Unterbegriff

Die beiden überschneiden sich, ohne dass einer den anderen enthält:

ScopeReichweite
task:manage (nur *)Jede Aufgabe, die dem Konto des Schlüssels gehört – über alle Projekte hinweg, ohne Möglichkeit, auf ein einzelnes Projekt zu pinnen. Lesen, Ändern, Ausführen; kein Anlegen.
project:tasks:<p>Jede Aufgabe in genau diesem Projekt – auch eine, die dem Konto nur über eine ThreadAuthorization-Freigabe zugänglich ist, nicht über Eigentum. Genau dieser Fall bleibt für die flache Oberfläche (GET /api/tasks) unsichtbar, da sie ausschließlich nach Eigentum filtert.

Ein Schlüssel mit project:tasks:p1abc erreicht also Aufgaben eines Projekts, das dem Konto nur freigegeben wurde – etwas, das kein task:manage-Schlüssel je könnte, unabhängig von dessen Reichweite.

Umgebungsvariablen: zwei unabhängige Hälften

GET /api/projects/{project_id}/env
PUT /api/projects/{project_id}/env
RouteScope
GETproject:env:<project_id>
PUTproject:env-write:<project_id>
project:env und project:env-write implizieren sich nicht gegenseitig

Anders als bei Dateien und Wissen ist die Schreib-Hälfte hier keine Erweiterung der Lese-Hälfte. GET /api/projects/{project_id}/env liefert die gespeicherten Werte der Umgebungsvariablen zurück – das sind die Geheimnisse, die die Werkzeuge des Projekts benutzen. Ein Schlüssel mit nur project:env-write kann Werte setzen, aber nicht lesen; ein Schlüssel mit nur project:env kann sie lesen, aber nicht ändern. Wer beides braucht, muss beide Scopes ausstellen.

Der Grund für den Bruch mit dem sonstigen Muster: Ein Schlüssel, der nur ein Geheimnis rotieren soll, muss es nie lesen können.

# Werte setzen.
curl -sS -X PUT https://your-instance.platform.basepeak.ai/api/projects/p1abc/env \
-H "Authorization: Bearer sk-bpai-1-42-…" \
-H "Content-Type: application/json" \
-d '{"API_TOKEN": "sk-live-…"}'

# Werte lesen – erfordert project:env, nicht project:env-write.
curl -sS https://your-instance.platform.basepeak.ai/api/projects/p1abc/env \
-H "Authorization: Bearer sk-bpai-1-42-…"

Scopes im Überblick

RouteBenötigter Scope
POST /api/projects/{p}/invoke, .../invoke/thread(s)/{thread}project:chat:<p>
GET /api/projects/{p}/files, .../file(s)/{file}project:files:<p> oder project:files-write:<p>
POST/DELETE /api/projects/{p}/file(s)/{file}project:files-write:<p>
GET /api/projects/{p}/knowledge, .../knowledge/{file}project:knowledge:<p> oder project:knowledge-write:<p>
POST/DELETE /api/projects/{p}/knowledge/{file}project:knowledge-write:<p>
POST/GET/PUT/DELETE /api/projects/{p}/tasks…project:tasks:<p>
GET /api/projects/{p}/envproject:env:<p>
PUT /api/projects/{p}/envproject:env-write:<p>

Alle acht Scopes gründen ausschließlich auf Projektmitgliedschaft – keine Management-Berechtigung ist nötig, um irgendeinen von ihnen auszustellen, auch nicht die schreibenden Hälften: Die Browser-Sitzung verlangt für dieselben Mutationen ebenfalls nichts weiter als Zugriff auf das Projekt, und diese Scopes verlangen nicht mehr. Das unterscheidet sie von agent:files-write, dessen Ausstellung zusätzlich agent:update voraussetzt – siehe API-Schlüssel.

Ein Schlüssel mit Platzhalter (project:chat:* etc.) wird bei jedem Aufruf gegen die aktuelle Projektmitgliedschaft des zugehörigen Kontos geprüft – verliert das Konto den Zugriff auf ein Projekt, greift ein solcher Scope für dieses Projekt sofort nicht mehr.

Was über die API weiterhin nicht erreichbar ist

Drei Projekt-Oberflächen bleiben Schlüsseln verschlossen, nicht aus Versehen, sondern weil sie wer ein Projekt erreichen darf ändern statt es zu bedienen:

Nicht erreichbarWarum
Projekt-MitgliederÄndert, wer das Projekt erreicht – Browser-Sitzung, nicht Integrationsrecht.
Projekt-EinladungenDasselbe: ein kompromittierter Schlüssel soll niemanden ins Projekt einladen können.
Projekt-Anmeldedaten (Verwaltung)Gibt gespeicherte Geheimnisse heraus – anders als project:env, das gezielt für genau diesen Zweck existiert.

Fehlerbehebung

AntwortBedeutung
400Die Projekt-ID ist keine p1…-ID (oder das Alias default, das sich pro Konto auflöst und sich daher nicht mit einem Scope abgleichen lässt).
403Die Scopes decken das Projekt nicht ab, oder das Konto des Schlüssels hat keinen Zugriff mehr auf dieses Projekt. Ein Scope für Projekt A greift nie für Projekt B.
425Die Wissenssammlung des Projekts existiert noch nicht – siehe oben, erneut versuchen.

Weiterführende Dokumentation

  • API-Schlüssel – die neun Projekt-Scopes im Kontext aller Scopes
  • Invoke-API – der Ereignisstrom, den beide Routen teilen
  • Threads – Fortsetzen, Pollen, async
  • Dateien – der Arbeitsbereich des Projekts neben Agent und Thread