A referência completa de endpoints REST. Para tutoriais e exemplos, veja o Guia da API.
Tudo o que um member do projeto pode fazer na interface web está disponível aqui — o SPA consome esta mesma API. As operações que exigem o papel de manager são marcadas com (manager); todo o resto precisa apenas de associação ao projeto (ou, para leituras marcadas com (viewer), qualquer nível de acesso). As tabelas abaixo nomeiam cada grupo de rotas que o servidor monta; os resumidos em uma única linha estão descritos por completo no openapi.json ao vivo.
https://eastagiletracker.com/api/v1https://api.eastagiletracker.com/api/v1 serve a API idêntica. Todas as requisições e respostas são JSON, exceto alguns endpoints de upload de arquivo que aceitam multipart.
Dois grupos ficam um nível acima, em /api em vez de /api/v1: a superfície de autenticação (/api/auth/*) e os formulários públicos (/api/contact, /api/feedback). As variantes /api/v1/… deles retornam 404.
Autenticação
Seção intitulada “Autenticação”Toda requisição autenticada envia uma credencial por uma das opções:
X-TrackerToken: <key>Authorization: Bearer <key>
As chaves de usuário começam com ea_user_, as chaves de agente com ea_agent_ e os tokens de acesso MCP com ea_mcp_. Veja Guia da API → Três tipos de credenciais.
Endpoints não autenticados: /openapi.json, /docs, os endpoints /api/auth/* e as consultas de dados de referência (/story_types, /story_states, /effort_scales, /priority_scales). /meta é autenticado — qualquer chave válida funciona, mas não tem escopo de projeto (uma chave de agente vinculada a um projeto também o alcança).
Quatro níveis controlam os endpoints com escopo de projeto:
| Nível | Quem passa | Operações típicas |
|---|---|---|
| public viewer | qualquer pessoa, em um projeto com visibilidade pública | leituras do quadro: histórias, iterações, busca, atividade de histórias e épicos (com os detalhes do ator censurados) |
| viewer | viewer, member, manager | leituras (listar/obter histórias, buscar, métricas, lista de formatos de exportação) |
| member | member, manager | todas as escritas de item de trabalho (histórias, tarefas, comentários, …), o fluxo de eventos |
| manager | apenas manager | configurações do projeto, gerenciamento de associação, chaves de agente, exclusão, importação, downloads de exportação, backups, audit log |
Os agentes têm os mesmos papéis que os membros — viewer, member ou manager — limitados ao papel do membro que emitiu a chave. Um não-membro recebe 404 unfound_resource (não 403) em caminhos de projetos privados, então os IDs de projeto não são enumeráveis.
Endpoints autodescritivos
Seção intitulada “Endpoints autodescritivos”| Método | Caminho | Descrição |
|---|---|---|
| GET | /openapi.json | A especificação OpenAPI 3 ao vivo, com os corpos de requisição. Não autenticado. |
| GET | /docs | Swagger UI. Não autenticado. |
| GET | /meta | Identidade do chamador (auth.kind/key_id/agent_id/project_id) + o grafo de transições por tipo de história. Autenticado (qualquer chave válida; sem escopo de projeto). Chame isto primeiro. |
| GET | /api/health · /api/config | Verificação de disponibilidade e a configuração pública do deployment (modo de organização única, recursos opcionais ativados, nome da instância). Não autenticados, fora de /v1. |
Auth (/api/auth/*, fora de /v1)
Seção intitulada “Auth (/api/auth/*, fora de /v1)”Endpoints de sessão, não autenticados salvo indicação em contrário. O SPA os aciona; scripts normalmente usam uma chave de API.
| Método | Caminho | Descrição |
|---|---|---|
| POST | /auth/register | Registra uma nova conta — protegido por reCAPTCHA; a conta depois passa pela verificação por SMS |
| POST | /auth/sms/challenge · /auth/sms/status · /auth/sms/bypass | Envia / verifica o código SMS do cadastro (o bypass é restrito ao operador) |
| GET | /auth/config | Quais métodos de login o deployment oferece |
| POST | /auth/login | Login com e-mail + senha; retorna um JWT de sessão ou um desafio TOTP |
| POST | /auth/login/totp | Conclui um login com um código do app autenticador ou um código de recuperação |
| POST | /auth/passkey/login/start · /auth/passkey/login/finish | Login WebAuthn sem senha |
| GET | /auth/oauth/github/start · /auth/oauth/github/callback · /auth/oauth/google/start · /auth/oauth/google/callback · POST /auth/oauth/exchange | Login OAuth com GitHub ou Google |
| POST | /auth/refresh · /auth/refresh/revoke | Rotaciona o refresh token / revoga-o |
| POST | /auth/logout | Faz logout (revoga o refresh token) |
| POST | /auth/forgot-password · /auth/reset-password | Solicita um e-mail de redefinição / usa o token de redefinição |
| POST | /auth/accept-invite/lookup · /auth/accept-invite | Resolve um token de convite → e-mail / aceita o convite de projeto (após autenticar) |
Conta / identidade
Seção intitulada “Conta / identidade”Estes atuam sobre o chamador e precisam apenas de uma chave válida (sem papel de projeto).
| Método | Caminho | Descrição |
|---|---|---|
| GET | /me | Perfil do usuário atual |
| PUT | /me | Atualiza o perfil |
| DELETE | /me | Exclui a conta — recusado enquanto você for o único owner de uma organização ou de um projeto com outros membros |
| GET | /me/deletion-impact | O que a exclusão da conta removeria e o que a impede |
| PUT | /me/password | Altera a senha |
| PUT | /me/settings | Atualiza as configurações (tema, preferências de notificação) |
| POST | /me/avatar | Faz upload do avatar (multipart) |
| POST | /me/api-token/regenerate | Rotaciona seu token de API — invalida sessões/chaves existentes |
| GET | /me/api_keys · POST /me/api_keys · DELETE /me/api_keys/{id} | Gerencia chaves de API de usuário (ea_user_) |
| GET | /me/totp · POST /me/totp/setup · /me/totp/verify · /me/totp/disable | Ativação da autenticação em dois fatores (TOTP); verify retorna os códigos de recuperação uma única vez |
| GET | /me/passkeys · POST /me/passkeys/register/start · /me/passkeys/register/finish · DELETE /me/passkeys/{credential_id} | Cadastro e remoção de passkeys |
| GET | /me/oauth_grants · DELETE /me/oauth_grants/{grant_id} | Apps conectados — os clientes MCP e apps OAuth que você autorizou |
| GET | /me/activity | Sua atividade em todos os projetos |
| GET | /me/stories | Histórias das quais você é owner, que solicitou ou que segue, em todos os projetos que o token alcança — role=owned|requested|following, state=, cursor= / limit= (máx. 200) |
| GET | /me/mentions · POST /me/mentions/{mention_id}/ack | A caixa de @-menções (unacked=true para filtrar) e a confirmação de leitura — também incorporada ao feed de notificações abaixo |
| GET | /me/data-export | Autoexportação GDPR dos seus dados |
| GET | /me/consent · POST /me/consent | Lê / registra consentimento ({ consent_type, granted }) |
| GET | /legal/pending · POST /legal/accept | Documentos clickwrap pendentes / registra aceitação |
| GET / PUT | /agent/me | A identidade e o perfil de uma chave de agente, legíveis e editáveis pelo próprio agente (a contraparte de /me do lado do agente) |
| POST | /api/contact · /api/feedback · /api/feedback/with-screenshot | Contato + feedback no aplicativo. Fora de /v1; com limite de taxa por IP |
Dados de referência (não autenticados)
Seção intitulada “Dados de referência (não autenticados)”Consultas de seed usadas ao criar/estimar histórias. IDs estáveis.
| Método | Caminho | Descrição |
|---|---|---|
| GET | /story_types | feature, bug, chore, release (+ allow_points) |
| GET | /story_states | unstarted … accepted, rejected |
| GET | /effort_scales | escalas de estimativa disponíveis |
| GET | /effort_scales/{scale_id}/values | os valores de pontos em uma escala |
| GET | /priority_scales · /priority_scales/{scale_id}/values | as escalas de prioridade e seus valores (o priority_id de uma história é resolvido aqui) |
Organizações
Seção intitulada “Organizações”Somente no serviço hospedado — uma instalação self-hosted roda em modo de organização única e não monta estes endpoints (exceto a lista de organizações). Os papéis são papéis de organização: owner, admin, member.
| Método | Caminho | Descrição |
|---|---|---|
| GET / POST | /organizations | Lista suas organizações / cria uma |
| GET / PUT / DELETE | /organizations/{oid} | Lê, renomeia (nome + slug; owner ou admin), exclui |
| GET / POST | /organizations/{oid}/memberships · PUT / DELETE …/memberships/{member_id} | Membros e convites; os convites têm um teto de papel (nunca acima do papel do chamador; o owner nunca é convidado) |
| POST | /organizations/{oid}/memberships/bulk-role · …/memberships/bulk-remove | Altere o papel de até 200 membros de uma vez ou remova-os. Tudo ou nada: um lote que removeria o último owner ou deixaria um projeto sem proprietário é recusado por inteiro; com reassign_confirmed você passa a ser proprietário desses projetos |
| DELETE | /organizations/{oid}/invitations/{invitation_id} | Revoga um convite pendente |
| POST | /organizations/{oid}/transfer-ownership | Passa o papel de owner para outro membro |
| PUT | /organizations/{oid}/memberships/{member_id}/anonymization | Mascara o nome / e-mail / avatar de um membro em toda a organização |
| GET | /organization-invitations/{token} · POST …/{token}/accept | Resolve / aceita um convite de organização recebido por e-mail |
| POST | /organizations/{oid}/export · GET / POST …/export/jobs · GET …/export/jobs/{job_id} · …/export/jobs/{job_id}/download | Exportação da organização exclusiva do owner: um zip com um dump SQL e todos os anexos, executada como job |
Projetos
Seção intitulada “Projetos”| Método | Caminho | Descrição |
|---|---|---|
| GET | /projects | Lista seus projetos (limit ≤ 200) |
| POST | /projects | Cria um projeto |
| GET | /projects/{id} | Obtém detalhes do projeto (viewer) |
| PUT | /projects/{id} | Atualiza as configurações do projeto (manager) |
| DELETE | /projects/{id} | Exclui um projeto (manager) |
| POST | /projects/{id}/pin | Fixa / desafixa o projeto na sua lista de projetos |
| POST | /projects/{id}/transfer-organization | Move o projeto para outra organização (manager) |
| POST | /projects/{id}/slack/test | Envia uma mensagem de teste ao feed do Slack do projeto (manager) |
| GET / POST | /projects/{id}/showcase_claim_eligibility · /projects/{id}/showcase_claim · /projects/{id}/showcase_seed | Projetos de vitrine públicos: verifica se você pode reivindicar um, reivindica, popula |
| GET | /projects/{id}/audit-log | Leitura do audit log — histórico do projeto mais atividade por história / por épico via surface=; o acesso varia conforme o surface, veja abaixo |
| GET | /projects/{id}/events | Fluxo de eventos paginado por cursor (member) — veja Eventos |
Parâmetros de consulta do audit log: event_type= (um tipo ou lista separada por vírgulas), limit= (≤ 1000), before= (cursor keyset, created_at ISO-8601), surface= (project_history, story_activities, epic_activities), target_id= (o id da história/épico — obrigatório quando surface=story_activities ou epic_activities). Acesso: o log sem filtro e surface=project_history são (manager); story_activities / epic_activities podem ser lidos por qualquer membro do projeto, e anonimamente em projetos públicos com a PII do ator censurada.
Membros, agentes e chaves de agente
Seção intitulada “Membros, agentes e chaves de agente”| Método | Caminho | Descrição |
|---|---|---|
| GET | /projects/{id}/memberships | Lista membros (viewer) |
| POST | /projects/{id}/memberships | Convida um membro por e-mail (manager) |
| PUT | /projects/{id}/memberships/{mid} | Atualiza o papel (manager) |
| DELETE | /projects/{id}/memberships/{mid} | Remove um membro (manager) |
| GET | /projects/{id}/addable-members · POST /projects/{id}/members/add-existing | Membros da organização que ainda não estão no projeto / adiciona um sem convite por e-mail (manager) |
| POST | /projects/{id}/members/join | Um owner ou admin da organização entra como manager em um projeto da sua organização, ou se promove a manager (a ação Make me owner na lista de projetos) |
| PUT | /projects/{id}/members/{mid}/anonymization | Mascara o nome / e-mail / avatar de um membro neste projeto (manager) |
| GET / POST | /projects/{id}/agent_keys | Lista / emite chaves de agente — managers, ou os papéis que a política de papéis criadores do projeto admite |
| DELETE | /projects/{id}/agent_keys/{kid} | Revoga uma chave de agente |
| GET | /projects/{id}/agent_keys/onboarding | O pacote de onboarding: prompts e arquivos de configuração para os clientes de agente mais comuns |
| GET | /projects/{id}/agents · GET / PUT /projects/{id}/agents/{aid} | Os agentes do projeto e seus perfis (nome, iniciais, descrição, cor) |
| POST | /projects/{id}/agents/{aid}/rotate-key · /projects/{id}/agents/{aid}/avatar | Rotaciona a chave de um agente (identidade e histórico mantidos) / faz upload do avatar dele |
Histórias
Seção intitulada “Histórias”Todas as escritas de história precisam do papel member.
| Método | Caminho | Descrição |
|---|---|---|
| GET | /projects/{id}/stories | Lista histórias (paginadas, filtráveis) (viewer) |
| POST | /projects/{id}/stories | Cria uma história |
| GET | /projects/{id}/stories/{sid} | Obtém uma história (viewer) |
| PUT | /projects/{id}/stories/{sid} | Atualiza uma história |
| DELETE | /projects/{id}/stories/{sid} | Exclui uma história |
| POST | /projects/{id}/stories/{sid}/transitions | Altera o estado com validação |
| POST | /projects/{id}/stories/{sid}/reject · /projects/{id}/stories/{sid}/restart | Rejeita uma história delivered / devolve uma rejeitada a started (rejected é terminal para /transitions) |
| POST | /projects/{id}/stories/{sid}/archive · /projects/{id}/stories/{sid}/unarchive | Arquiva / desarquiva uma história |
| POST | /projects/{id}/stories/bulk_transition | Transiciona muitas histórias (1–100) de uma vez |
| POST | /projects/{id}/stories/bulk-archive · bulk-delete · bulk-duplicate · bulk-move | Arquiva, exclui, duplica ou move (para um painel / posição) muitas histórias |
| POST | /projects/{id}/stories/{sid}/duplicate | Duplica uma história |
| GET / POST / DELETE | /projects/{id}/stories/{sid}/epics · …/epics/{eid} | A associação da história a épicos |
| GET | /short-links/{code} · /story-references | Resolve um link curto /s/<code> para a sua história / resolve até 100 referências de histórias (#id, URLs) para as histórias que o chamador pode ler |
Parâmetros de consulta da lista de histórias: archived= (exclude padrão / include / only — o filtro de arquivamento de três estados; substitui o obsoleto include_archived=true, agora um alias de archived=include), include_done=true (admite histórias do painel Done congeladas em iterações passadas, excluídas por padrão). Paginação (cursor= / limit= / offset=) e conjuntos esparsos de campos (fields=) seguem Paginação e Projeção de campos.
Criar (POST …/stories): { "name" (required), "story_type": "feature|bug|chore|release", "description"?, "estimate"?, "current_state"?, "icebox"?, "labels"? }. estimate é o rótulo do valor da escala, como string ("3", "13"); um número JSON é rejeitado. labels aceita ["auth"] ou [{ "name": "auth" }]; labels desconhecidas são criadas. Padrões: story_type=feature, current_state=unstarted.
Atualizar (PUT …/stories/{sid}): os mesmos campos, todos opcionais, mais "position" (float), "force_state_change" (bool) e "expected_updated_at" (RFC 3339 — salvar uma descrição é recusado com 409 stale_write se a história mudou desde que você a leu). As escritas de história também respeitam If-Match contra o ETag da história; uma divergência resulta em 412 precondition_failed.
Transição (POST …/transitions): { "to": "<state>" }. O campo é to. Retorna { story_id, state }. Movimento ilegal → 422 invalid_transition com details: { from, to, allowed }.
Transição em massa (POST …/bulk_transition): { "story_ids": [int,…] (1–100), "to": "<state>" }. Cada história é julgada de forma independente; retorna { results: [ { id, status: "ok" } | { id, status: "failed", error } ] }.
Sub-recursos da história
Seção intitulada “Sub-recursos da história”Todos member. Listar/GET na maioria é (viewer).
| Método | Caminho | Corpo / observações |
|---|---|---|
| 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 recebe fields= (lista de permitidos: comment_id, story_comment_id, story_id, comment_text, comment_emoji, member, created) mais 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; URLs /pull/ e /tree/ do GitHub recebem o tipo automaticamente |
| GET / POST | /projects/{id}/stories/{sid}/reviews · PUT/DELETE …/reviews/{rid} | Criar: { reviewer_id? / reviewer_agent_id?, comment? } — omita ambos para atribuir a você mesmo. Atualizar: { status, comment? } |
| GET / POST | /projects/{id}/stories/{sid}/owners · DELETE …/owners/{mid} · DELETE …/owners/agents/{aid} | { member_id? / agent_id? } — omita ambos para adicionar o chamador |
| 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} | upload multipart — vídeo ≤ 200 MB, PDF / Word / Excel ≤ 25 MB, imagens / CSV / texto ≤ 10 MB; listar é (viewer) |
| GET / POST | /projects/{id}/stories/{sid}/link-attachments · DELETE …/link-attachments/{laid} | Anexos de link — uma URL externa mantida junto aos anexos de arquivo, e não como link de código |
| GET | /attachments/{token} · /api/avatars/{token} | Leituras endereçadas por token de um anexo ou avatar — as URLs que a API entrega; não precisam de X-TrackerToken |
Mesmo formato das histórias, sem a máquina de estados. member para escritas, (viewer) para leituras.
| Método | Caminho | Descrição |
|---|---|---|
| GET / POST | /projects/{id}/epics · GET / PUT / DELETE …/epics/{eid} | Os épicos têm um nome, uma descrição em Markdown e uma label de apoio que reúne suas histórias |
| GET / POST / PUT / DELETE | …/epics/{eid}/comments · …/comments/{cid} | Comentários de épicos |
| GET / POST / DELETE | …/epics/{eid}/owners · …/followers (+ variantes /agents/{aid}) | Owners e seguidores, membros ou agentes — os owners de um épico se propagam para suas histórias |
| GET / POST / DELETE | …/epics/{eid}/attachments (+ /json) · …/link-attachments | Anexos, com os mesmos limites das histórias |
| GET | /projects/{id}/analytics/epics · …/analytics/epics/{eid} | Progresso por épico: burnup, vazão, saúde, previsão (viewer) |
member para escritas, (viewer) para leituras.
| Método | Caminho | Descrição |
|---|---|---|
| GET / POST | /projects/{id}/labels | Lista / cria uma label |
| PUT / DELETE | /projects/{id}/labels/{lid} | Atualiza / exclui uma label |
| POST | /projects/{id}/labels/{lid}/archive | Arquiva (oculta suavemente) uma label |
Iterações
Seção intitulada “Iterações”As leituras são abertas a qualquer papel de projeto, e anônimas em um projeto público.
| Método | Caminho | Descrição |
|---|---|---|
| GET | /projects/{id}/iterations | Lista iterações (≤ 500 por página; traz um ETag e os cabeçalhos de continuação X-Tracker-Pagination-* quando truncada) |
| GET | /projects/{id}/iterations/{itid} | Uma iteração |
| GET | /projects/{id}/iterations/first-preview | As datas que a primeira iteração receberia, mostradas na confirmação de criação |
| POST | /projects/{id}/iterations | Cria uma iteração manual (member) |
| DELETE | /projects/{id}/iterations/{itid} | Exclui uma iteração (manager) |
| PUT | /projects/{id}/iterations/{itid}/velocity | Substitui a velocidade de uma iteração sem alterar a estratégia do projeto (manager) |
| GET | /projects/{id}/iterations/{itid}/done-stories | As histórias aceitas de uma iteração encerrada, paginadas |
Busca, métricas, preferências
Seção intitulada “Busca, métricas, preferências”| Método | Caminho | Descrição |
|---|---|---|
| GET | /projects/{id}/search?q=… | Busca poderosa — texto completo + qualificadores de faceta / intervalo de datas / pessoas (DSL no estilo do GitHub); retorna { results, total, limit, offset }. query é um alias de q; limit= (padrão 50, máx. 1000) / offset= paginam; sort= ordena por relevance (padrão), created, created_asc, state ou updated. (viewer) — veja o Guia |
| GET | /projects/{id}/metrics/{velocity,burndown,story-types,contributors} | As séries da página Metrics (viewer); as métricas de épicos ficam em /analytics/epics, acima |
| GET | /projects/{id}/backlog/grouping | Os grupos de iterações projetados do Backlog (viewer) |
| GET / PUT | /projects/{id}/preferences | Suas preferências de quadro para este projeto — qualquer papel de projeto, apenas a sua própria linha |
Eventos
Seção intitulada “Eventos”| Método | Caminho | Descrição |
|---|---|---|
| GET | /projects/{id}/events | Fluxo de eventos paginado por cursor (member) — viewers recebem 403 |
Parâmetros de consulta: since=<event_id>, types=story.created,story.transitioned,comment.added,…, limit= (≤ 500), cursor=. A resposta inclui next_cursor. Passe o último event_id que você viu como since para retomar.
Notificações
Seção intitulada “Notificações”O feed unificado de notificações no app: linhas de notificação de primeira classe (pedidos de review, atividade de histórias, convites, …) mescladas com a caixa de @-menções em um único fluxo, do mais recente para o mais antigo. Os ids do feed têm prefixo de origem (nt-… / sc-… / ec-…). Sessões de membro e chaves ea_user_* leem suas linhas de membro; chaves ea_agent_* suas linhas de agente.
| Método | Caminho | Descrição |
|---|---|---|
| GET | /me/notifications | Seu feed de notificações. Filtros: unread=true, since_id=, kind= (mentions / reviews / stories / invitations); pagine com cursor= / limit= |
| GET | /me/notifications/unread-count | Totais não lidos — { unread_count, by_category: { mentions, reviews, stories, invitations } } |
| POST | /me/notifications/read-all | Marcar tudo como lido; devolve os contadores atualizados |
| POST | /me/notifications/{id}/ack | Marcar um item como lido (idempotente) |
| POST | /me/notifications/{id}/accept | Aceitar um convite de projeto / organização a partir do feed (apenas tokens de membro) |
| POST | /me/notifications/{id}/decline | Recusar um convite de projeto / organização (apenas tokens de membro) |
| GET | /me/notifications/resolve-invite?token=… | Resolver um token de convite recebido por e-mail para o id da sua notificação — { "id": "nt-…" } ou { "id": null } |
| GET | /me/notifications/stream | Push ao vivo — Server-Sent Events (text/event-stream); veja abaixo |
O endpoint de stream não é um endpoint JSON e, portanto, não está na especificação OpenAPI: ele mantém a conexão aberta e emite um frame sem payload ({"type":"notification","kind":…}) sempre que algo novo chega, sinalizando ao cliente que recarregue o feed. As conexões são encerradas no servidor após 45 minutos — reconecte e autentique-se novamente. Apenas sessões de membro e chaves ea_user_*; chaves ea_agent_* recebem 403.
Importação (manager)
Seção intitulada “Importação (manager)”| Método | Caminho | Descrição |
|---|---|---|
| POST | /projects/{id}/import | Fontes de arquivo: source= ∈ pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat. Multipart file=. Síncrono — responde com as contagens do resultado. |
| POST | /projects/{id}/import/json | Corpo JSON; source=github não precisa de arquivo — owner, repo, token opcional e as flags opt-in include_pull_requests / include_milestones / include_releases / include_dependencies; as fontes de arquivo enviam file_base64. Assíncrono: retorna 202 { import_id, status }. O servidor busca pela API GraphQL do GitHub, que rejeita chamadores anônimos, então um token sempre chega ao GitHub — o seu, ou o compartilhado do deployment. Veja o Guia. |
| GET | /projects/{id}/imports/{import_id} | Consulta um job: status avança por pending → fetching → writing → done | failed, com progress_current / progress_total durante a busca e as contagens do resultado em done |
Só uma importação roda por projeto de cada vez; um segundo POST enquanto outra está em andamento dá 409 import_already_running. dry_run: true (corpo JSON ou dry_run=true multipart) faz a prévia de qualquer fonte: analisa, resolve, remove duplicatas, retorna as mesmas contagens { imported, skipped, errors, unmatched } e então reverte — nada é escrito. Limites: corpo de 10 MiB e 5.000 histórias por importação para as fontes de arquivo (acima de qualquer um → 400, nada escrito). A fonte GitHub não tem teto — ela grava em blocos em vez de uma única transação. A reimportação é idempotente por id de origem — linhas já importadas são ignoradas, não duplicadas.
Exportação
Seção intitulada “Exportação”| Método | Caminho | Descrição |
|---|---|---|
| GET | /projects/{id}/export/formats | Formatos registrados: { id, name, content_type, drops, includes_archived }. Qualquer papel de projeto. |
| GET | /projects/{id}/export/{format} | Baixa um (manager). Intercâmbio: eat (fidelidade total), jira, pivotal, shortcut, trello, asana, gitlab, linear, plane, plane_json; documentos: pdf, docx. |
| GET | /projects/{id}/export/attachments | Todo anexo como um único zip navegável (os arquivos mantêm os nomes originais; manifesto JSON + CSV) (manager). |
Exportações de documentos (pdf, docx) recebem parâmetros de consulta extras: page_size= (letter padrão / a4 / legal / folio), from= / to= (limites da janela de histórias — RFC 3339 ou apenas YYYY-MM-DD; uma história está no intervalo quando seu created ou completed_at cai dentro dele), include_icebox= / include_backlog= (ambos padrão false, então uma exportação compartilhável mostra apenas trabalho agendado / em andamento). Os formatos CSV de intercâmbio os ignoram.
Backups e restaurações (manager)
Seção intitulada “Backups e restaurações (manager)”| Método | Caminho | Descrição |
|---|---|---|
| GET / POST | /projects/{id}/backups · GET …/backups/{snapshot_id} · …/backups/health | Lista snapshots, cria um agora, lê um, e o resumo de saúde da retenção |
| GET / POST | /projects/{id}/restores · POST …/restores/partial · GET …/restores/{restore_id} | Restaura um snapshot inteiro, ou tabelas selecionadas de um, e consulta o andamento da restauração |
Esses POSTs ficam no nível de limite de taxa sensitive (abaixo).
MCP e provedor OAuth
Seção intitulada “MCP e provedor OAuth”East Agile Tracker é um provedor OAuth 2.1 para clientes MCP. Um cliente o descobre em /.well-known/oauth-authorization-server e /.well-known/oauth-protected-resource/mcp, envia você para /oauth/authorize (a página de consentimento), troca o código em /oauth/token e então fala MCP em /mcp com o token ea_mcp_* resultante. As autorizações são listadas e revogadas em /me/oauth_grants. Os endpoints do provedor têm seu próprio nível de limite de taxa.
WebSocket
Seção intitulada “WebSocket”wss://eastagiletracker.com/ws/control?token=<session JWT>Para controle remoto interativo da interface ({ "action": "get_state", "id": "req-1" }). O token é um JWT de sessão do navegador — uma chave de API é recusada com 401 antes do upgrade. Não é um canal de dados — todas as leituras/escritas passam pelo REST. Apenas instância única; não distribuído entre réplicas.
Idempotência
Seção intitulada “Idempotência”Os endpoints de escrita (POST, PUT, DELETE) aceitam um cabeçalho Idempotency-Key. A mesma chave + o mesmo corpo reproduz a resposta em cache (janela de 24 horas); a mesma chave + um corpo diferente retorna 409 idempotency_conflict. A chave tem como escopo a credencial que a enviou. Não se aplica a GET/HEAD/OPTIONS, a /openapi.json e /docs, a /api/auth/* nem a uploads multipart em caminhos /attachments. Respostas que pararam antes de uma resposta de domínio nunca são armazenadas em cache — 401, 403, 404, 429 e todo 5xx — então uma nova tentativa depois de qualquer uma delas alcança o handler; 400, 409, 412 e 422 são a resposta do domínio e são reproduzidas como um sucesso.
Paginação
Seção intitulada “Paginação”Os endpoints de listagem aceitam cursor=<opaque> e limit=<n>. Quando definidos, a resposta é { "items": [...], "next_cursor": "<str|null>" }; passe next_cursor de volta para paginar. O teto de limit é por endpoint: 200 em histórias, comentários e projetos; 500 em eventos; 1000 na busca e no audit log.
Uma lista simples (sem cursor/limit) que precisou truncar a resposta avisa nos cabeçalhos — X-Tracker-Pagination-Truncated, X-Tracker-Pagination-Limit, X-Tracker-Pagination-Offset e X-Tracker-Pagination-Next-Offset; passe o último de volta como offset= para a próxima página. Não há cabeçalho com a contagem total.
Projeção de campos
Seção intitulada “Projeção de campos”Os endpoints de listagem aceitam fields= (separados por vírgula) para retornar apenas campos específicos. story_id é sempre incluído; um nome de campo desconhecido retorna 400 validation_failed com os nomes problemáticos em details.fields.
GET /projects/123/stories?fields=story_id,name,current_state,ownersFormato de erro
Seção intitulada “Formato de erro”Todo erro JSON tem code e error; alguns adicionam details:
{ "code": "invalid_transition", "error": "Cannot move story from `unstarted` to `accepted`", "details": { "from": "unstarted", "to": "accepted", "allowed": ["started"] } }| Status | code | Quando |
|---|---|---|
| 400 | invalid_parameter | entrada inválida; mensagem em error, sem details (a maioria das validações: em branco/comprimento/byte nulo/e-mail) |
| 400 | validation_failed | erro de entrada estruturado; details.fields é um array dos nomes dos campos problemáticos |
| 401 | unauthenticated | token ausente/inválido |
| 403 | unauthorized_operation | autenticado, mas com papel insuficiente |
| 404 | unfound_resource | não encontrado — também retornado a não-membros |
| 409 | conflict | conflito de recurso (por exemplo, duplicata) |
| 409 | idempotency_conflict | Idempotency-Key reutilizado com um corpo diferente |
| 409 | stale_write · import_already_running | a história mudou desde o seu expected_updated_at · uma importação já está em andamento |
| 412 | precondition_failed | If-Match não corresponde ao ETag atual do recurso; details traz expected e current |
| 413 | request_too_large | o corpo excede o limite de tamanho da rota |
| 422 | invalid_transition | movimento de estado ilegal; details carrega { from, to, allowed } |
| 429 | rate_limited | requisições demais deste IP em uma rota com limite de taxa; cabeçalho Retry-After |
| 500 | internal_error | falha do servidor — mensagem genérica; seguro para tentar novamente |
| 503 | not_configured | o deployment não tem a integração de que esta rota precisa (SMS, armazenamento de objetos, …) |
details.fields é um array JSON de nomes de campos (por exemplo, ["to"]), às vezes com chaves extras como max. Não há um mapa de campo→mensagem.
{ "code": "validation_failed", "error": "unknown field(s): foo", "details": { "fields": ["foo"] } }Limites de taxa
Seção intitulada “Limites de taxa”Por IP de cliente, em um punhado de rotas; o restante do tráfego autenticado da API não tem limite de taxa. Padrões (cada par é a taxa sustentada e o burst, ajustáveis pelo operador):
- Auth —
/api/auth/*: 0,5 req/s, burst 20. - OAuth provider —
/oauth/*: 1 req/s, burst 60. - Public —
/api/contact: 0,2 req/s, burst 10. - Feedback —
/api/feedback: três níveis sobrepostos — um envio a cada 15 s, 10 por hora, 36 por dia. - Avatars — o redirecionamento de avatar não autenticado: 20 req/s, burst 200.
- Sensitive — os
POSTs de backup e restauração: ~0,002 req/s, burst 5.
Um limite excedido retorna 429 com um cabeçalho Retry-After e o envelope de erro JSON padrão, code: "rate_limited".