La référence complète des endpoints REST. Pour les tutoriels et les exemples, voir le Guide de l’API.
Tout ce qu’un membre de projet peut faire dans l’interface web est disponible ici — la SPA consomme cette même API. Les opérations nécessitant le rôle manager sont marquées (manager) ; tout le reste ne requiert que l’appartenance au projet (ou, pour les lectures marquées (viewer), n’importe quel niveau d’accès). Les tableaux ci-dessous nomment chaque groupe de routes monté par le serveur ; ceux résumés en une seule ligne sont entièrement décrits dans le openapi.json en direct.
https://eastagiletracker.com/api/v1https://api.eastagiletracker.com/api/v1 sert l’API identique. Toutes les requêtes et réponses sont en JSON, à l’exception de quelques endpoints d’envoi de fichiers qui acceptent le multipart.
Deux groupes se trouvent un niveau plus haut, sous /api plutôt que /api/v1 : la surface d’authentification (/api/auth/*) et les formulaires publics (/api/contact, /api/feedback). Leurs variantes /api/v1/… renvoient 404.
Authentification
Section intitulée « Authentification »Chaque requête authentifiée envoie un identifiant via l’un des moyens suivants :
X-TrackerToken: <key>Authorization: Bearer <key>
Les clés utilisateur commencent par ea_user_, les clés d’agent par ea_agent_, et les jetons d’accès MCP par ea_mcp_. Voir Guide de l’API → Trois types d’identifiants.
Endpoints non authentifiés : /openapi.json, /docs, les endpoints /api/auth/*, et les recherches de données de référence (/story_types, /story_states, /effort_scales, /priority_scales). /meta est authentifié — n’importe quelle clé valide fonctionne, mais il n’est pas restreint à un projet (une clé d’agent liée à un projet y accède également).
Quatre niveaux contrôlent l’accès aux endpoints restreints à un projet :
| Niveau | Qui passe | Opérations types |
|---|---|---|
| public viewer | n’importe qui, sur un projet dont la visibilité est publique | lectures du tableau : stories, itérations, recherche, activité des stories et des epics (détails de l’acteur caviardés) |
| viewer | viewer, member, manager | lectures (lister/obtenir des stories, recherche, métriques, liste des formats d’export) |
| member | member, manager | toutes les écritures sur les éléments de travail (stories, tâches, commentaires, …), le flux d’événements |
| manager | manager uniquement | paramètres du projet, gestion des membres, clés d’agent, suppression, import, téléchargements d’export, sauvegardes, journal d’audit |
Les agents détiennent les mêmes rôles que les membres — viewer, member ou manager — plafonnés au rôle du membre qui a émis la clé. Un non-membre reçoit 404 unfound_resource (et non 403) sur les chemins de projets privés, de sorte que les identifiants de projet ne sont pas énumérables.
Endpoints auto-descriptifs
Section intitulée « Endpoints auto-descriptifs »| Méthode | Chemin | Description |
|---|---|---|
| GET | /openapi.json | La spécification OpenAPI 3 en direct, corps de requête compris. Non authentifié. |
| GET | /docs | Swagger UI. Non authentifié. |
| GET | /meta | Identité de l’appelant (auth.kind/key_id/agent_id/project_id) + le graphe de transitions par type de story. Authentifié (n’importe quelle clé valide ; non restreint à un projet). À appeler en premier. |
| GET | /api/health · /api/config | Sonde de disponibilité, et la configuration publique du déploiement (mode mono-organisation, fonctionnalités optionnelles activées, nom de l’instance). Non authentifié, hors de /v1. |
Auth (/api/auth/*, hors de /v1)
Section intitulée « Auth (/api/auth/*, hors de /v1) »Endpoints de session, non authentifiés sauf mention contraire. La SPA les pilote ; les scripts utilisent normalement une clé d’API à la place.
| Méthode | Chemin | Description |
|---|---|---|
| POST | /auth/register | Enregistrer un nouveau compte — protégé par reCAPTCHA ; le compte passe ensuite la vérification par SMS |
| POST | /auth/sms/challenge · /auth/sms/status · /auth/sms/bypass | Envoyer / vérifier le code SMS d’inscription (le contournement est réservé à l’opérateur) |
| GET | /auth/config | Les méthodes de connexion proposées par le déploiement |
| POST | /auth/login | Se connecter avec e-mail + mot de passe ; renvoie un JWT de session, ou une demande de code TOTP |
| POST | /auth/login/totp | Terminer une connexion avec un code d’application d’authentification ou un code de récupération |
| POST | /auth/passkey/login/start · /auth/passkey/login/finish | Connexion WebAuthn sans mot de passe |
| GET | /auth/oauth/github/start · /auth/oauth/github/callback · /auth/oauth/google/start · /auth/oauth/google/callback · POST /auth/oauth/exchange | Connexion OAuth avec GitHub ou Google |
| POST | /auth/refresh · /auth/refresh/revoke | Renouveler le jeton de rafraîchissement / le révoquer |
| POST | /auth/logout | Se déconnecter (révoque le jeton de rafraîchissement) |
| POST | /auth/forgot-password · /auth/reset-password | Demander un e-mail de réinitialisation / utiliser le jeton de réinitialisation |
| POST | /auth/accept-invite/lookup · /auth/accept-invite | Résoudre un jeton d’invitation → e-mail / accepter l’invitation au projet (après authentification) |
Compte / identité
Section intitulée « Compte / identité »Ces opérations agissent sur l’appelant et ne nécessitent qu’une clé valide (aucun rôle de projet).
| Méthode | Chemin | Description |
|---|---|---|
| GET | /me | Profil de l’utilisateur actuel |
| PUT | /me | Mettre à jour le profil |
| DELETE | /me | Supprimer le compte — refusé tant que vous êtes l’unique propriétaire d’une organisation ou d’un projet comptant d’autres membres |
| GET | /me/deletion-impact | Ce que la suppression du compte retirerait, et ce qui la bloque |
| PUT | /me/password | Changer le mot de passe |
| PUT | /me/settings | Mettre à jour les paramètres (thème, préférences de notification) |
| POST | /me/avatar | Téléverser un avatar (multipart) |
| POST | /me/api-token/regenerate | Renouveler votre jeton d’API — invalide les sessions/clés existantes |
| GET | /me/api_keys · POST /me/api_keys · DELETE /me/api_keys/{id} | Gérer les clés d’API utilisateur (ea_user_) |
| GET | /me/totp · POST /me/totp/setup · /me/totp/verify · /me/totp/disable | Activation de la double authentification (TOTP) ; verify renvoie les codes de récupération une seule fois |
| GET | /me/passkeys · POST /me/passkeys/register/start · /me/passkeys/register/finish · DELETE /me/passkeys/{credential_id} | Enregistrement et suppression de passkeys |
| GET | /me/oauth_grants · DELETE /me/oauth_grants/{grant_id} | Applications connectées — les clients MCP et applications OAuth que vous avez autorisés |
| GET | /me/activity | Votre activité sur tous les projets |
| GET | /me/stories | Les stories dont vous êtes propriétaire, demandeur ou abonné, dans tous les projets que le jeton peut atteindre — role=owned|requested|following, state=, cursor= / limit= (max 200) |
| GET | /me/mentions · POST /me/mentions/{mention_id}/ack | La boîte de mentions @ (unacked=true pour filtrer) et l’accusé de lecture — également intégrée au flux de notifications ci-dessous |
| GET | /me/data-export | Auto-export RGPD de vos données |
| GET | /me/consent · POST /me/consent | Lire / enregistrer le consentement ({ consent_type, granted }) |
| GET | /legal/pending · POST /legal/accept | Documents clickwrap en attente / enregistrer l’acceptation |
| GET / PUT | /agent/me | L’identité et le profil d’une clé d’agent, lisibles et modifiables par l’agent lui-même (l’équivalent côté agent de /me) |
| POST | /api/contact · /api/feedback · /api/feedback/with-screenshot | Contact + retours dans l’application. Hors de /v1 ; débit limité par IP |
Données de référence (non authentifiées)
Section intitulée « Données de référence (non authentifiées) »Recherches sur les données de référence utilisées lors de la création/estimation des stories. Identifiants stables.
| Méthode | Chemin | Description |
|---|---|---|
| GET | /story_types | feature, bug, chore, release (+ allow_points) |
| GET | /story_states | unstarted … accepted, rejected |
| GET | /effort_scales | échelles d’estimation disponibles |
| GET | /effort_scales/{scale_id}/values | les valeurs de points d’une échelle |
| GET | /priority_scales · /priority_scales/{scale_id}/values | les échelles de priorité et leurs valeurs (le priority_id d’une story se résout ici) |
Organisations
Section intitulée « Organisations »Service hébergé uniquement — une installation auto-hébergée fonctionne en mode mono-organisation et ne monte pas ces routes (sauf la liste des organisations). Les rôles sont des rôles d’organisation : owner, admin, member.
| Méthode | Chemin | Description |
|---|---|---|
| GET / POST | /organizations | Lister vos organisations / en créer une |
| GET / PUT / DELETE | /organizations/{oid} | Lire, renommer (nom + slug ; owner ou admin), supprimer |
| GET / POST | /organizations/{oid}/memberships · PUT / DELETE …/memberships/{member_id} | Membres et invitations ; une invitation porte un plafond de rôle (jamais au-dessus de celui de l’appelant ; le rôle owner n’est jamais attribué par invitation) |
| POST | /organizations/{oid}/memberships/bulk-role · …/memberships/bulk-remove | Changer le rôle de 200 membres au plus en une fois, ou les retirer. Tout ou rien : un lot qui retirerait le dernier owner ou laisserait un projet sans propriétaire est refusé en entier ; avec reassign_confirmed, vous devenez propriétaire de ces projets à la place |
| DELETE | /organizations/{oid}/invitations/{invitation_id} | Révoquer une invitation en attente |
| POST | /organizations/{oid}/transfer-ownership | Céder le rôle owner à un autre membre |
| PUT | /organizations/{oid}/memberships/{member_id}/anonymization | Masquer le nom / l’e-mail / l’avatar d’un membre dans toute l’organisation |
| GET | /organization-invitations/{token} · POST …/{token}/accept | Résoudre / accepter une invitation d’organisation reçue par e-mail |
| POST | /organizations/{oid}/export · GET / POST …/export/jobs · GET …/export/jobs/{job_id} · …/export/jobs/{job_id}/download | Export de l’organisation, réservé à l’owner : un zip contenant un dump SQL et toutes les pièces jointes, exécuté sous forme de tâche |
| Méthode | Chemin | Description |
|---|---|---|
| GET | /projects | Lister vos projets (limit ≤ 200) |
| POST | /projects | Créer un projet |
| GET | /projects/{id} | Obtenir les détails du projet (viewer) |
| PUT | /projects/{id} | Mettre à jour les paramètres du projet (manager) |
| DELETE | /projects/{id} | Supprimer un projet (manager) |
| POST | /projects/{id}/pin | Épingler / désépingler le projet dans votre liste de projets |
| POST | /projects/{id}/transfer-organization | Déplacer le projet vers une autre organisation (manager) |
| POST | /projects/{id}/slack/test | Envoyer un message de test au flux Slack du projet (manager) |
| GET / POST | /projects/{id}/showcase_claim_eligibility · /projects/{id}/showcase_claim · /projects/{id}/showcase_seed | Projets vitrines publics : vérifier si vous pouvez en revendiquer un, le revendiquer, l’amorcer |
| GET | /projects/{id}/audit-log | Lecture de l’audit log — historique du projet plus activité par story / par epic via surface= ; l’accès varie selon le surface, voir ci-dessous |
| GET | /projects/{id}/events | Flux d’événements paginé par curseur (member) — voir Événements |
Paramètres de requête de l’audit log : event_type= (un type ou liste séparée par des virgules), limit= (≤ 1000), before= (curseur keyset, created_at ISO-8601), surface= (project_history, story_activities, epic_activities), target_id= (l’id de la story/epic — requis quand surface=story_activities ou epic_activities). Accès : le log non filtré et surface=project_history sont (manager) ; story_activities / epic_activities sont lisibles par tout membre du projet, et anonymement sur les projets publics avec les PII de l’acteur caviardées.
Membres, agents et clés d’agent
Section intitulée « Membres, agents et clés d’agent »| Méthode | Chemin | Description |
|---|---|---|
| GET | /projects/{id}/memberships | Lister les membres (viewer) |
| POST | /projects/{id}/memberships | Inviter un membre par e-mail (manager) |
| PUT | /projects/{id}/memberships/{mid} | Mettre à jour le rôle (manager) |
| DELETE | /projects/{id}/memberships/{mid} | Retirer un membre (manager) |
| GET | /projects/{id}/addable-members · POST /projects/{id}/members/add-existing | Membres de l’organisation pas encore sur le projet / en ajouter un sans invitation par e-mail (manager) |
| POST | /projects/{id}/members/join | Un owner ou admin d’organisation rejoint un projet de son organisation en tant que manager, ou s’y promeut lui-même manager (l’action Make me owner de la liste des projets) |
| PUT | /projects/{id}/members/{mid}/anonymization | Masquer le nom / l’e-mail / l’avatar d’un membre sur ce projet (manager) |
| GET / POST | /projects/{id}/agent_keys | Lister / émettre des clés d’agent — les managers, ou les rôles qu’admet la politique de création de clés du projet |
| DELETE | /projects/{id}/agent_keys/{kid} | Révoquer une clé d’agent |
| GET | /projects/{id}/agent_keys/onboarding | Le kit de prise en main : prompts et fichiers de configuration pour les clients d’agent courants |
| GET | /projects/{id}/agents · GET / PUT /projects/{id}/agents/{aid} | Les agents du projet et leurs profils (nom, initiales, description, couleur) |
| POST | /projects/{id}/agents/{aid}/rotate-key · /projects/{id}/agents/{aid}/avatar | Renouveler la clé d’un agent (identité et historique conservés) / téléverser son avatar |
Toutes les écritures sur les stories nécessitent le rôle member.
| Méthode | Chemin | Description |
|---|---|---|
| GET | /projects/{id}/stories | Lister les stories (paginées, filtrables) (viewer) |
| POST | /projects/{id}/stories | Créer une story |
| GET | /projects/{id}/stories/{sid} | Obtenir une story (viewer) |
| PUT | /projects/{id}/stories/{sid} | Mettre à jour une story |
| DELETE | /projects/{id}/stories/{sid} | Supprimer une story |
| POST | /projects/{id}/stories/{sid}/transitions | Changer d’état avec validation |
| POST | /projects/{id}/stories/{sid}/reject · /projects/{id}/stories/{sid}/restart | Rejeter une story livrée / remettre une story rejetée à started (rejected est terminal pour /transitions) |
| POST | /projects/{id}/stories/{sid}/archive · /projects/{id}/stories/{sid}/unarchive | Archiver / désarchiver une story |
| POST | /projects/{id}/stories/bulk_transition | Faire transiter plusieurs stories (1–100) à la fois |
| POST | /projects/{id}/stories/bulk-archive · bulk-delete · bulk-duplicate · bulk-move | Archiver, supprimer, dupliquer ou déplacer (vers un panneau / une position) plusieurs stories |
| POST | /projects/{id}/stories/{sid}/duplicate | Dupliquer une story |
| GET / POST / DELETE | /projects/{id}/stories/{sid}/epics · …/epics/{eid} | L’appartenance de la story aux epics |
| GET | /short-links/{code} · /story-references | Résoudre un lien court /s/<code> vers sa story / résoudre jusqu’à 100 références de stories (#id, URL) vers les stories que l’appelant peut lire |
Paramètres de requête de la liste de stories : archived= (exclude par défaut / include / only — le filtre d’archivage à trois états ; remplace le déprécié include_archived=true, désormais alias de archived=include), include_done=true (admet les stories du panneau Done figées sur des itérations passées, exclues par défaut). La pagination (cursor= / limit= / offset=) et les ensembles de champs partiels (fields=) suivent les sections Pagination et Projection de champs.
Création (POST …/stories) : { "name" (required), "story_type": "feature|bug|chore|release", "description"?, "estimate"?, "current_state"?, "icebox"?, "labels"? }. estimate est le libellé de la valeur d’échelle, sous forme de chaîne ("3", "13") ; un nombre JSON est rejeté. labels accepte ["auth"] ou [{ "name": "auth" }] ; les labels inconnus sont créés. Valeurs par défaut : story_type=feature, current_state=unstarted.
Mise à jour (PUT …/stories/{sid}) : mêmes champs, tous optionnels, plus "position" (float), "force_state_change" (bool) et "expected_updated_at" (RFC 3339 — l’enregistrement d’une description est refusé avec 409 stale_write si la story a changé depuis votre lecture). Les écritures sur les stories respectent aussi If-Match par rapport à l’ETag de la story ; une non-correspondance donne 412 precondition_failed.
Transition (POST …/transitions) : { "to": "<state>" }. Le champ est to. Renvoie { story_id, state }. Déplacement illégal → 422 invalid_transition avec details: { from, to, allowed }.
Transition groupée (POST …/bulk_transition) : { "story_ids": [int,…] (1–100), "to": "<state>" }. Chaque story est évaluée indépendamment ; renvoie { results: [ { id, status: "ok" } | { id, status: "failed", error } ] }.
Sous-ressources des stories
Section intitulée « Sous-ressources des stories »Toutes en member. La liste/GET sur la plupart est en (viewer).
| Méthode | Chemin | Corps / notes |
|---|---|---|
| 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) } ou { comment_emoji }. GET accepte fields= (liste autorisée : comment_id, story_comment_id, story_id, comment_text, comment_emoji, member, created) plus 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 ; les URL GitHub en /pull/ et /tree/ sont typées automatiquement |
| GET / POST | /projects/{id}/stories/{sid}/reviews · PUT/DELETE …/reviews/{rid} | Création : { reviewer_id? / reviewer_agent_id?, comment? } — omettez les deux pour vous assigner vous-même. Mise à jour : { status, comment? } |
| GET / POST | /projects/{id}/stories/{sid}/owners · DELETE …/owners/{mid} · DELETE …/owners/agents/{aid} | { member_id? / agent_id? } — omettez les deux pour ajouter l’appelant |
| 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} | envoi multipart — vidéo ≤ 200 Mo, PDF / Word / Excel ≤ 25 Mo, images / CSV / texte ≤ 10 Mo ; la liste est en (viewer) |
| GET / POST | /projects/{id}/stories/{sid}/link-attachments · DELETE …/link-attachments/{laid} | Pièces jointes de type lien — une URL externe conservée avec les pièces jointes de fichier plutôt que comme lien de code |
| GET | /attachments/{token} · /api/avatars/{token} | Lectures d’une pièce jointe ou d’un avatar adressées par jeton — les URL que l’API renvoie ; aucun X-TrackerToken n’est requis |
Même forme que les stories, sans la machine à états. member pour les écritures, (viewer) pour les lectures.
| Méthode | Chemin | Description |
|---|---|---|
| GET / POST | /projects/{id}/epics · GET / PUT / DELETE …/epics/{eid} | Un epic porte un nom, une description Markdown et un label associé qui rattache ses stories |
| GET / POST / PUT / DELETE | …/epics/{eid}/comments · …/comments/{cid} | Commentaires d’epic |
| GET / POST / DELETE | …/epics/{eid}/owners · …/followers (+ variantes /agents/{aid}) | Propriétaires et abonnés, membres ou agents — les propriétaires d’un epic se propagent à ses stories |
| GET / POST / DELETE | …/epics/{eid}/attachments (+ /json) · …/link-attachments | Pièces jointes, mêmes plafonds que pour les stories |
| GET | /projects/{id}/analytics/epics · …/analytics/epics/{eid} | Progression par epic : burnup, débit, santé, prévision (viewer) |
member pour les écritures, (viewer) pour les lectures.
| Méthode | Chemin | Description |
|---|---|---|
| GET / POST | /projects/{id}/labels | Lister / créer un label |
| PUT / DELETE | /projects/{id}/labels/{lid} | Mettre à jour / supprimer un label |
| POST | /projects/{id}/labels/{lid}/archive | Archiver (masquer en douceur) un label |
Itérations
Section intitulée « Itérations »Les lectures sont ouvertes à tout rôle de projet, et anonymes sur un projet public.
| Méthode | Chemin | Description |
|---|---|---|
| GET | /projects/{id}/iterations | Lister les itérations (≤ 500 par page ; porte un ETag et, en cas de troncature, les en-têtes de continuation X-Tracker-Pagination-*) |
| GET | /projects/{id}/iterations/{itid} | Une itération |
| GET | /projects/{id}/iterations/first-preview | Les dates que recevrait la première itération, affichées dans la confirmation de création |
| POST | /projects/{id}/iterations | Créer une itération manuelle (member) |
| DELETE | /projects/{id}/iterations/{itid} | Supprimer une itération (manager) |
| PUT | /projects/{id}/iterations/{itid}/velocity | Remplacer la vélocité d’une itération sans changer la stratégie du projet (manager) |
| GET | /projects/{id}/iterations/{itid}/done-stories | Les stories acceptées d’une itération close, paginées |
Recherche, métriques, préférences
Section intitulée « Recherche, métriques, préférences »| Méthode | Chemin | Description |
|---|---|---|
| GET | /projects/{id}/search?q=… | Recherche puissante — texte intégral + qualificateurs de facette / de plage de dates / de personnes (DSL inspiré de GitHub) ; renvoie { results, total, limit, offset }. query est un alias de q ; limit= (50 par défaut, max 1000) / offset= paginent ; sort= trie par relevance (par défaut), created, created_asc, state ou updated. (viewer) — voir le Guide |
| GET | /projects/{id}/metrics/{velocity,burndown,story-types,contributors} | Les séries de la page Metrics (viewer) ; les métriques d’epic se trouvent sous /analytics/epics ci-dessus |
| GET | /projects/{id}/backlog/grouping | Les groupes d’itérations projetés du Backlog (viewer) |
| GET / PUT | /projects/{id}/preferences | Vos préférences de tableau pour ce projet — tout rôle de projet, uniquement votre propre ligne |
Événements
Section intitulée « Événements »| Méthode | Chemin | Description |
|---|---|---|
| GET | /projects/{id}/events | Flux d’événements paginé par curseur (member) — les viewers reçoivent 403 |
Paramètres de requête : since=<event_id>, types=story.created,story.transitioned,comment.added,…, limit= (≤ 500), cursor=. La réponse inclut next_cursor. Transmettez le dernier event_id que vous avez vu via since pour reprendre.
Notifications
Section intitulée « Notifications »Le flux de notifications unifié dans l’application : des lignes de notification de premier ordre (demandes de revue, activité des stories, invitations, …) fusionnées avec la boîte de mentions @ en un seul flux, du plus récent au plus ancien. Les ids du flux sont préfixés par leur source (nt-… / sc-… / ec-…). Les sessions membre et les clés ea_user_* lisent leurs lignes côté membre ; les clés ea_agent_* leurs lignes côté agent.
| Méthode | Chemin | Description |
|---|---|---|
| GET | /me/notifications | Votre flux de notifications. Filtres : unread=true, since_id=, kind= (mentions / reviews / stories / invitations) ; paginez avec cursor= / limit= |
| GET | /me/notifications/unread-count | Totaux non lus — { unread_count, by_category: { mentions, reviews, stories, invitations } } |
| POST | /me/notifications/read-all | Tout marquer comme lu ; renvoie les compteurs à jour |
| POST | /me/notifications/{id}/ack | Marquer un élément comme lu (idempotent) |
| POST | /me/notifications/{id}/accept | Accepter une invitation à un projet / une organisation depuis le flux (jetons membre uniquement) |
| POST | /me/notifications/{id}/decline | Décliner une invitation à un projet / une organisation (jetons membre uniquement) |
| GET | /me/notifications/resolve-invite?token=… | Associer un jeton d’invitation reçu par e-mail à l’id de votre notification — { "id": "nt-…" } ou { "id": null } |
| GET | /me/notifications/stream | Push en direct — Server-Sent Events (text/event-stream) ; voir ci-dessous |
L’endpoint de stream n’est pas un endpoint JSON et n’apparaît donc pas dans la spécification OpenAPI : il maintient la connexion ouverte et émet une trame sans payload ({"type":"notification","kind":…}) dès que quelque chose de nouveau arrive, indiquant au client de recharger le flux. Les connexions sont coupées côté serveur au bout de 45 minutes — reconnectez-vous et ré-authentifiez-vous. Sessions membre et clés ea_user_* uniquement ; les clés ea_agent_* reçoivent 403.
Import (manager)
Section intitulée « Import (manager) »| Méthode | Chemin | Description |
|---|---|---|
| POST | /projects/{id}/import | Sources de fichiers : source= ∈ pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat. Multipart file=. Synchrone — répond avec les compteurs de résultat. |
| POST | /projects/{id}/import/json | Corps JSON ; source=github ne requiert aucun fichier — owner, repo, token facultatif, et les indicateurs optionnels include_pull_requests / include_milestones / include_releases / include_dependencies ; les sources de fichiers envoient file_base64. Asynchrone : renvoie 202 { import_id, status }. Le serveur récupère via l’API GraphQL de GitHub, qui rejette les appelants anonymes : un jeton parvient donc toujours à GitHub — le vôtre, ou celui partagé par le déploiement. Voir le Guide. |
| GET | /projects/{id}/imports/{import_id} | Suivre une tâche : status passe par pending → fetching → writing → done | failed, avec progress_current / progress_total pendant la récupération et les compteurs de résultat à done |
Un seul import s’exécute par projet à la fois ; un second POST pendant qu’un import est en cours renvoie 409 import_already_running. dry_run: true (corps JSON ou dry_run=true multipart) prévisualise n’importe quelle source : analyse, résout, dédoublonne, renvoie les mêmes compteurs { imported, skipped, errors, unmatched }, puis annule tout — rien n’est écrit. Plafonds : corps de 10 MiB, et 5 000 stories par import pour les sources fichier (au-delà de l’un ou l’autre → 400, rien d’écrit). La source GitHub n’est pas plafonnée — elle écrit par lots successifs plutôt qu’en une seule transaction. La réimportation est idempotente par id source — les lignes déjà importées sont ignorées, pas dupliquées.
| Méthode | Chemin | Description |
|---|---|---|
| GET | /projects/{id}/export/formats | Formats enregistrés : { id, name, content_type, drops, includes_archived }. Tout rôle de projet. |
| GET | /projects/{id}/export/{format} | En télécharger un (manager). Échange : eat (fidélité complète), jira, pivotal, shortcut, trello, asana, gitlab, linear, plane, plane_json ; documents : pdf, docx. |
| GET | /projects/{id}/export/attachments | Toutes les pièces jointes dans un seul zip navigable (les fichiers conservent leurs noms d’origine ; manifeste JSON + CSV) (manager). |
Les exports de documents (pdf, docx) acceptent des paramètres de requête supplémentaires : page_size= (letter par défaut / a4 / legal / folio), from= / to= (bornes de la fenêtre de stories — RFC 3339 ou simple YYYY-MM-DD ; une story est dans la plage quand son created ou son completed_at tombe dedans), include_icebox= / include_backlog= (tous deux false par défaut, de sorte qu’un export partageable ne montre que le travail planifié / en cours). Les formats CSV d’échange les ignorent.
Sauvegardes et restaurations (manager)
Section intitulée « Sauvegardes et restaurations (manager) »| Méthode | Chemin | Description |
|---|---|---|
| GET / POST | /projects/{id}/backups · GET …/backups/{snapshot_id} · …/backups/health | Lister les instantanés, en prendre un immédiatement, en lire un, et le résumé de santé de la rétention |
| GET / POST | /projects/{id}/restores · POST …/restores/partial · GET …/restores/{restore_id} | Restaurer un instantané complet, ou certaines de ses tables, et suivre la restauration |
Les POST relèvent du palier de limite de débit sensible (ci-dessous).
Fournisseur MCP et OAuth
Section intitulée « Fournisseur MCP et OAuth »East Agile Tracker est un fournisseur OAuth 2.1 pour les clients MCP. Un client le découvre via /.well-known/oauth-authorization-server et /.well-known/oauth-protected-resource/mcp, vous envoie vers /oauth/authorize (la page de consentement), échange le code sur /oauth/token, puis parle MCP sur /mcp avec le jeton ea_mcp_* obtenu. Les autorisations se listent et se révoquent sur /me/oauth_grants. Les endpoints du fournisseur ont leur propre palier de limite de débit.
WebSocket
Section intitulée « WebSocket »wss://eastagiletracker.com/ws/control?token=<session JWT>Pour la télécommande interactive de l’interface ({ "action": "get_state", "id": "req-1" }). Le jeton est un JWT de session de navigateur — une clé d’API est refusée avec 401 avant la mise à niveau de la connexion. Ce n’est pas un canal de données — toutes les lectures/écritures passent par REST. Mono-instance uniquement ; non distribué entre les réplicas.
Idempotence
Section intitulée « Idempotence »Les endpoints d’écriture (POST, PUT, DELETE) acceptent un en-tête Idempotency-Key. La même clé + le même corps rejoue la réponse mise en cache (fenêtre de 24 heures) ; la même clé + un corps différent renvoie 409 idempotency_conflict. La clé est propre à l’identifiant qui l’a envoyée. Non appliqué aux requêtes GET/HEAD/OPTIONS, à /openapi.json et /docs, à /api/auth/*, ni aux envois multipart sur les chemins /attachments. Les réponses qui n’ont pas abouti à une réponse métier ne sont jamais mises en cache — 401, 403, 404, 429 et tout 5xx — si bien qu’un nouvel essai après l’une d’elles atteint le gestionnaire ; 400, 409, 412 et 422 sont la réponse métier et sont rejouées comme un succès.
Pagination
Section intitulée « Pagination »Les endpoints de liste acceptent cursor=<opaque> et limit=<n>. Lorsqu’ils sont définis, la réponse est { "items": [...], "next_cursor": "<str|null>" } ; renvoyez next_cursor pour paginer. Le plafond de limit dépend de l’endpoint : 200 pour les stories, les commentaires et les projets ; 500 pour les événements ; 1000 pour la recherche et le journal d’audit.
Une liste simple (sans cursor/limit) qui a dû tronquer sa réponse le signale dans ses en-têtes — X-Tracker-Pagination-Truncated, X-Tracker-Pagination-Limit, X-Tracker-Pagination-Offset et X-Tracker-Pagination-Next-Offset ; renvoyez ce dernier comme offset= pour obtenir la page suivante. Il n’existe pas d’en-tête de nombre total.
Projection de champs
Section intitulée « Projection de champs »Les endpoints de liste acceptent fields= (séparés par des virgules) pour ne renvoyer que des champs spécifiques. story_id est toujours inclus ; un nom de champ inconnu renvoie 400 validation_failed avec les noms en cause dans details.fields.
GET /projects/123/stories?fields=story_id,name,current_state,ownersFormat des erreurs
Section intitulée « Format des erreurs »Chaque erreur JSON possède code et error ; certaines ajoutent details :
{ "code": "invalid_transition", "error": "Cannot move story from `unstarted` to `accepted`", "details": { "from": "unstarted", "to": "accepted", "allowed": ["started"] } }| Statut | code | Quand |
|---|---|---|
| 400 | invalid_parameter | entrée incorrecte ; message dans error, pas de details (la plupart des validations : vide/longueur/octet null/e-mail) |
| 400 | validation_failed | erreur d’entrée structurée ; details.fields est un tableau de noms de champs en cause |
| 401 | unauthenticated | jeton manquant/invalide |
| 403 | unauthorized_operation | authentifié mais rôle insuffisant |
| 404 | unfound_resource | introuvable — également renvoyé aux non-membres |
| 409 | conflict | conflit de ressource (par ex. doublon) |
| 409 | idempotency_conflict | Idempotency-Key réutilisée avec un corps différent |
| 409 | stale_write · import_already_running | la story a changé depuis votre expected_updated_at · un import est déjà en cours |
| 412 | precondition_failed | If-Match ne correspond pas à l’ETag actuel de la ressource ; details contient expected et current |
| 413 | request_too_large | le corps dépasse la limite de taille de la route |
| 422 | invalid_transition | déplacement d’état illégal ; details contient { from, to, allowed } |
| 429 | rate_limited | trop de requêtes depuis cette IP sur une route à débit limité ; en-tête Retry-After |
| 500 | internal_error | défaillance serveur — message générique ; peut être réessayé sans risque |
| 503 | not_configured | le déploiement ne dispose pas de l’intégration requise par cette route (SMS, stockage objet, …) |
details.fields est un tableau JSON de noms de champs (par ex. ["to"]), parfois accompagné de clés supplémentaires comme max. Il n’y a pas de correspondance champ→message.
{ "code": "validation_failed", "error": "unknown field(s): foo", "details": { "fields": ["foo"] } }Limites de débit
Section intitulée « Limites de débit »Par IP client, sur une poignée de routes ; ailleurs, le trafic d’API authentifié n’est pas soumis à une limite de débit. Valeurs par défaut (chaque paire indique le débit soutenu et la rafale, réglables par l’opérateur) :
- Auth —
/api/auth/*: 0,5 req/s, rafale 20. - Fournisseur OAuth —
/oauth/*: 1 req/s, rafale 60. - Public —
/api/contact: 0,2 req/s, rafale 10. - Retours —
/api/feedback: trois paliers superposés — un envoi par 15 s, 10 par heure, 36 par jour. - Avatars — la redirection d’avatar non authentifiée : 20 req/s, rafale 200.
- Sensible — les
POSTde sauvegarde et de restauration : ~0,002 req/s, rafale 5.
Une limite dépassée renvoie 429 avec un en-tête Retry-After et l’enveloppe d’erreur JSON standard, code: "rate_limited".