Référence complète des endpoints REST de l'API East Agile Tracker : authentification et rôles, projets, stories, epics, itérations, événements, import et export.
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://api.eastagiletracker.com/api/v1L’API dispose de son propre hôte : eastagiletracker.com sert l’application web et répond 404 à /api/v1/…. 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 le formulaire de contact public (/api/contact). 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 (authentifié ; révoque le jeton de rafraîchissement de cette session) |
| 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) |
| POST | /auth/oauth/link/preview · …/link/confirm · /auth/oauth/merge/preview · …/merge/confirm | Associer un compte GitHub ou Google à un compte existant, ou fusionner deux comptes |
| POST | /auth/email_addresses/primary/preview · …/primary/confirm | Finaliser un changement d’e-mail principal depuis le lien de confirmation reçu par e-mail |
Compte / identité
Section intitulée « Compte / identité »Ces opérations agissent sur l’appelant et ne nécessitent aucun rôle de projet. Elles exigent une identité de membre — une clé d’agent reçoit 401 (les agents utilisent /agent/me). Les appels qui modifient des identifiants — mot de passe, TOTP, passkeys, suppression du compte, changement d’e-mail, régénération du jeton — exigent une session de navigateur ; une clé d’API reçoit 403.
| 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 / DELETE | /me/avatar | Téléverser (multipart) / retirer votre avatar |
| POST | /me/api-token/regenerate | Déconnecter toutes les sessions et renvoyer un nouveau jeton de session ; les clés d’API ne sont pas affectées |
| GET / POST | /me/email_addresses · GET …/email_addresses/offers · PUT …/email_addresses/primary | Vos adresses e-mail ; adopter l’adresse d’un fournisseur connecté comme adresse secondaire ; demander un changement d’adresse principale (confirmé par e-mail) |
| GET | /me/oauth_identities · DELETE …/oauth_identities/{provider} · POST …/oauth_identities/{provider}/link | Comptes de connexion associés (GitHub, Google) : lister, déconnecter, lancer une association |
| 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/v1/feedback · /api/v1/feedback/with-screenshot | Contact + retours dans l’application ; 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 |
| GET | /organization-invitations/{token} · POST …/{token}/accept | Résoudre / accepter une invitation d’organisation reçue par e-mail |
| GET | /organizations/{oid}/export · 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 / DELETE | /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 — l’appelant doit être Responsable du projet et owner ou admin de l’organisation cible |
| 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 (l’amorçage est réservé aux administrateurs du produit ; tout autre appelant reçoit 404) |
| 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= (50 par défaut, plafonné à 1000), before= (curseur keyset <ISO-8601>|<audit_id> — transmettez le next_cursor de la page précédente), 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é est (manager) ; surface=project_history est (viewer), avec les e-mails des membres caviardés quand le projet les masque ; 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) |
| POST | /projects/{id}/memberships/bulk-role · …/memberships/bulk-remove | Changer le rôle de plusieurs membres à la fois, ou les retirer (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) et owner ou admin d’organisation |
| 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) |
| GET / POST | /projects/{id}/agent_keys | Lister (manager) / émettre des clés d’agent — les personnes dont le rôle figure dans la politique de création de clés du projet ; une clé d’agent ne peut pas en émettre |
| PUT / DELETE | /projects/{id}/agent_keys/{kid} | Modifier le nom, le rôle ou les indices de réponse d’une clé / la révoquer (manager) |
| 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 / DELETE /projects/{id}/agents/{aid} | Les agents du projet et leurs profils (nom, initiales, description, couleur) ; DELETE révoque l’agent et toutes ses clés — un manager ou le créateur de l’agent |
| 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. Créer une story avec des dates antidatées, une provenance d’import (import_source / import_external_id), ou des propriétaires ou un demandeur externes nécessite (manager).
| 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-unarchive | Désarchiver plusieurs stories |
| 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 |
| 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 — codes= (codes de liens courts séparés par des virgules) et ids= (project_id:story_id séparés par des virgules) — 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_version" (entier, la version de la story — l’enregistrement d’une description est refusé avec 409 stale_write si la description a changé après cette version). L’ancien "expected_updated_at" (RFC 3339) est déprécié et fonctionne encore pendant une version : envoyé avec une description et sans expected_version, l’enregistrement est refusé avec 409 stale_write s’il ne correspond pas à l’updated_at de la story. 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). Supprimer une pièce jointe ou une pièce jointe de type lien nécessite d’en être l’auteur de l’envoi ou (manager).
| 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} | Création : { url, link_type?, title? } ; mise à jour : { url, 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} | { label_id } — un label existant du projet ; créez les labels avec POST /projects/{id}/labels, ou envoyez labels dans le PUT de la story |
| 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/v1/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 et pour les listes de commentaires, de propriétaires et d’abonnés ; (viewer) pour la liste des epics, un epic seul et les listes de pièces jointes.
| 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 |
| GET / PUT / DELETE | /projects/{id}/labels/{lid} | Lire / 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 | La fenêtre, la vélocité projetée et le remplissage depuis le Backlog de l’itération qu’une écriture d’amorçage créerait, ou de l’itération courante si elle existe (member) |
| POST | /projects/{id}/iterations | Créer une itération manuelle (manager) |
| 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_id=<event_id> (since est l’ancien alias ; since_id l’emporte quand les deux sont envoyés), types=story.created,story.transitioned,comment.added,…, limit= (100 par défaut, ≤ 500), cursor=. La réponse est { items, next_since_id, next_cursor } : conservez next_since_id et renvoyez-le comme since_id pour reprendre ; next_cursor vaut null sur la dernière page.
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, et include_comments (par défaut true) ; 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 JSON s’exécute par projet à la fois ; un second POST …/import/json pendant qu’un import est en cours renvoie 409 import_already_running. Avec check_unpointed_estimates: true (sources fichier ; ignoré pour github), un fichier contenant des estimations de bugs ou de corvées que le projet ne chiffre pas est refusé avec 409 import_unpointed_estimates et details.count avant le démarrage de tout job ; sans l’option, l’import abandonne ces estimations et signale { code: "estimates_unpointed_dropped", count } dans les warnings du résultat. 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 : un fichier de 10 MiB (400 import_too_large) et 5 000 stories par import pour les sources fichier (400 import_too_many_records) ; rien n’est écrit. Un corps de requête de plus de 16 MiB est refusé plus tôt avec 413 request_too_large. 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 |
| 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.
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/*, à /mcp, à tout chemin contenant /attachments, ni à toute requête multipart/* ; une requête sans identifiant n’est jamais mise en cache. 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 le journal d’audit. La recherche pagine avec limit (≤ 1000) et offset plutôt qu’avec un curseur, et renvoie { results, total, limit, offset }.
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 listes de stories, de commentaires et de projets acceptent fields= (séparés par des virgules) pour ne renvoyer que des champs spécifiques. L’id de la ressource est toujours inclus (story_id, story_comment_id et comment_id, project_id) ; 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. La validation des champs (vide/longueur/octet null/e-mail) ajoute details.fields et details.constraint ; seule une simple erreur de requête invalide omet details |
| 400 | validation_failed | erreur d’entrée structurée ; details.fields est un tableau de noms de champs en cause |
| 400 | codes métier | un refus propre à la route, avec son propre code et sans details — par ex. unsupported_export_format, import_too_large, import_unknown_source |
| 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 · import_unpointed_estimates | la description a changé après votre expected_version (ou expected_updated_at ne correspond plus) · un import est déjà en cours · le fichier contient des estimations de bugs ou de corvées que le projet ne chiffre pas (details.count) |
| 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 |
| 502 | upstream_error | un service dont dépend la route (par ex. GitHub) a échoué |
| 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/v1/feedbacket/api/v1/feedback/with-screenshot: 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".