Zum Inhalt springen

API-Spezifikation

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 Owner-Rolle erfordern, sind mit (owner) markiert; alles andere benötigt nur die Projektmitgliedschaft (oder, für mit (viewer) markierte Lesevorgänge, jede Zugriffsebene).

https://eastagiletracker.com/api/v1

https://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.

Jede authentifizierte Anfrage sendet einen API-Schlüssel über einen von:

  • X-TrackerToken: <key>
  • Authorization: Bearer <key>

Benutzerschlüssel beginnen mit ea_user_. Agenten-Schlüssel beginnen mit ea_agent_. Siehe API-Leitfaden → Zwei Arten von Schlüsseln.

Nicht authentifizierte Endpunkte: /openapi.json, /docs, die /auth/*-Endpunkte und die Referenzdaten-Lookups (/story_types, /story_states, /effort_scales, …). /meta ist authentifiziert — jeder gültige Schlüssel funktioniert, aber er ist nicht projektbezogen (auch ein projektgebundener Agenten-Schlüssel erreicht ihn).

Drei Ebenen steuern projektbezogene Endpunkte:

EbeneWer passiertTypische Operationen
viewerviewer, member, ownerLesevorgänge (Stories listen/abrufen, Suche, Analytics)
membermember, owneralle Schreibvorgänge auf Arbeitselementen (Stories, Tasks, Kommentare, …)
ownernur ownerProjekteinstellungen, Mitgliedschaftsverwaltung, Agenten-Schlüssel, Löschen, Import, Audit-Log

Ein Nicht-Mitglied erhält 404 unfound_resource (nicht 403) auf Projektpfaden, sodass Projekt-IDs nicht aufzählbar sind.

MethodePfadBeschreibung
GET/openapi.jsonDie Live-OpenAPI-3-Spezifikation. Nicht authentifiziert.
GET/docsSwagger UI. Nicht authentifiziert.
GET/metaAufrufer-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.

Diese wirken auf den Aufrufer und benötigen nur einen gültigen Schlüssel (keine Projektrolle).

MethodePfadBeschreibung
POST/auth/registerEin neues Konto registrieren
POST/auth/loginAnmelden, gibt ein Sitzungs-Token zurück
POST/auth/logoutAbmelden
POST/auth/forgot-passwordEine Passwort-Zurücksetzungs-E-Mail anfordern
POST/auth/reset-passwordEin Reset-Token verwenden, um ein neues Passwort zu setzen
GET/auth/verify-emailEine E-Mail-Adresse verifizieren
POST/auth/accept-invite/lookupEin Einladungs-Token → E-Mail auflösen (nicht authentifiziert)
POST/auth/accept-inviteEine Projekteinladung annehmen (nach der Authentifizierung)
GET/meAktuelles Benutzerprofil
PUT/meProfil aktualisieren
DELETE/meKonto löschen
PUT/me/passwordPasswort ändern
PUT/me/settingsEinstellungen aktualisieren (Theme, Benachrichtigungspräferenzen)
POST/me/avatarAvatar hochladen (Multipart)
POST/me/api-token/regenerateIhr 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/activityIhre Aktivität über alle Projekte hinweg
GET/me/data-exportDSGVO-Selbstexport Ihrer Daten
GET/me/consent · POST /me/consentEinwilligung lesen / aufzeichnen ({ consent_type, granted })
GET/legal/pending · POST /legal/acceptAusstehende Clickwrap-Dokumente / Annahme aufzeichnen
POST/contact · POST /feedback · POST /feedback/with-screenshotKontakt + In-App-Feedback

Seed-Lookups, die beim Erstellen/Schätzen von Stories verwendet werden. Stabile IDs.

MethodePfadBeschreibung
GET/story_typesfeature, bug, chore, release (+ allow_points)
GET/story_statesunstarted … accepted, rejected
GET/effort_scalesverfügbare Schätzskalen
GET/effort_scales/{scale_id}/valuesdie Punktewerte in einer Skala
MethodePfadBeschreibung
GET/projectsIhre Projekte auflisten
POST/projectsEin Projekt erstellen
GET/projects/{id}Projektdetails abrufen (viewer)
PUT/projects/{id}Projekteinstellungen aktualisieren (owner)
DELETE/projects/{id}Ein Projekt löschen (owner)
GET/projects/{id}/audit-logProjekt-Aktivitätsstream (owner)
GET/projects/{id}/eventsCursor-paginierter Event-Stream (viewer) — siehe Events
MethodePfadBeschreibung
GET/projects/{id}/membershipsMitglieder auflisten (viewer)
POST/projects/{id}/membershipsEin Mitglied per E-Mail einladen (owner)
PUT/projects/{id}/memberships/{mid}Rolle aktualisieren (owner)
DELETE/projects/{id}/memberships/{mid}Ein Mitglied entfernen (owner)
GET / POST/projects/{id}/agent_keysAgenten-Schlüssel auflisten / ausstellen (owner)
DELETE/projects/{id}/agent_keys/{kid}Einen Agenten-Schlüssel widerrufen (owner)

Alle Schreibvorgänge auf Stories benötigen die member-Rolle.

MethodePfadBeschreibung
GET/projects/{id}/storiesStories auflisten (paginiert, filterbar) (viewer)
POST/projects/{id}/storiesEine 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}/transitionsZustand mit Validierung ändern
POST/projects/{id}/stories/bulk_transitionViele Stories (1–100) auf einmal wechseln
POST/projects/{id}/stories/bulk-deleteViele Stories löschen
POST/projects/{id}/stories/bulk-duplicateViele Stories duplizieren
POST/projects/{id}/stories/{sid}/duplicateEine Story duplizieren

Create (POST …/stories): { "name" (required), "story_type": "feature|bug|chore|release", "description"?, "estimate"?, "current_state"?, "icebox"?, "labels"? }. labels akzeptiert ["auth"] oder [{ "name": "auth" }]; unbekannte Labels werden erstellt. Voreinstellungen: story_type=feature, current_state=unstarted.

Update (PUT …/stories/{sid}): dieselben Felder, alle optional, plus "position" (float) und "force_state_change" (bool).

Transition (POST …/transitions): { "to": "<state>", "reason"? }. Das Feld ist to. Gibt { story_id, state } zurück. Unzulässige Bewegung → 422 invalid_transition mit details: { from, to, allowed }.

Bulk transition (POST …/bulk_transition): { "story_ids": [int,…] (1–100), "to": "<state>", "reason"? }. Jede Story wird unabhängig beurteilt; gibt { results: [ { id, status: "ok" } | { id, status: "failed", error } ] } zurück.

Alle member. List/GET ist bei den meisten (viewer).

MethodePfadBody / 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 / POST/projects/{id}/stories/{sid}/blockers · PUT/DELETE …/blockers/{bid}{ blocker_desc, resolved? }
GET / POST/projects/{id}/stories/{sid}/links · DELETE …/links/{lid}{ url, link_type?, title? }
GET / POST/projects/{id}/stories/{sid}/reviews · PUT/DELETE …/reviews/{rid}{ reviewer_id? / reviewer_agent_id?, 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 (≤ 2 GB pro Stück); Liste ist (viewer)

member für Schreibvorgänge, (viewer) für Lesevorgänge.

MethodePfadBeschreibung
GET / POST/projects/{id}/labelsEin Label auflisten / erstellen
PUT / DELETE/projects/{id}/labels/{lid}Ein Label aktualisieren / löschen
POST/projects/{id}/labels/{lid}/archiveEin Label archivieren (sanft ausblenden)
MethodePfadBeschreibung
GET/projects/{id}/iterationsIterationen auflisten (member)
POST/projects/{id}/iterationsEine manuelle Iteration erstellen (owner)
DELETE/projects/{id}/iterations/{itid}Eine Iteration löschen (owner)
MethodePfadBeschreibung
GET/projects/{id}/search?query=…Suche mit Filtersyntax (viewer) — siehe Leitfaden
GET/projects/{id}/analytics/{overview,iteration,releases,activity,cycle-time,projections}Analytics (viewer). Iterations-Drilldown nimmt ?iteration_id=
GET/projects/{id}/metrics/{velocity,burndown,story-types}Metriken (viewer)
GET / PUT/projects/{id}/preferencesIhre Board-Präferenzen für dieses Projekt (member)
MethodePfadBeschreibung
GET/projects/{id}/eventsCursor-paginierter Event-Stream (viewer)

Query-Parameter: since=<event_id>, types=story.created,story.transitioned,comment.created,…, limit=, cursor=. Die Antwort enthält next_cursor. Übergeben Sie die letzte event_id, die Sie gesehen haben, als since, um fortzufahren.

MethodePfadBeschreibung
POST/projects/{id}/import (+ /json)Multipart-Upload. source=pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json.
wss://eastagiletracker.com/ws/control?token=<key>

Für interaktive UI-Fernsteuerung ({ "action": "get_state", "id": "req-1" }). Kein Datenkanal — alle Lese-/Schreibvorgänge laufen über REST. Nur Einzelinstanz; nicht über Replikate verteilt.

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. Nicht angewendet auf GET/HEAD/OPTIONS, /auth/* oder /attachments-Pfade. 5xx-Antworten werden nie zwischengespeichert — ein Retry erreicht den Handler.

List-Endpunkte akzeptieren cursor=<opaque> und limit=<n≤200>. Wenn gesetzt, ist die Antwort { "items": [...], "next_cursor": "<str|null>" }; übergeben Sie next_cursor zurück, um zu blättern. Einige Listen geben auch einen X-Tracker-Pagination-Total-Header zurück.

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,owners

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"] } }
StatuscodeWann
400invalid_parameterfehlerhafte Eingabe; Nachricht in error, kein details (die meiste Validierung: leer/Länge/Null-Byte/E-Mail)
400validation_failedstrukturierter Eingabefehler; details.fields ist ein Array von beanstandeten Feldnamen
401unauthenticatedfehlendes/ungültiges Token
403unauthorized_operationauthentifiziert, aber unzureichende Rolle
404unfound_resourcenicht gefunden — wird auch an Nicht-Mitglieder zurückgegeben
409conflictRessourcenkonflikt (z. B. Duplikat)
409idempotency_conflictIdempotency-Key mit einem anderen Body wiederverwendet
422invalid_transitionunzulässige Zustandsbewegung; details trägt { from, to, allowed }
500internal_errorServerfehler — generische Nachricht; sicher zu wiederholen

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"] } }

Pro Schlüssel (pro IP für nicht authentifizierte Endpunkte), GCRA-Token-Bucket:

  • Auth/auth/*: 0,5 req/s, Burst 20.
  • Public/contact, /feedback: 0,2 req/s, Burst 10.
  • Sensitive — Passwort-Zurücksetzung: ~0,002 req/s, Burst 5.

Eine überschrittene Begrenzung gibt 429 Too Many Requests mit einem Retry-After-Header und einem Klartext-Body zurück (nicht der JSON-Fehlerumschlag).