Ga naar inhoud

API-specificatie

De volledige REST-endpoint-referentie. Voor tutorials en voorbeelden, zie de API-gids.

Alles wat een project-member in de web-UI kan doen is hier beschikbaar — de SPA verbruikt dezelfde API. Operaties die de rol owner vereisen zijn gemarkeerd met (owner); al het andere heeft alleen projectlidmaatschap nodig (of, voor reads gemarkeerd met (viewer), een willekeurig toegangsniveau).

https://eastagiletracker.com/api/v1

https://api.eastagiletracker.com/api/v1 serveert de identieke API. Alle verzoeken en antwoorden zijn JSON, behalve een paar bestandsupload-endpoints die multipart accepteren.

Elk geauthenticeerd verzoek stuurt een API-sleutel via een van:

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

User-sleutels beginnen met ea_user_. Agent-sleutels beginnen met ea_agent_. Zie API-gids → Twee soorten sleutels.

Endpoints zonder authenticatie: /openapi.json, /docs, de /auth/*-endpoints, en de referentiegegevens-lookups (/story_types, /story_states, /effort_scales, …). /meta is geauthenticeerd — elke geldige sleutel werkt, maar het is niet projectgebonden (een aan een project gebonden agent-sleutel bereikt het ook).

Drie niveaus reguleren projectgebonden endpoints:

NiveauWie passeertTypische operaties
viewerviewer, member, ownerreads (list/get stories, search, analytics)
membermember, owneralle writes op werkitems (stories, tasks, comments, …)
owneralleen ownerprojectinstellingen, lidmaatschapsbeheer, agent-sleutels, verwijderen, import, auditlog

Een niet-member ontvangt 404 unfound_resource (niet 403) op projectpaden, zodat project-ID’s niet enumereerbaar zijn.

MethodePadBeschrijving
GET/openapi.jsonDe live OpenAPI 3-spec. Zonder authenticatie.
GET/docsSwagger UI. Zonder authenticatie.
GET/metaIdentiteit van de aanroeper (auth.kind/key_id/agent_id/project_id) + de transitiegraaf per story-type. Geauthenticeerd (elke geldige sleutel; niet projectgebonden). Roep dit eerst aan.

Deze handelen op de aanroeper en hebben alleen een geldige sleutel nodig (geen projectrol).

MethodePadBeschrijving
POST/auth/registerEen nieuw account registreren
POST/auth/loginInloggen, geeft een sessietoken terug
POST/auth/logoutUitloggen
POST/auth/forgot-passwordEen wachtwoordreset-e-mail aanvragen
POST/auth/reset-passwordEen resettoken gebruiken om een nieuw wachtwoord in te stellen
GET/auth/verify-emailEen e-mailadres verifiëren
POST/auth/accept-invite/lookupEen uitnodigingstoken oplossen → e-mail (zonder authenticatie)
POST/auth/accept-inviteEen projectuitnodiging accepteren (na authenticatie)
GET/meHuidig gebruikersprofiel
PUT/meProfiel bijwerken
DELETE/meAccount verwijderen
PUT/me/passwordWachtwoord wijzigen
PUT/me/settingsInstellingen bijwerken (thema, notificatievoorkeuren)
POST/me/avatarAvatar uploaden (multipart)
POST/me/api-token/regenerateJe API-token roteren — maakt bestaande sessies/sleutels ongeldig
GET/me/api_keys · POST /me/api_keys · DELETE /me/api_keys/{id}Beheer user- (ea_user_) API-sleutels
GET/me/activityJe activiteit over alle projecten
GET/me/data-exportGDPR-zelfexport van je gegevens
GET/me/consent · POST /me/consentToestemming lezen / registreren ({ consent_type, granted })
GET/legal/pending · POST /legal/acceptOpenstaande clickwrap-documenten / acceptatie registreren
POST/contact · POST /feedback · POST /feedback/with-screenshotContact + in-app feedback

Seed-lookups die worden gebruikt bij het aanmaken/schatten van stories. Stabiele ID’s.

MethodePadBeschrijving
GET/story_typesfeature, bug, chore, release (+ allow_points)
GET/story_statesunstarted … accepted, rejected
GET/effort_scalesbeschikbare schattingsschalen
GET/effort_scales/{scale_id}/valuesde puntwaarden in een schaal
MethodePadBeschrijving
GET/projectsJe projecten tonen
POST/projectsEen project aanmaken
GET/projects/{id}Projectdetails ophalen (viewer)
PUT/projects/{id}Projectinstellingen bijwerken (owner)
DELETE/projects/{id}Een project verwijderen (owner)
GET/projects/{id}/audit-logProjectactiviteitenstroom (owner)
GET/projects/{id}/eventsCursor-gepagineerde eventstream (viewer) — zie Events
MethodePadBeschrijving
GET/projects/{id}/membershipsMembers tonen (viewer)
POST/projects/{id}/membershipsEen member uitnodigen via e-mail (owner)
PUT/projects/{id}/memberships/{mid}Rol bijwerken (owner)
DELETE/projects/{id}/memberships/{mid}Een member verwijderen (owner)
GET / POST/projects/{id}/agent_keysAgent-sleutels tonen / aanmaken (owner)
DELETE/projects/{id}/agent_keys/{kid}Een agent-sleutel intrekken (owner)

Alle story-writes hebben de rol member nodig.

MethodePadBeschrijving
GET/projects/{id}/storiesStories tonen (gepagineerd, filterbaar) (viewer)
POST/projects/{id}/storiesEen story aanmaken
GET/projects/{id}/stories/{sid}Eén story ophalen (viewer)
PUT/projects/{id}/stories/{sid}Een story bijwerken
DELETE/projects/{id}/stories/{sid}Een story verwijderen
POST/projects/{id}/stories/{sid}/transitionsToestand wijzigen met validatie
POST/projects/{id}/stories/bulk_transitionVeel stories (1–100) tegelijk laten overgaan
POST/projects/{id}/stories/bulk-deleteVeel stories verwijderen
POST/projects/{id}/stories/bulk-duplicateVeel stories dupliceren
POST/projects/{id}/stories/{sid}/duplicateEén story dupliceren

Aanmaken (POST …/stories): { "name" (verplicht), "story_type": "feature|bug|chore|release", "description"?, "estimate"?, "current_state"?, "icebox"?, "labels"? }. labels accepteert ["auth"] of [{ "name": "auth" }]; onbekende labels worden aangemaakt. Standaardwaarden: story_type=feature, current_state=unstarted.

Bijwerken (PUT …/stories/{sid}): dezelfde velden, allemaal optioneel, plus "position" (float) en "force_state_change" (bool).

Transition (POST …/transitions): { "to": "<state>", "reason"? }. Het veld is to. Geeft { story_id, state } terug. Ongeldige beweging → 422 invalid_transition met details: { from, to, allowed }.

Bulk transition (POST …/bulk_transition): { "story_ids": [int,…] (1–100), "to": "<state>", "reason"? }. Elke story wordt onafhankelijk beoordeeld; geeft { results: [ { id, status: "ok" } | { id, status: "failed", error } ] } terug.

Alle member. List/GET op de meeste is (viewer).

MethodePadBody / notities
GET / POST/projects/{id}/stories/{sid}/tasks · PUT/DELETE …/tasks/{tid}{ description (of task_desc), complete?, task_order? }
GET / POST/projects/{id}/stories/{sid}/comments · PUT/DELETE …/comments/{cid}{ text (of comment_text) } of { 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? } — laat beide weg om de aanroeper toe te voegen
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 per stuk); list is (viewer)

member voor writes, (viewer) voor reads.

MethodePadBeschrijving
GET / POST/projects/{id}/labelsEen label tonen / aanmaken
PUT / DELETE/projects/{id}/labels/{lid}Een label bijwerken / verwijderen
POST/projects/{id}/labels/{lid}/archiveEen label archiveren (zacht verbergen)
MethodePadBeschrijving
GET/projects/{id}/iterationsIteraties tonen (member)
POST/projects/{id}/iterationsEen handmatige iteratie aanmaken (owner)
DELETE/projects/{id}/iterations/{itid}Een iteratie verwijderen (owner)
MethodePadBeschrijving
GET/projects/{id}/search?query=…Zoeken met filtersyntaxis (viewer) — zie Gids
GET/projects/{id}/analytics/{overview,iteration,releases,activity,cycle-time,projections}Analytics (viewer). Inzoomen op iteratie neemt ?iteration_id=
GET/projects/{id}/metrics/{velocity,burndown,story-types}Metrics (viewer)
GET / PUT/projects/{id}/preferencesJe bordvoorkeuren voor dit project (member)
MethodePadBeschrijving
GET/projects/{id}/eventsCursor-gepagineerde eventstream (viewer)

Query-parameters: since=<event_id>, types=story.created,story.transitioned,comment.created,…, limit=, cursor=. Het antwoord bevat next_cursor. Geef het laatste event_id dat je zag door als since om verder te gaan.

MethodePadBeschrijving
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>

Voor interactieve UI-afstandsbediening ({ "action": "get_state", "id": "req-1" }). Geen datakanaal — alle reads/writes gaan via REST. Alleen single-instance; niet uitgewaaierd over replica’s.

Write-endpoints (POST, PUT, DELETE) accepteren een Idempotency-Key-header. Dezelfde sleutel + dezelfde body speelt het gecachte antwoord opnieuw af (venster van 24 uur); dezelfde sleutel + een andere body geeft 409 idempotency_conflict terug. Niet toegepast op GET/HEAD/OPTIONS, /auth/* of /attachments-paden. 5xx-antwoorden worden nooit gecacht — een retry bereikt de handler.

List-endpoints accepteren cursor=<opaque> en limit=<n≤200>. Indien ingesteld is het antwoord { "items": [...], "next_cursor": "<str|null>" }; geef next_cursor terug om te pagineren. Sommige lijsten geven ook een X-Tracker-Pagination-Total-header terug.

List-endpoints accepteren fields= (komma-gescheiden) om alleen specifieke velden terug te geven. story_id wordt altijd opgenomen; een onbekende veldnaam geeft 400 validation_failed terug met de schendende namen in details.fields.

GET /projects/123/stories?fields=story_id,name,current_state,owners

Elke JSON-fout heeft code en error; sommige voegen details toe:

{ "code": "invalid_transition",
"error": "Cannot move story from `unstarted` to `accepted`",
"details": { "from": "unstarted", "to": "accepted", "allowed": ["started"] } }
StatuscodeWanneer
400invalid_parameterfoute invoer; bericht in error, geen details (meeste validatie: blank/lengte/null-byte/e-mail)
400validation_failedgestructureerde invoerfout; details.fields is een array van schendende veldnamen
401unauthenticatedontbrekend/ongeldig token
403unauthorized_operationgeauthenticeerd maar onvoldoende rol
404unfound_resourceniet gevonden — ook teruggegeven aan niet-members
409conflictresourceconflict (bijv. duplicaat)
409idempotency_conflictIdempotency-Key hergebruikt met een andere body
422invalid_transitionongeldige toestandsbeweging; details draagt { from, to, allowed }
500internal_errorserverfout — generiek bericht; veilig om opnieuw te proberen

details.fields is een JSON-array van veldnamen (bijv. ["to"]), soms met extra sleutels zoals max. Er is geen veld→bericht-map.

{ "code": "validation_failed", "error": "unknown field(s): foo", "details": { "fields": ["foo"] } }

Per sleutel (per IP voor endpoints zonder authenticatie), GCRA token bucket:

  • Auth/auth/*: 0,5 req/s, burst 20.
  • Public/contact, /feedback: 0,2 req/s, burst 10.
  • Sensitive — wachtwoordreset: ~0,002 req/s, burst 5.

Een overschreden limiet geeft 429 Too Many Requests terug met een Retry-After-header en een plat-tekst-body (niet de JSON-foutenvelop).