Die vollständige REST-Endpunktreferenz. Für Tutorials und Beispiele siehe den API-Leitfaden.
Alles, was ein Projektmitglied in der Web-Benutzeroberfläche tun kann, ist hier verfügbar — die SPA nutzt dieselbe API. Operationen, die die Manager-Rolle erfordern, sind mit (manager) markiert; alles andere benötigt nur die Projektmitgliedschaft (oder, für mit (viewer) markierte Lesevorgänge, jede Zugriffsebene). Die Tabellen unten benennen jede Routengruppe, die der Server einhängt; die in einer einzigen Zeile zusammengefassten sind vollständig in der Live-openapi.json beschrieben.
https://eastagiletracker.com/api/v1https://api.eastagiletracker.com/api/v1 liefert die identische API. Alle Anfragen und Antworten sind JSON, außer ein paar Datei-Upload-Endpunkten, die Multipart akzeptieren.
Zwei Gruppen liegen eine Ebene höher, unter /api statt /api/v1: die Authentifizierungsfläche (/api/auth/*) und die öffentlichen Formulare (/api/contact, /api/feedback). Ihre /api/v1/…-Schreibweisen geben 404 zurück.
Authentifizierung
Abschnitt betitelt „Authentifizierung“Jede authentifizierte Anfrage sendet ein Zugangsdatum über einen von:
X-TrackerToken: <key>Authorization: Bearer <key>
Benutzerschlüssel beginnen mit ea_user_, Agenten-Schlüssel mit ea_agent_ und MCP-Zugriffstokens mit ea_mcp_. Siehe API-Leitfaden → Drei Arten von Zugangsdaten.
Nicht authentifizierte Endpunkte: /openapi.json, /docs, die /api/auth/*-Endpunkte und die Referenzdaten-Lookups (/story_types, /story_states, /effort_scales, /priority_scales). /meta ist authentifiziert — jeder gültige Schlüssel funktioniert, aber er ist nicht projektbezogen (auch ein projektgebundener Agenten-Schlüssel erreicht ihn).
Vier Ebenen steuern projektbezogene Endpunkte:
| Ebene | Wer passiert | Typische Operationen |
|---|---|---|
| public viewer | jeder, bei einem Projekt mit öffentlicher Sichtbarkeit | Lesevorgänge des Boards: Stories, Iterationen, Suche, Story- und Epic-Aktivität (mit geschwärzten Akteursdaten) |
| viewer | viewer, member, manager | Lesevorgänge (Stories listen/abrufen, Suche, Metriken, Liste der Exportformate) |
| member | member, manager | alle Schreibvorgänge auf Arbeitselementen (Stories, Tasks, Kommentare, …), der Event-Stream |
| manager | nur manager | Projekteinstellungen, Mitgliedschaftsverwaltung, Agenten-Schlüssel, Löschen, Import, Export-Downloads, Backups, Audit-Log |
Agenten tragen dieselben Rollen wie Mitglieder — viewer, member oder manager — gedeckelt auf die Rolle des Mitglieds, das den Schlüssel ausgestellt hat. Ein Nicht-Mitglied erhält 404 unfound_resource (nicht 403) auf Pfaden privater Projekte, sodass Projekt-IDs nicht aufzählbar sind.
Selbstbeschreibende Endpunkte
Abschnitt betitelt „Selbstbeschreibende Endpunkte“| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /openapi.json | Die Live-OpenAPI-3-Spezifikation, Request-Bodies eingeschlossen. Nicht authentifiziert. |
| GET | /docs | Swagger UI. Nicht authentifiziert. |
| GET | /meta | Aufrufer-Identität (auth.kind/key_id/agent_id/project_id) + der Transition-Graph pro Story-Typ. Authentifiziert (jeder gültige Schlüssel; nicht projektbezogen). Rufen Sie dies zuerst auf. |
| GET | /api/health · /api/config | Lebenszeichen und die öffentliche Konfiguration des Deployments (Einzelorganisationsmodus, aktivierte optionale Funktionen, Name der Instanz). Nicht authentifiziert, außerhalb von /v1. |
Auth (/api/auth/*, außerhalb von /v1)
Abschnitt betitelt „Auth (/api/auth/*, außerhalb von /v1)“Sitzungs-Endpunkte, nicht authentifiziert, sofern nicht anders vermerkt. Die SPA treibt diese an; Skripte verwenden normalerweise stattdessen einen API-Schlüssel.
| Methode | Pfad | Beschreibung |
|---|---|---|
| POST | /auth/register | Ein neues Konto registrieren — durch reCAPTCHA geschützt; das Konto durchläuft anschließend die SMS-Prüfung |
| POST | /auth/sms/challenge · /auth/sms/status · /auth/sms/bypass | Den Registrierungs-SMS-Code senden / prüfen (der Bypass ist dem Betreiber vorbehalten) |
| GET | /auth/config | Welche Anmeldemethoden das Deployment anbietet |
| POST | /auth/login | Mit E-Mail + Passwort anmelden; gibt ein Sitzungs-JWT zurück oder eine TOTP-Aufforderung |
| POST | /auth/login/totp | Eine Anmeldung mit einem Authenticator-Code oder einem Wiederherstellungscode abschließen |
| POST | /auth/passkey/login/start · /auth/passkey/login/finish | Passwortlose WebAuthn-Anmeldung |
| GET | /auth/oauth/github/start · /auth/oauth/github/callback · /auth/oauth/google/start · /auth/oauth/google/callback · POST /auth/oauth/exchange | OAuth-Anmeldung mit GitHub oder Google |
| POST | /auth/refresh · /auth/refresh/revoke | Das Refresh-Token rotieren / widerrufen |
| POST | /auth/logout | Abmelden (widerruft das Refresh-Token) |
| POST | /auth/forgot-password · /auth/reset-password | Eine Zurücksetzungs-E-Mail anfordern / das Reset-Token verwenden |
| POST | /auth/accept-invite/lookup · /auth/accept-invite | Ein Einladungs-Token → E-Mail auflösen / die Projekteinladung annehmen (nach der Authentifizierung) |
Konto / Identität
Abschnitt betitelt „Konto / Identität“Diese wirken auf den Aufrufer und benötigen nur einen gültigen Schlüssel (keine Projektrolle).
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /me | Aktuelles Benutzerprofil |
| PUT | /me | Profil aktualisieren |
| DELETE | /me | Konto löschen — abgelehnt, solange Sie alleiniger Eigentümer einer Organisation oder eines Projekts mit weiteren Mitgliedern sind |
| GET | /me/deletion-impact | Was das Löschen des Kontos entfernen würde und was es blockiert |
| PUT | /me/password | Passwort ändern |
| PUT | /me/settings | Einstellungen aktualisieren (Theme, Benachrichtigungspräferenzen) |
| POST | /me/avatar | Avatar hochladen (Multipart) |
| POST | /me/api-token/regenerate | Ihr API-Token rotieren — macht bestehende Sitzungen/Schlüssel ungültig |
| GET | /me/api_keys · POST /me/api_keys · DELETE /me/api_keys/{id} | Benutzer- (ea_user_) API-Schlüssel verwalten |
| GET | /me/totp · POST /me/totp/setup · /me/totp/verify · /me/totp/disable | Zwei-Faktor-Einrichtung (TOTP); verify gibt die Wiederherstellungscodes einmalig zurück |
| GET | /me/passkeys · POST /me/passkeys/register/start · /me/passkeys/register/finish · DELETE /me/passkeys/{credential_id} | Passkeys registrieren und entfernen |
| GET | /me/oauth_grants · DELETE /me/oauth_grants/{grant_id} | Verbundene Apps — die MCP-Clients und OAuth-Apps, die Sie autorisiert haben |
| GET | /me/activity | Ihre Aktivität über alle Projekte hinweg |
| GET | /me/stories | Stories, die Sie besitzen, angefordert haben oder verfolgen, über jedes Projekt hinweg, das das Token erreicht — role=owned|requested|following, state=, cursor= / limit= (max. 200) |
| GET | /me/mentions · POST /me/mentions/{mention_id}/ack | Der @-Mention-Posteingang (unacked=true zum Filtern) und die Bestätigung — auch in den Benachrichtigungsfeed unten eingefügt |
| GET | /me/data-export | DSGVO-Selbstexport Ihrer Daten |
| GET | /me/consent · POST /me/consent | Einwilligung lesen / aufzeichnen ({ consent_type, granted }) |
| GET | /legal/pending · POST /legal/accept | Ausstehende Clickwrap-Dokumente / Annahme aufzeichnen |
| GET / PUT | /agent/me | Identität und Profil eines Agenten-Schlüssels, vom Agenten lesbar und bearbeitbar (das agentenseitige Gegenstück zu /me) |
| POST | /api/contact · /api/feedback · /api/feedback/with-screenshot | Kontakt + In-App-Feedback. Außerhalb von /v1; pro IP ratenbegrenzt |
Referenzdaten (nicht authentifiziert)
Abschnitt betitelt „Referenzdaten (nicht authentifiziert)“Seed-Lookups, die beim Erstellen/Schätzen von Stories verwendet werden. Stabile IDs.
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /story_types | feature, bug, chore, release (+ allow_points) |
| GET | /story_states | unstarted … accepted, rejected |
| GET | /effort_scales | verfügbare Schätzskalen |
| GET | /effort_scales/{scale_id}/values | die Punktewerte in einer Skala |
| GET | /priority_scales · /priority_scales/{scale_id}/values | die Prioritätsskalen und ihre Werte (die priority_id einer Story wird hier aufgelöst) |
Organisationen
Abschnitt betitelt „Organisationen“Nur im gehosteten Dienst — eine selbst gehostete Installation läuft im Einzelorganisationsmodus und hängt diese Routen nicht ein (außer der Organisationsliste). Die Rollen sind Organisationsrollen: owner, admin, member.
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET / POST | /organizations | Ihre Organisationen auflisten / eine erstellen |
| GET / PUT / DELETE | /organizations/{oid} | Lesen, umbenennen (Name + Slug; owner oder admin), löschen |
| GET / POST | /organizations/{oid}/memberships · PUT / DELETE …/memberships/{member_id} | Mitglieder und Einladungen; eine Einladung trägt eine Rollenobergrenze (nie über der des Aufrufers; die owner-Rolle wird nie per Einladung vergeben) |
| POST | /organizations/{oid}/memberships/bulk-role · …/memberships/bulk-remove | Rolle von bis zu 200 Mitgliedern auf einmal ändern oder sie entfernen. Alles oder nichts: Ein Batch, der den letzten Owner entfernen oder ein Projekt ohne Eigentümer zurücklassen würde, wird vollständig abgelehnt; mit reassign_confirmed werden Sie stattdessen Eigentümer dieser Projekte |
| DELETE | /organizations/{oid}/invitations/{invitation_id} | Eine ausstehende Einladung widerrufen |
| POST | /organizations/{oid}/transfer-ownership | Die owner-Rolle an ein anderes Mitglied übergeben |
| PUT | /organizations/{oid}/memberships/{member_id}/anonymization | Name / E-Mail / Avatar eines Mitglieds organisationsweit maskieren |
| GET | /organization-invitations/{token} · POST …/{token}/accept | Eine per E-Mail erhaltene Organisationseinladung auflösen / annehmen |
| POST | /organizations/{oid}/export · GET / POST …/export/jobs · GET …/export/jobs/{job_id} · …/export/jobs/{job_id}/download | Organisationsexport nur für den owner: ein zip mit einem SQL-Dump und jedem Anhang, als Job ausgeführt |
Projekte
Abschnitt betitelt „Projekte“| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /projects | Ihre Projekte auflisten (limit ≤ 200) |
| POST | /projects | Ein Projekt erstellen |
| GET | /projects/{id} | Projektdetails abrufen (viewer) |
| PUT | /projects/{id} | Projekteinstellungen aktualisieren (manager) |
| DELETE | /projects/{id} | Ein Projekt löschen (manager) |
| POST | /projects/{id}/pin | Das Projekt in Ihrer Projektliste anheften / lösen |
| POST | /projects/{id}/transfer-organization | Das Projekt in eine andere Organisation verschieben (manager) |
| POST | /projects/{id}/slack/test | Eine Testnachricht an den Slack-Feed des Projekts senden (manager) |
| GET / POST | /projects/{id}/showcase_claim_eligibility · /projects/{id}/showcase_claim · /projects/{id}/showcase_seed | Öffentliche Showcase-Projekte: prüfen, ob Sie eines übernehmen können, es übernehmen, es mit Daten befüllen |
| GET | /projects/{id}/audit-log | Audit-Log-Lesezugriff — Projekthistorie plus Aktivität pro Story / pro Epic über surface=; Zugriff variiert je nach Surface, siehe unten |
| GET | /projects/{id}/events | Cursor-paginierter Event-Stream (member) — siehe Events |
Query-Parameter des Audit-Logs: event_type= (ein Typ oder kommaseparierte Liste), limit= (≤ 1000), before= (Keyset-Cursor, ISO-8601 created_at), surface= (project_history, story_activities, epic_activities), target_id= (die Story-/Epic-ID — erforderlich bei surface=story_activities oder epic_activities). Zugriff: das ungefilterte Log und surface=project_history sind (manager); story_activities / epic_activities kann jedes Projektmitglied lesen, bei öffentlichen Projekten auch anonym mit geschwärzten personenbezogenen Akteursdaten.
Mitglieder, Agenten und Agenten-Schlüssel
Abschnitt betitelt „Mitglieder, Agenten und Agenten-Schlüssel“| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /projects/{id}/memberships | Mitglieder auflisten (viewer) |
| POST | /projects/{id}/memberships | Ein Mitglied per E-Mail einladen (manager) |
| PUT | /projects/{id}/memberships/{mid} | Rolle aktualisieren (manager) |
| DELETE | /projects/{id}/memberships/{mid} | Ein Mitglied entfernen (manager) |
| GET | /projects/{id}/addable-members · POST /projects/{id}/members/add-existing | Organisationsmitglieder, die noch nicht im Projekt sind / eines ohne E-Mail-Einladung hinzufügen (manager) |
| POST | /projects/{id}/members/join | Ein owner oder admin der Organisation tritt einem Projekt seiner Organisation als manager bei oder stuft sich selbst zum manager hoch (die Aktion Make me owner in der Projektliste) |
| PUT | /projects/{id}/members/{mid}/anonymization | Name / E-Mail / Avatar eines Mitglieds in diesem Projekt maskieren (manager) |
| GET / POST | /projects/{id}/agent_keys | Agenten-Schlüssel auflisten / ausstellen — Manager oder die Rollen, die die Richtlinie des Projekts für Schlüsselersteller zulässt |
| DELETE | /projects/{id}/agent_keys/{kid} | Einen Agenten-Schlüssel widerrufen |
| GET | /projects/{id}/agent_keys/onboarding | Das Onboarding-Paket: Prompts und Konfigurationsdateien für die gängigen Agenten-Clients |
| GET | /projects/{id}/agents · GET / PUT /projects/{id}/agents/{aid} | Die Agenten des Projekts und ihre Profile (Name, Initialen, Beschreibung, Farbe) |
| POST | /projects/{id}/agents/{aid}/rotate-key · /projects/{id}/agents/{aid}/avatar | Den Schlüssel eines Agenten rotieren (Identität und Historie bleiben erhalten) / seinen Avatar hochladen |
Stories
Abschnitt betitelt „Stories“Alle Schreibvorgänge auf Stories benötigen die member-Rolle.
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /projects/{id}/stories | Stories auflisten (paginiert, filterbar) (viewer) |
| POST | /projects/{id}/stories | Eine Story erstellen |
| GET | /projects/{id}/stories/{sid} | Eine Story abrufen (viewer) |
| PUT | /projects/{id}/stories/{sid} | Eine Story aktualisieren |
| DELETE | /projects/{id}/stories/{sid} | Eine Story löschen |
| POST | /projects/{id}/stories/{sid}/transitions | Zustand mit Validierung ändern |
| POST | /projects/{id}/stories/{sid}/reject · /projects/{id}/stories/{sid}/restart | Eine gelieferte Story ablehnen / eine abgelehnte zurück auf started setzen (rejected ist für /transitions ein Endzustand) |
| POST | /projects/{id}/stories/{sid}/archive · /projects/{id}/stories/{sid}/unarchive | Eine Story archivieren / dearchivieren |
| POST | /projects/{id}/stories/bulk_transition | Viele Stories (1–100) auf einmal wechseln |
| POST | /projects/{id}/stories/bulk-archive · bulk-delete · bulk-duplicate · bulk-move | Viele Stories archivieren, löschen, duplizieren oder verschieben (in ein Panel / an eine Position) |
| POST | /projects/{id}/stories/{sid}/duplicate | Eine Story duplizieren |
| GET / POST / DELETE | /projects/{id}/stories/{sid}/epics · …/epics/{eid} | Die Epic-Zugehörigkeit der Story |
| GET | /short-links/{code} · /story-references | Einen /s/<code>-Kurzlink zu seiner Story auflösen / bis zu 100 Story-Referenzen (#id, URLs) zu den Stories auflösen, die der Aufrufer lesen kann |
Query-Parameter für Story-Listen: archived= (exclude Standard / include / only — der dreistufige Archiv-Filter; ersetzt das veraltete include_archived=true, das jetzt ein Alias für archived=include ist), include_done=true (lässt Done-Panel-Stories zu, die auf vergangenen Iterationen eingefroren sind; standardmäßig ausgeschlossen). Paginierung (cursor= / limit= / offset=) und schlanke Feldmengen (fields=) folgen Paginierung und Feldprojektion.
Erstellen (POST …/stories): { "name" (required), "story_type": "feature|bug|chore|release", "description"?, "estimate"?, "current_state"?, "icebox"?, "labels"? }. estimate ist das Label des Skalenwerts als String ("3", "13"); eine JSON-Zahl wird abgelehnt. labels akzeptiert ["auth"] oder [{ "name": "auth" }]; unbekannte Labels werden erstellt. Voreinstellungen: story_type=feature, current_state=unstarted.
Aktualisieren (PUT …/stories/{sid}): dieselben Felder, alle optional, plus "position" (float), "force_state_change" (bool) und "expected_updated_at" (RFC 3339 — das Speichern einer Beschreibung wird mit 409 stale_write abgelehnt, wenn sich die Story seit Ihrem Lesen geändert hat). Story-Schreibvorgänge berücksichtigen außerdem If-Match gegen das ETag der Story; eine Abweichung ergibt 412 precondition_failed.
Transition (POST …/transitions): { "to": "<state>" }. Das Feld ist to. Gibt { story_id, state } zurück. Unzulässige Bewegung → 422 invalid_transition mit details: { from, to, allowed }.
Massen-Transition (POST …/bulk_transition): { "story_ids": [int,…] (1–100), "to": "<state>" }. Jede Story wird unabhängig beurteilt; gibt { results: [ { id, status: "ok" } | { id, status: "failed", error } ] } zurück.
Story-Unterressourcen
Abschnitt betitelt „Story-Unterressourcen“Alle member. List/GET ist bei den meisten (viewer).
| Methode | Pfad | Body / Hinweise |
|---|---|---|
| GET / POST | /projects/{id}/stories/{sid}/tasks · PUT/DELETE …/tasks/{tid} | { description (or task_desc), complete?, task_order? } |
| GET / POST | /projects/{id}/stories/{sid}/comments · PUT/DELETE …/comments/{cid} | { text (or comment_text) } oder { comment_emoji }. GET nimmt fields= (Allowlist: comment_id, story_comment_id, story_id, comment_text, comment_emoji, member, created) sowie cursor= / limit= (≤ 200) / order=asc|desc |
| GET / POST | /projects/{id}/stories/{sid}/blockers · PUT/DELETE …/blockers/{bid} | { blocker_desc, resolved? } |
| GET / POST | /projects/{id}/stories/{sid}/links · PUT/DELETE …/links/{lid} | { url, link_type?, title? } — link_type ∈ relates_to, duplicates, blocks, is_blocked_by, pull_request, branch, other; GitHub-URLs mit /pull/ und /tree/ werden automatisch typisiert |
| GET / POST | /projects/{id}/stories/{sid}/reviews · PUT/DELETE …/reviews/{rid} | Erstellen: { reviewer_id? / reviewer_agent_id?, comment? } — beides weglassen, um sich selbst zuzuweisen. Aktualisieren: { status, comment? } |
| GET / POST | /projects/{id}/stories/{sid}/owners · DELETE …/owners/{mid} · DELETE …/owners/agents/{aid} | { member_id? / agent_id? } — beides weglassen, um den Aufrufer hinzuzufügen |
| GET / POST | /projects/{id}/stories/{sid}/followers · DELETE …/followers/{mid} · DELETE …/followers/agents/{aid} | { member_id? / agent_id? } |
| GET / POST | /projects/{id}/stories/{sid}/labels · DELETE …/labels/{lid} | { name } |
| GET / POST | /projects/{id}/stories/{sid}/attachments (+ /json) · DELETE …/attachments/{aid} | Multipart-Upload — Video ≤ 200 MB, PDF / Word / Excel ≤ 25 MB, Bilder / CSV / Text ≤ 10 MB; Liste ist (viewer) |
| GET / POST | /projects/{id}/stories/{sid}/link-attachments · DELETE …/link-attachments/{laid} | Link-Anhänge — eine externe URL, die neben den Dateianhängen statt als Code-Link geführt wird |
| GET | /attachments/{token} · /api/avatars/{token} | Token-adressierte Lesezugriffe auf einen Anhang oder einen Avatar — die URLs, die die API ausgibt; kein X-TrackerToken nötig |
Dieselbe Form wie Stories, ohne die Zustandsmaschine. member für Schreibvorgänge, (viewer) für Lesevorgänge.
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET / POST | /projects/{id}/epics · GET / PUT / DELETE …/epics/{eid} | Epics haben einen Namen, eine Markdown-Beschreibung und ein zugehöriges Label, das ihre Stories verbindet |
| GET / POST / PUT / DELETE | …/epics/{eid}/comments · …/comments/{cid} | Epic-Kommentare |
| GET / POST / DELETE | …/epics/{eid}/owners · …/followers (+ /agents/{aid}-Varianten) | Eigentümer und Follower, Mitglieder oder Agenten — die Eigentümer eines Epics werden an seine Stories weitergegeben |
| GET / POST / DELETE | …/epics/{eid}/attachments (+ /json) · …/link-attachments | Anhänge, dieselben Obergrenzen wie bei Stories |
| GET | /projects/{id}/analytics/epics · …/analytics/epics/{eid} | Fortschritt pro Epic: Burnup, Durchsatz, Gesundheit, Prognose (viewer) |
member für Schreibvorgänge, (viewer) für Lesevorgänge.
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET / POST | /projects/{id}/labels | Ein Label auflisten / erstellen |
| PUT / DELETE | /projects/{id}/labels/{lid} | Ein Label aktualisieren / löschen |
| POST | /projects/{id}/labels/{lid}/archive | Ein Label archivieren (sanft ausblenden) |
Iterationen
Abschnitt betitelt „Iterationen“Lesezugriffe stehen jeder Projektrolle offen und sind bei einem öffentlichen Projekt auch anonym möglich.
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /projects/{id}/iterations | Iterationen auflisten (≤ 500 pro Seite; trägt ein ETag und bei Kürzung die X-Tracker-Pagination-*-Fortsetzungs-Header) |
| GET | /projects/{id}/iterations/{itid} | Eine Iteration |
| GET | /projects/{id}/iterations/first-preview | Die Daten, die die erste Iteration erhalten würde, angezeigt in der Bestätigung beim Anlegen |
| POST | /projects/{id}/iterations | Eine manuelle Iteration erstellen (member) |
| DELETE | /projects/{id}/iterations/{itid} | Eine Iteration löschen (manager) |
| PUT | /projects/{id}/iterations/{itid}/velocity | Die Velocity einer Iteration übersteuern, ohne die Projektstrategie zu ändern (manager) |
| GET | /projects/{id}/iterations/{itid}/done-stories | Die akzeptierten Stories einer abgeschlossenen Iteration, paginiert |
Suche, Metriken, Präferenzen
Abschnitt betitelt „Suche, Metriken, Präferenzen“| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /projects/{id}/search?q=… | Mächtige Suche — Volltext + Facetten- / Datumsbereichs- / Personen-Qualifier (DSL im GitHub-Stil); gibt { results, total, limit, offset } zurück. query ist ein Alias für q; limit= (Standard 50, max. 1000) / offset= paginieren; sort= sortiert nach relevance (Standard), created, created_asc, state oder updated. (viewer) — siehe den Leitfaden |
| GET | /projects/{id}/metrics/{velocity,burndown,story-types,contributors} | Die Datenreihen der Metrics-Seite (viewer); Epic-Metriken liegen oben unter /analytics/epics |
| GET | /projects/{id}/backlog/grouping | Die projizierten Iterationsgruppen des Backlogs (viewer) |
| GET / PUT | /projects/{id}/preferences | Ihre Board-Präferenzen für dieses Projekt — jede Projektrolle, nur Ihre eigene Zeile |
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /projects/{id}/events | Cursor-paginierter Event-Stream (member) — Viewer erhalten 403 |
Query-Parameter: since=<event_id>, types=story.created,story.transitioned,comment.added,…, limit= (≤ 500), cursor=. Die Antwort enthält next_cursor. Übergeben Sie die letzte event_id, die Sie gesehen haben, als since, um fortzufahren.
Benachrichtigungen
Abschnitt betitelt „Benachrichtigungen“Der vereinheitlichte In-App-Benachrichtigungsfeed: eigenständige Benachrichtigungszeilen (Review-Anfragen, Story-Aktivität, Einladungen, …) zusammengeführt mit dem @-Mention-Posteingang zu einem Stream, Neueste zuerst. Feed-Ids tragen ein Quellen-Präfix (nt-… / sc-… / ec-…). Mitglieder-Sessions und ea_user_*-Schlüssel lesen ihre Mitgliedszeilen; ea_agent_*-Schlüssel ihre Agentenzeilen.
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /me/notifications | Ihr Benachrichtigungsfeed. Filter: unread=true, since_id=, kind= (mentions / reviews / stories / invitations); Paginierung über cursor= / limit= |
| GET | /me/notifications/unread-count | Ungelesen-Zähler — { unread_count, by_category: { mentions, reviews, stories, invitations } } |
| POST | /me/notifications/read-all | Alles als gelesen markieren; liefert die frischen Zähler zurück |
| POST | /me/notifications/{id}/ack | Ein Element als gelesen markieren (idempotent) |
| POST | /me/notifications/{id}/accept | Eine Projekt-/Organisationseinladung aus dem Feed annehmen (nur Mitglieds-Token) |
| POST | /me/notifications/{id}/decline | Eine Projekt-/Organisationseinladung ablehnen (nur Mitglieds-Token) |
| GET | /me/notifications/resolve-invite?token=… | Ein per E-Mail erhaltenes Einladungstoken auf Ihre Benachrichtigungs-Id abbilden — { "id": "nt-…" } oder { "id": null } |
| GET | /me/notifications/stream | Live-Push — Server-Sent Events (text/event-stream); siehe unten |
Der Stream-Endpunkt ist kein JSON-Endpunkt und daher nicht in der OpenAPI-Spezifikation: Er hält die Verbindung offen und sendet bei jedem neuen Ereignis einen Frame ohne Payload ({"type":"notification","kind":…}), der den Client zum Neuladen des Feeds auffordert. Verbindungen werden serverseitig nach 45 Minuten beendet — neu verbinden und erneut authentifizieren. Nur Mitglieder-Sessions und ea_user_*-Schlüssel; ea_agent_*-Schlüssel erhalten 403.
Import (manager)
Abschnitt betitelt „Import (manager)“| Methode | Pfad | Beschreibung |
|---|---|---|
| POST | /projects/{id}/import | Datei-Quellen: source= ∈ pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat. Multipart file=. Synchron — antwortet mit den Ergebniszahlen. |
| POST | /projects/{id}/import/json | JSON-Body; source=github braucht keine Datei — owner, repo, optionales token und die Opt-in-Flags include_pull_requests / include_milestones / include_releases / include_dependencies; die Datei-Quellen senden file_base64. Asynchron: gibt 202 { import_id, status } zurück. Der Server ruft über GitHubs GraphQL-API ab, die anonyme Aufrufer ablehnt; ein Token erreicht GitHub also immer — Ihres oder das geteilte des Deployments. Siehe den Leitfaden. |
| GET | /projects/{id}/imports/{import_id} | Einen Job abfragen: status durchläuft pending → fetching → writing → done | failed, mit progress_current / progress_total während des Abrufs und den Ergebniszahlen bei done |
Pro Projekt läuft jeweils nur ein Import; ein zweiter POST, während einer läuft, ergibt 409 import_already_running. dry_run: true (JSON-Body oder dry_run=true Multipart) zeigt eine Vorschau jeder Quelle: analysiert, löst auf, dedupliziert, gibt dieselben { imported, skipped, errors, unmatched }-Zahlen zurück und macht dann alles rückgängig — nichts wird geschrieben. Limits: 10 MiB Body und 5.000 Stories pro Import für die dateibasierten Quellen (über einem der beiden → 400, nichts geschrieben). Die GitHub-Quelle ist unbegrenzt — sie schreibt in Blöcken statt in einer einzigen Transaktion. Der Re-Import ist idempotent pro Quell-ID — bereits importierte Zeilen werden übersprungen, nicht dupliziert.
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /projects/{id}/export/formats | Registrierte Formate: { id, name, content_type, drops, includes_archived }. Jede Projektrolle. |
| GET | /projects/{id}/export/{format} | Eines herunterladen (manager). Austausch: eat (volle Wiedergabetreue), jira, pivotal, shortcut, trello, asana, gitlab, linear, plane, plane_json; Dokumente: pdf, docx. |
| GET | /projects/{id}/export/attachments | Jeder Anhang als ein durchsuchbares zip (Dateien behalten ihre ursprünglichen Namen; JSON- und CSV-Manifest) (manager). |
Dokument-Exporte (pdf, docx) nehmen zusätzliche Query-Parameter: page_size= (letter Standard / a4 / legal / folio), from= / to= (Grenzen des Story-Fensters — RFC 3339 oder bloßes YYYY-MM-DD; eine Story liegt im Bereich, wenn ihr created oder completed_at hineinfällt), include_icebox= / include_backlog= (beide standardmäßig false, sodass ein teilbarer Export nur geplante / laufende Arbeit zeigt). Die Austausch-CSV-Formate ignorieren sie.
Backups und Wiederherstellungen (manager)
Abschnitt betitelt „Backups und Wiederherstellungen (manager)“| Methode | Pfad | Beschreibung |
|---|---|---|
| GET / POST | /projects/{id}/backups · GET …/backups/{snapshot_id} · …/backups/health | Snapshots auflisten, sofort einen erstellen, einen lesen, und die Zusammenfassung zum Zustand der Aufbewahrung |
| GET / POST | /projects/{id}/restores · POST …/restores/partial · GET …/restores/{restore_id} | Einen ganzen Snapshot oder ausgewählte Tabellen daraus wiederherstellen und die Wiederherstellung abfragen |
Die POSTs liegen in der Ratenbegrenzungsstufe Sensitive (siehe unten).
MCP- und OAuth-Anbieter
Abschnitt betitelt „MCP- und OAuth-Anbieter“East Agile Tracker ist ein OAuth-2.1-Anbieter für MCP-Clients. Ein Client entdeckt ihn unter /.well-known/oauth-authorization-server und /.well-known/oauth-protected-resource/mcp, schickt Sie zu /oauth/authorize (der Zustimmungsseite), tauscht den Code unter /oauth/token ein und spricht dann MCP unter /mcp mit dem resultierenden ea_mcp_*-Token. Grants werden unter /me/oauth_grants aufgelistet und widerrufen. Die Anbieter-Endpunkte haben eine eigene Ratenbegrenzungsstufe.
WebSocket
Abschnitt betitelt „WebSocket“wss://eastagiletracker.com/ws/control?token=<session JWT>Für interaktive UI-Fernsteuerung ({ "action": "get_state", "id": "req-1" }). Das Token ist ein Browser-Sitzungs-JWT — ein API-Schlüssel wird vor dem Upgrade mit 401 abgelehnt. Kein Datenkanal — alle Lese-/Schreibvorgänge laufen über REST. Nur Einzelinstanz; nicht über Replikate verteilt.
Idempotenz
Abschnitt betitelt „Idempotenz“Schreib-Endpunkte (POST, PUT, DELETE) akzeptieren einen Idempotency-Key-Header. Derselbe Schlüssel + derselbe Body spielt die zwischengespeicherte Antwort erneut ab (24-Stunden-Fenster); derselbe Schlüssel + ein anderer Body gibt 409 idempotency_conflict zurück. Der Schlüssel ist an das Zugangsdatum gebunden, das ihn gesendet hat. Nicht angewendet auf GET/HEAD/OPTIONS, /openapi.json und /docs, /api/auth/* oder Multipart-Uploads auf /attachments-Pfaden. Antworten, die vor einer fachlichen Antwort abbrachen, werden nie zwischengespeichert — 401, 403, 404, 429 und jede 5xx —, sodass ein Retry nach einer davon den Handler erreicht; 400, 409, 412 und 422 sind die fachliche Antwort und werden wie ein Erfolg erneut abgespielt.
Paginierung
Abschnitt betitelt „Paginierung“List-Endpunkte akzeptieren cursor=<opaque> und limit=<n>. Wenn gesetzt, ist die Antwort { "items": [...], "next_cursor": "<str|null>" }; übergeben Sie next_cursor zurück, um zu blättern. Die limit-Obergrenze gilt pro Endpunkt: 200 bei Stories, Kommentaren und Projekten; 500 bei Events; 1000 bei Suche und Audit-Log.
Eine einfache Liste (ohne cursor/limit), die ihre Antwort kürzen musste, zeigt dies in Headern an — X-Tracker-Pagination-Truncated, X-Tracker-Pagination-Limit, X-Tracker-Pagination-Offset und X-Tracker-Pagination-Next-Offset; übergeben Sie den letzten als offset= für die nächste Seite. Einen Header für die Gesamtzahl gibt es nicht.
Feldprojektion
Abschnitt betitelt „Feldprojektion“List-Endpunkte akzeptieren fields= (kommagetrennt), um nur bestimmte Felder zurückzugeben. story_id ist immer enthalten; ein unbekannter Feldname gibt 400 validation_failed mit den beanstandeten Namen in details.fields zurück.
GET /projects/123/stories?fields=story_id,name,current_state,ownersFehlerformat
Abschnitt betitelt „Fehlerformat“Jeder JSON-Fehler hat code und error; einige fügen details hinzu:
{ "code": "invalid_transition", "error": "Cannot move story from `unstarted` to `accepted`", "details": { "from": "unstarted", "to": "accepted", "allowed": ["started"] } }| Status | code | Wann |
|---|---|---|
| 400 | invalid_parameter | fehlerhafte Eingabe; Nachricht in error, kein details (die meiste Validierung: leer/Länge/Null-Byte/E-Mail) |
| 400 | validation_failed | strukturierter Eingabefehler; details.fields ist ein Array von beanstandeten Feldnamen |
| 401 | unauthenticated | fehlendes/ungültiges Token |
| 403 | unauthorized_operation | authentifiziert, aber unzureichende Rolle |
| 404 | unfound_resource | nicht gefunden — wird auch an Nicht-Mitglieder zurückgegeben |
| 409 | conflict | Ressourcenkonflikt (z. B. Duplikat) |
| 409 | idempotency_conflict | Idempotency-Key mit einem anderen Body wiederverwendet |
| 409 | stale_write · import_already_running | die Story hat sich seit Ihrem expected_updated_at geändert · ein Import läuft bereits |
| 412 | precondition_failed | If-Match stimmte nicht mit dem aktuellen ETag der Ressource überein; details trägt expected und current |
| 413 | request_too_large | der Body überschreitet die Größenbegrenzung der Route |
| 422 | invalid_transition | unzulässige Zustandsbewegung; details trägt { from, to, allowed } |
| 429 | rate_limited | zu viele Anfragen von dieser IP auf einer ratenbegrenzten Route; Retry-After-Header |
| 500 | internal_error | Serverfehler — generische Nachricht; sicher zu wiederholen |
| 503 | not_configured | dem Deployment fehlt die Integration, die diese Route benötigt (SMS, Objektspeicher, …) |
details.fields ist ein JSON-Array von Feldnamen (z. B. ["to"]), manchmal mit zusätzlichen Schlüsseln wie max. Es gibt keine Feld→Nachricht-Zuordnung.
{ "code": "validation_failed", "error": "unknown field(s): foo", "details": { "fields": ["foo"] } }Ratenbegrenzungen
Abschnitt betitelt „Ratenbegrenzungen“Pro Client-IP, auf einer Handvoll Routen; authentifizierter API-Verkehr ist anderswo nicht ratenbegrenzt. Standardwerte (jedes Paar ist Dauerrate und Burst, vom Betreiber einstellbar):
- Auth —
/api/auth/*: 0,5 req/s, Burst 20. - OAuth-Anbieter —
/oauth/*: 1 req/s, Burst 60. - Public —
/api/contact: 0,2 req/s, Burst 10. - Feedback —
/api/feedback: drei gestapelte Stufen — eine Übermittlung pro 15 s, 10 pro Stunde, 36 pro Tag. - Avatare — die nicht authentifizierte Avatar-Weiterleitung: 20 req/s, Burst 200.
- Sensitive — die
POSTs für Backup und Wiederherstellung: ~0,002 req/s, Burst 5.
Eine überschrittene Begrenzung gibt 429 mit einem Retry-After-Header und dem standardmäßigen JSON-Fehlerumschlag zurück, code: "rate_limited".