Pular para o conteúdo

Especificação da API

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

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

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ívelQuem passaOperações típicas
public viewerqualquer pessoa, em um projeto com visibilidade públicaleituras do quadro: histórias, iterações, busca, atividade de histórias e épicos (com os detalhes do ator censurados)
viewerviewer, member, managerleituras (listar/obter histórias, buscar, métricas, lista de formatos de exportação)
membermember, managertodas as escritas de item de trabalho (histórias, tarefas, comentários, …), o fluxo de eventos
managerapenas managerconfiguraçõ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.

MétodoCaminhoDescrição
GET/openapi.jsonA especificação OpenAPI 3 ao vivo, com os corpos de requisição. Não autenticado.
GET/docsSwagger UI. Não autenticado.
GET/metaIdentidade 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/configVerificaçã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.

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étodoCaminhoDescrição
POST/auth/registerRegistra uma nova conta — protegido por reCAPTCHA; a conta depois passa pela verificação por SMS
POST/auth/sms/challenge · /auth/sms/status · /auth/sms/bypassEnvia / verifica o código SMS do cadastro (o bypass é restrito ao operador)
GET/auth/configQuais métodos de login o deployment oferece
POST/auth/loginLogin com e-mail + senha; retorna um JWT de sessão ou um desafio TOTP
POST/auth/login/totpConclui um login com um código do app autenticador ou um código de recuperação
POST/auth/passkey/login/start · /auth/passkey/login/finishLogin WebAuthn sem senha
GET/auth/oauth/github/start · /auth/oauth/github/callback · /auth/oauth/google/start · /auth/oauth/google/callback · POST /auth/oauth/exchangeLogin OAuth com GitHub ou Google
POST/auth/refresh · /auth/refresh/revokeRotaciona o refresh token / revoga-o
POST/auth/logoutFaz logout (revoga o refresh token)
POST/auth/forgot-password · /auth/reset-passwordSolicita um e-mail de redefinição / usa o token de redefinição
POST/auth/accept-invite/lookup · /auth/accept-inviteResolve um token de convite → e-mail / aceita o convite de projeto (após autenticar)

Estes atuam sobre o chamador e precisam apenas de uma chave válida (sem papel de projeto).

MétodoCaminhoDescrição
GET/mePerfil do usuário atual
PUT/meAtualiza o perfil
DELETE/meExclui a conta — recusado enquanto você for o único owner de uma organização ou de um projeto com outros membros
GET/me/deletion-impactO que a exclusão da conta removeria e o que a impede
PUT/me/passwordAltera a senha
PUT/me/settingsAtualiza as configurações (tema, preferências de notificação)
POST/me/avatarFaz upload do avatar (multipart)
POST/me/api-token/regenerateRotaciona 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/disableAtivaçã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/activitySua atividade em todos os projetos
GET/me/storiesHistó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}/ackA 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-exportAutoexportação GDPR dos seus dados
GET/me/consent · POST /me/consentLê / registra consentimento ({ consent_type, granted })
GET/legal/pending · POST /legal/acceptDocumentos clickwrap pendentes / registra aceitação
GET / PUT/agent/meA 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-screenshotContato + feedback no aplicativo. Fora de /v1; com limite de taxa por IP

Consultas de seed usadas ao criar/estimar histórias. IDs estáveis.

MétodoCaminhoDescrição
GET/story_typesfeature, bug, chore, release (+ allow_points)
GET/story_statesunstarted … accepted, rejected
GET/effort_scalesescalas de estimativa disponíveis
GET/effort_scales/{scale_id}/valuesos valores de pontos em uma escala
GET/priority_scales · /priority_scales/{scale_id}/valuesas escalas de prioridade e seus valores (o priority_id de uma história é resolvido aqui)

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étodoCaminhoDescrição
GET / POST/organizationsLista 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-removeAltere 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-ownershipPassa o papel de owner para outro membro
PUT/organizations/{oid}/memberships/{member_id}/anonymizationMascara o nome / e-mail / avatar de um membro em toda a organização
GET/organization-invitations/{token} · POST …/{token}/acceptResolve / 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}/downloadExportação da organização exclusiva do owner: um zip com um dump SQL e todos os anexos, executada como job
MétodoCaminhoDescrição
GET/projectsLista seus projetos (limit ≤ 200)
POST/projectsCria 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}/pinFixa / desafixa o projeto na sua lista de projetos
POST/projects/{id}/transfer-organizationMove o projeto para outra organização (manager)
POST/projects/{id}/slack/testEnvia 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_seedProjetos de vitrine públicos: verifica se você pode reivindicar um, reivindica, popula
GET/projects/{id}/audit-logLeitura 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}/eventsFluxo 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.

MétodoCaminhoDescrição
GET/projects/{id}/membershipsLista membros (viewer)
POST/projects/{id}/membershipsConvida 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-existingMembros da organização que ainda não estão no projeto / adiciona um sem convite por e-mail (manager)
POST/projects/{id}/members/joinUm 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}/anonymizationMascara o nome / e-mail / avatar de um membro neste projeto (manager)
GET / POST/projects/{id}/agent_keysLista / 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/onboardingO 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}/avatarRotaciona a chave de um agente (identidade e histórico mantidos) / faz upload do avatar dele

Todas as escritas de história precisam do papel member.

MétodoCaminhoDescrição
GET/projects/{id}/storiesLista histórias (paginadas, filtráveis) (viewer)
POST/projects/{id}/storiesCria 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}/transitionsAltera o estado com validação
POST/projects/{id}/stories/{sid}/reject · /projects/{id}/stories/{sid}/restartRejeita uma história delivered / devolve uma rejeitada a started (rejected é terminal para /transitions)
POST/projects/{id}/stories/{sid}/archive · /projects/{id}/stories/{sid}/unarchiveArquiva / desarquiva uma história
POST/projects/{id}/stories/bulk_transitionTransiciona muitas histórias (1–100) de uma vez
POST/projects/{id}/stories/bulk-archive · bulk-delete · bulk-duplicate · bulk-moveArquiva, exclui, duplica ou move (para um painel / posição) muitas histórias
POST/projects/{id}/stories/{sid}/duplicateDuplica 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-referencesResolve 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 } ] }.

Todos member. Listar/GET na maioria é (viewer).

MétodoCaminhoCorpo / 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_typerelates_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étodoCaminhoDescriçã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-attachmentsAnexos, 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étodoCaminhoDescrição
GET / POST/projects/{id}/labelsLista / cria uma label
PUT / DELETE/projects/{id}/labels/{lid}Atualiza / exclui uma label
POST/projects/{id}/labels/{lid}/archiveArquiva (oculta suavemente) uma label

As leituras são abertas a qualquer papel de projeto, e anônimas em um projeto público.

MétodoCaminhoDescrição
GET/projects/{id}/iterationsLista 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-previewAs datas que a primeira iteração receberia, mostradas na confirmação de criação
POST/projects/{id}/iterationsCria uma iteração manual (member)
DELETE/projects/{id}/iterations/{itid}Exclui uma iteração (manager)
PUT/projects/{id}/iterations/{itid}/velocitySubstitui a velocidade de uma iteração sem alterar a estratégia do projeto (manager)
GET/projects/{id}/iterations/{itid}/done-storiesAs histórias aceitas de uma iteração encerrada, paginadas
MétodoCaminhoDescriçã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/groupingOs grupos de iterações projetados do Backlog (viewer)
GET / PUT/projects/{id}/preferencesSuas preferências de quadro para este projeto — qualquer papel de projeto, apenas a sua própria linha
MétodoCaminhoDescrição
GET/projects/{id}/eventsFluxo 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.

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étodoCaminhoDescrição
GET/me/notificationsSeu feed de notificações. Filtros: unread=true, since_id=, kind= (mentions / reviews / stories / invitations); pagine com cursor= / limit=
GET/me/notifications/unread-countTotais não lidos — { unread_count, by_category: { mentions, reviews, stories, invitations } }
POST/me/notifications/read-allMarcar tudo como lido; devolve os contadores atualizados
POST/me/notifications/{id}/ackMarcar um item como lido (idempotente)
POST/me/notifications/{id}/acceptAceitar um convite de projeto / organização a partir do feed (apenas tokens de membro)
POST/me/notifications/{id}/declineRecusar 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/streamPush 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.

MétodoCaminhoDescrição
POST/projects/{id}/importFontes 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/jsonCorpo 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.

MétodoCaminhoDescrição
GET/projects/{id}/export/formatsFormatos 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/attachmentsTodo 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.

MétodoCaminhoDescrição
GET / POST/projects/{id}/backups · GET …/backups/{snapshot_id} · …/backups/healthLista 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).

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.

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.

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.

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.

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

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"] } }
StatuscodeQuando
400invalid_parameterentrada inválida; mensagem em error, sem details (a maioria das validações: em branco/comprimento/byte nulo/e-mail)
400validation_failederro de entrada estruturado; details.fields é um array dos nomes dos campos problemáticos
401unauthenticatedtoken ausente/inválido
403unauthorized_operationautenticado, mas com papel insuficiente
404unfound_resourcenão encontrado — também retornado a não-membros
409conflictconflito de recurso (por exemplo, duplicata)
409idempotency_conflictIdempotency-Key reutilizado com um corpo diferente
409stale_write · import_already_runninga história mudou desde o seu expected_updated_at · uma importação já está em andamento
412precondition_failedIf-Match não corresponde ao ETag atual do recurso; details traz expected e current
413request_too_largeo corpo excede o limite de tamanho da rota
422invalid_transitionmovimento de estado ilegal; details carrega { from, to, allowed }
429rate_limitedrequisições demais deste IP em uma rota com limite de taxa; cabeçalho Retry-After
500internal_errorfalha do servidor — mensagem genérica; seguro para tentar novamente
503not_configuredo 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"] } }

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