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

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.

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:

EbeneWer passiertTypische Operationen
public viewerjeder, bei einem Projekt mit öffentlicher SichtbarkeitLesevorgänge des Boards: Stories, Iterationen, Suche, Story- und Epic-Aktivität (mit geschwärzten Akteursdaten)
viewerviewer, member, managerLesevorgänge (Stories listen/abrufen, Suche, Metriken, Liste der Exportformate)
membermember, manageralle Schreibvorgänge auf Arbeitselementen (Stories, Tasks, Kommentare, …), der Event-Stream
managernur managerProjekteinstellungen, 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.

MethodePfadBeschreibung
GET/openapi.jsonDie Live-OpenAPI-3-Spezifikation, Request-Bodies eingeschlossen. 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.
GET/api/health · /api/configLebenszeichen und die öffentliche Konfiguration des Deployments (Einzelorganisationsmodus, aktivierte optionale Funktionen, Name der Instanz). Nicht authentifiziert, 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.

MethodePfadBeschreibung
POST/auth/registerEin 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/bypassDen Registrierungs-SMS-Code senden / prüfen (der Bypass ist dem Betreiber vorbehalten)
GET/auth/configWelche Anmeldemethoden das Deployment anbietet
POST/auth/loginMit E-Mail + Passwort anmelden; gibt ein Sitzungs-JWT zurück oder eine TOTP-Aufforderung
POST/auth/login/totpEine Anmeldung mit einem Authenticator-Code oder einem Wiederherstellungscode abschließen
POST/auth/passkey/login/start · /auth/passkey/login/finishPasswortlose WebAuthn-Anmeldung
GET/auth/oauth/github/start · /auth/oauth/github/callback · /auth/oauth/google/start · /auth/oauth/google/callback · POST /auth/oauth/exchangeOAuth-Anmeldung mit GitHub oder Google
POST/auth/refresh · /auth/refresh/revokeDas Refresh-Token rotieren / widerrufen
POST/auth/logoutAbmelden (widerruft das Refresh-Token)
POST/auth/forgot-password · /auth/reset-passwordEine Zurücksetzungs-E-Mail anfordern / das Reset-Token verwenden
POST/auth/accept-invite/lookup · /auth/accept-inviteEin Einladungs-Token → E-Mail auflösen / die Projekteinladung annehmen (nach der Authentifizierung)

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

MethodePfadBeschreibung
GET/meAktuelles Benutzerprofil
PUT/meProfil aktualisieren
DELETE/meKonto löschen — abgelehnt, solange Sie alleiniger Eigentümer einer Organisation oder eines Projekts mit weiteren Mitgliedern sind
GET/me/deletion-impactWas das Löschen des Kontos entfernen würde und was es blockiert
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/totp · POST /me/totp/setup · /me/totp/verify · /me/totp/disableZwei-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/activityIhre Aktivität über alle Projekte hinweg
GET/me/storiesStories, 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}/ackDer @-Mention-Posteingang (unacked=true zum Filtern) und die Bestätigung — auch in den Benachrichtigungsfeed unten eingefügt
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
GET / PUT/agent/meIdentitä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-screenshotKontakt + In-App-Feedback. Außerhalb von /v1; pro IP ratenbegrenzt

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
GET/priority_scales · /priority_scales/{scale_id}/valuesdie Prioritätsskalen und ihre Werte (die priority_id einer Story wird hier aufgelöst)

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.

MethodePfadBeschreibung
GET / POST/organizationsIhre 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-removeRolle 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-ownershipDie owner-Rolle an ein anderes Mitglied übergeben
PUT/organizations/{oid}/memberships/{member_id}/anonymizationName / E-Mail / Avatar eines Mitglieds organisationsweit maskieren
GET/organization-invitations/{token} · POST …/{token}/acceptEine 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}/downloadOrganisationsexport nur für den owner: ein zip mit einem SQL-Dump und jedem Anhang, als Job ausgeführt
MethodePfadBeschreibung
GET/projectsIhre Projekte auflisten (limit ≤ 200)
POST/projectsEin 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}/pinDas Projekt in Ihrer Projektliste anheften / lösen
POST/projects/{id}/transfer-organizationDas Projekt in eine andere Organisation verschieben (manager)
POST/projects/{id}/slack/testEine 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-logAudit-Log-Lesezugriff — Projekthistorie plus Aktivität pro Story / pro Epic über surface=; Zugriff variiert je nach Surface, siehe unten
GET/projects/{id}/eventsCursor-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.

MethodePfadBeschreibung
GET/projects/{id}/membershipsMitglieder auflisten (viewer)
POST/projects/{id}/membershipsEin 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-existingOrganisationsmitglieder, die noch nicht im Projekt sind / eines ohne E-Mail-Einladung hinzufügen (manager)
POST/projects/{id}/members/joinEin 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}/anonymizationName / E-Mail / Avatar eines Mitglieds in diesem Projekt maskieren (manager)
GET / POST/projects/{id}/agent_keysAgenten-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/onboardingDas 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}/avatarDen Schlüssel eines Agenten rotieren (Identität und Historie bleiben erhalten) / seinen Avatar hochladen

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/{sid}/reject · /projects/{id}/stories/{sid}/restartEine 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}/unarchiveEine Story archivieren / dearchivieren
POST/projects/{id}/stories/bulk_transitionViele Stories (1–100) auf einmal wechseln
POST/projects/{id}/stories/bulk-archive · bulk-delete · bulk-duplicate · bulk-moveViele Stories archivieren, löschen, duplizieren oder verschieben (in ein Panel / an eine Position)
POST/projects/{id}/stories/{sid}/duplicateEine Story duplizieren
GET / POST / DELETE/projects/{id}/stories/{sid}/epics · …/epics/{eid}Die Epic-Zugehörigkeit der Story
GET/short-links/{code} · /story-referencesEinen /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.

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 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_typerelates_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.

MethodePfadBeschreibung
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-attachmentsAnhä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.

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)

Lesezugriffe stehen jeder Projektrolle offen und sind bei einem öffentlichen Projekt auch anonym möglich.

MethodePfadBeschreibung
GET/projects/{id}/iterationsIterationen 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-previewDie Daten, die die erste Iteration erhalten würde, angezeigt in der Bestätigung beim Anlegen
POST/projects/{id}/iterationsEine manuelle Iteration erstellen (member)
DELETE/projects/{id}/iterations/{itid}Eine Iteration löschen (manager)
PUT/projects/{id}/iterations/{itid}/velocityDie Velocity einer Iteration übersteuern, ohne die Projektstrategie zu ändern (manager)
GET/projects/{id}/iterations/{itid}/done-storiesDie akzeptierten Stories einer abgeschlossenen Iteration, paginiert
MethodePfadBeschreibung
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/groupingDie projizierten Iterationsgruppen des Backlogs (viewer)
GET / PUT/projects/{id}/preferencesIhre Board-Präferenzen für dieses Projekt — jede Projektrolle, nur Ihre eigene Zeile
MethodePfadBeschreibung
GET/projects/{id}/eventsCursor-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.

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.

MethodePfadBeschreibung
GET/me/notificationsIhr Benachrichtigungsfeed. Filter: unread=true, since_id=, kind= (mentions / reviews / stories / invitations); Paginierung über cursor= / limit=
GET/me/notifications/unread-countUngelesen-Zähler — { unread_count, by_category: { mentions, reviews, stories, invitations } }
POST/me/notifications/read-allAlles als gelesen markieren; liefert die frischen Zähler zurück
POST/me/notifications/{id}/ackEin Element als gelesen markieren (idempotent)
POST/me/notifications/{id}/acceptEine Projekt-/Organisationseinladung aus dem Feed annehmen (nur Mitglieds-Token)
POST/me/notifications/{id}/declineEine 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/streamLive-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.

MethodePfadBeschreibung
POST/projects/{id}/importDatei-Quellen: source=pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat. Multipart file=. Synchron — antwortet mit den Ergebniszahlen.
POST/projects/{id}/import/jsonJSON-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.

MethodePfadBeschreibung
GET/projects/{id}/export/formatsRegistrierte 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/attachmentsJeder 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.

MethodePfadBeschreibung
GET / POST/projects/{id}/backups · GET …/backups/{snapshot_id} · …/backups/healthSnapshots 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).

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.

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.

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.

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.

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
409stale_write · import_already_runningdie Story hat sich seit Ihrem expected_updated_at geändert · ein Import läuft bereits
412precondition_failedIf-Match stimmte nicht mit dem aktuellen ETag der Ressource überein; details trägt expected und current
413request_too_largeder Body überschreitet die Größenbegrenzung der Route
422invalid_transitionunzulässige Zustandsbewegung; details trägt { from, to, allowed }
429rate_limitedzu viele Anfragen von dieser IP auf einer ratenbegrenzten Route; Retry-After-Header
500internal_errorServerfehler — generische Nachricht; sicher zu wiederholen
503not_configureddem 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"] } }

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".