Aller au contenu

Spécification de l'API

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

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

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 :

NiveauQui passeOpérations types
public viewern’importe qui, sur un projet dont la visibilité est publiquelectures du tableau : stories, itérations, recherche, activité des stories et des epics (détails de l’acteur caviardés)
viewerviewer, member, managerlectures (lister/obtenir des stories, recherche, métriques, liste des formats d’export)
membermember, managertoutes les écritures sur les éléments de travail (stories, tâches, commentaires, …), le flux d’événements
managermanager uniquementparamè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.

MéthodeCheminDescription
GET/openapi.jsonLa spécification OpenAPI 3 en direct, corps de requête compris. Non authentifié.
GET/docsSwagger UI. Non authentifié.
GET/metaIdentité 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/configSonde 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.

Endpoints de session, non authentifiés sauf mention contraire. La SPA les pilote ; les scripts utilisent normalement une clé d’API à la place.

MéthodeCheminDescription
POST/auth/registerEnregistrer 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/bypassEnvoyer / vérifier le code SMS d’inscription (le contournement est réservé à l’opérateur)
GET/auth/configLes méthodes de connexion proposées par le déploiement
POST/auth/loginSe connecter avec e-mail + mot de passe ; renvoie un JWT de session, ou une demande de code TOTP
POST/auth/login/totpTerminer une connexion avec un code d’application d’authentification ou un code de récupération
POST/auth/passkey/login/start · /auth/passkey/login/finishConnexion 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/exchangeConnexion OAuth avec GitHub ou Google
POST/auth/refresh · /auth/refresh/revokeRenouveler le jeton de rafraîchissement / le révoquer
POST/auth/logoutSe déconnecter (révoque le jeton de rafraîchissement)
POST/auth/forgot-password · /auth/reset-passwordDemander un e-mail de réinitialisation / utiliser le jeton de réinitialisation
POST/auth/accept-invite/lookup · /auth/accept-inviteRésoudre un jeton d’invitation → e-mail / accepter l’invitation au projet (après authentification)

Ces opérations agissent sur l’appelant et ne nécessitent qu’une clé valide (aucun rôle de projet).

MéthodeCheminDescription
GET/meProfil de l’utilisateur actuel
PUT/meMettre à jour le profil
DELETE/meSupprimer 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-impactCe que la suppression du compte retirerait, et ce qui la bloque
PUT/me/passwordChanger le mot de passe
PUT/me/settingsMettre à jour les paramètres (thème, préférences de notification)
POST/me/avatarTéléverser un avatar (multipart)
POST/me/api-token/regenerateRenouveler 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/disableActivation 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/activityVotre activité sur tous les projets
GET/me/storiesLes 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}/ackLa 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-exportAuto-export RGPD de vos données
GET/me/consent · POST /me/consentLire / enregistrer le consentement ({ consent_type, granted })
GET/legal/pending · POST /legal/acceptDocuments clickwrap en attente / enregistrer l’acceptation
GET / PUT/agent/meL’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-screenshotContact + retours dans l’application. Hors de /v1 ; débit limité par IP

Recherches sur les données de référence utilisées lors de la création/estimation des stories. Identifiants stables.

MéthodeCheminDescription
GET/story_typesfeature, bug, chore, release (+ allow_points)
GET/story_statesunstarted … accepted, rejected
GET/effort_scaleséchelles d’estimation disponibles
GET/effort_scales/{scale_id}/valuesles valeurs de points d’une échelle
GET/priority_scales · /priority_scales/{scale_id}/valuesles échelles de priorité et leurs valeurs (le priority_id d’une story se résout ici)

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éthodeCheminDescription
GET / POST/organizationsLister 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-removeChanger 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-ownershipCéder le rôle owner à un autre membre
PUT/organizations/{oid}/memberships/{member_id}/anonymizationMasquer le nom / l’e-mail / l’avatar d’un membre dans toute l’organisation
GET/organization-invitations/{token} · POST …/{token}/acceptRé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}/downloadExport 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éthodeCheminDescription
GET/projectsLister vos projets (limit ≤ 200)
POST/projectsCré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-organizationDéplacer le projet vers une autre organisation (manager)
POST/projects/{id}/slack/testEnvoyer un message de test au flux Slack du projet (manager)
GET / POST/projects/{id}/showcase_claim_eligibility · /projects/{id}/showcase_claim · /projects/{id}/showcase_seedProjets vitrines publics : vérifier si vous pouvez en revendiquer un, le revendiquer, l’amorcer
GET/projects/{id}/audit-logLecture 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}/eventsFlux 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.

MéthodeCheminDescription
GET/projects/{id}/membershipsLister les membres (viewer)
POST/projects/{id}/membershipsInviter 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-existingMembres de l’organisation pas encore sur le projet / en ajouter un sans invitation par e-mail (manager)
POST/projects/{id}/members/joinUn 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}/anonymizationMasquer le nom / l’e-mail / l’avatar d’un membre sur ce projet (manager)
GET / POST/projects/{id}/agent_keysLister / é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/onboardingLe 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}/avatarRenouveler 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éthodeCheminDescription
GET/projects/{id}/storiesLister les stories (paginées, filtrables) (viewer)
POST/projects/{id}/storiesCré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}/transitionsChanger d’état avec validation
POST/projects/{id}/stories/{sid}/reject · /projects/{id}/stories/{sid}/restartRejeter 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}/unarchiveArchiver / désarchiver une story
POST/projects/{id}/stories/bulk_transitionFaire transiter plusieurs stories (1–100) à la fois
POST/projects/{id}/stories/bulk-archive · bulk-delete · bulk-duplicate · bulk-moveArchiver, supprimer, dupliquer ou déplacer (vers un panneau / une position) plusieurs stories
POST/projects/{id}/stories/{sid}/duplicateDupliquer une story
GET / POST / DELETE/projects/{id}/stories/{sid}/epics · …/epics/{eid}L’appartenance de la story aux epics
GET/short-links/{code} · /story-referencesRé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 } ] }.

Toutes en member. La liste/GET sur la plupart est en (viewer).

MéthodeCheminCorps / 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_typerelates_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éthodeCheminDescription
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-attachmentsPiè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éthodeCheminDescription
GET / POST/projects/{id}/labelsLister / créer un label
PUT / DELETE/projects/{id}/labels/{lid}Mettre à jour / supprimer un label
POST/projects/{id}/labels/{lid}/archiveArchiver (masquer en douceur) un label

Les lectures sont ouvertes à tout rôle de projet, et anonymes sur un projet public.

MéthodeCheminDescription
GET/projects/{id}/iterationsLister 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-previewLes dates que recevrait la première itération, affichées dans la confirmation de création
POST/projects/{id}/iterationsCréer une itération manuelle (member)
DELETE/projects/{id}/iterations/{itid}Supprimer une itération (manager)
PUT/projects/{id}/iterations/{itid}/velocityRemplacer la vélocité d’une itération sans changer la stratégie du projet (manager)
GET/projects/{id}/iterations/{itid}/done-storiesLes stories acceptées d’une itération close, paginées
MéthodeCheminDescription
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/groupingLes groupes d’itérations projetés du Backlog (viewer)
GET / PUT/projects/{id}/preferencesVos préférences de tableau pour ce projet — tout rôle de projet, uniquement votre propre ligne
MéthodeCheminDescription
GET/projects/{id}/eventsFlux 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.

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éthodeCheminDescription
GET/me/notificationsVotre flux de notifications. Filtres : unread=true, since_id=, kind= (mentions / reviews / stories / invitations) ; paginez avec cursor= / limit=
GET/me/notifications/unread-countTotaux non lus — { unread_count, by_category: { mentions, reviews, stories, invitations } }
POST/me/notifications/read-allTout marquer comme lu ; renvoie les compteurs à jour
POST/me/notifications/{id}/ackMarquer un élément comme lu (idempotent)
POST/me/notifications/{id}/acceptAccepter une invitation à un projet / une organisation depuis le flux (jetons membre uniquement)
POST/me/notifications/{id}/declineDé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/streamPush 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.

MéthodeCheminDescription
POST/projects/{id}/importSources 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/jsonCorps 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éthodeCheminDescription
GET/projects/{id}/export/formatsFormats 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/attachmentsToutes 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.

MéthodeCheminDescription
GET / POST/projects/{id}/backups · GET …/backups/{snapshot_id} · …/backups/healthLister 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).

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.

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.

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.

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.

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

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"] } }
StatutcodeQuand
400invalid_parameterentrée incorrecte ; message dans error, pas de details (la plupart des validations : vide/longueur/octet null/e-mail)
400validation_failederreur d’entrée structurée ; details.fields est un tableau de noms de champs en cause
401unauthenticatedjeton manquant/invalide
403unauthorized_operationauthentifié mais rôle insuffisant
404unfound_resourceintrouvable — également renvoyé aux non-membres
409conflictconflit de ressource (par ex. doublon)
409idempotency_conflictIdempotency-Key réutilisée avec un corps différent
409stale_write · import_already_runningla story a changé depuis votre expected_updated_at · un import est déjà en cours
412precondition_failedIf-Match ne correspond pas à l’ETag actuel de la ressource ; details contient expected et current
413request_too_largele corps dépasse la limite de taille de la route
422invalid_transitiondéplacement d’état illégal ; details contient { from, to, allowed }
429rate_limitedtrop de requêtes depuis cette IP sur une route à débit limité ; en-tête Retry-After
500internal_errordéfaillance serveur — message générique ; peut être réessayé sans risque
503not_configuredle 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"] } }

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