跳转到内容

API 指南

East Agile Tracker API 既为人类、也同等地为智能体而设计。凡是你能在 UI 中做的事,你都能通过 API 完成——而且还有一些 UI 不暴露的功能也在这里。

本指南会在十分钟内带你从零做到“脚本化你的待办列表”。完整的端点参考,请参阅 API 规范

你通过 X-TrackerToken 请求头中的密钥进行认证。有两种密钥由你自己铸造,第三种则由 MCP 客户端替你获取:

  • 用户密钥ea_user_…)——以你本人的身份行事。在 Account Settings → API Keys 中创建。用于个人脚本、CLI 工具、集成。
  • 智能体密钥ea_agent_…)——以某个项目中的具名智能体的身份行事。在 Project Settings → Agents 中创建。用于那些应当作为具名队友参与项目的 AI 智能体——Claude Code、Codex、你自己的。
  • MCP 令牌ea_mcp_…)——你在同意页面批准某个 MCP 客户端(Claude、某个 IDE)之后签发给它的 OAuth 2.1 访问令牌。它们以你的身份行事,你可以在 Account Settings → Connected apps 下撤销。

在账户设置中创建个人 API 密钥后仅显示一次的对话框,此截图中密钥已遮盖

设置说明下方 Agent 标签页中的创建密钥表单,已填写名称并选择 member 角色

你自己铸造的两种之间的区别如下:

User keyAgent key
Scope你所有的项目一个特定的项目
Identity in audit log你的名字该智能体的名字
Role你在每个项目中的角色创建密钥时设定(viewermembermanager——绝不高于铸造者自己的角色)
Revocation撤销一个密钥;你仍可通过其他密钥/会话保有访问权撤销或轮换一个密钥;该智能体立刻失去访问权
Best for个人自动化、脚本应当在历史中与你相区分的 AI 智能体

如果你更喜欢那种请求头风格,Authorization: Bearer … 也行得通。

获取你的项目:

Terminal window
curl https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: $TRACKER_TOKEN"

或者,对于一个智能体密钥,列出它所限定的那个项目:

Terminal window
curl https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: ea_agent_xxxxx"

API 是 JSON、REST 风格、在 /api/v1/ 处带版本。对人类和智能体是相同的数据形态。

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Onboarding redesign",
"description": "Q3 redesign of new-user onboarding",
"iteration_length_weeks": 1
}'

响应包含 project_id 以及服务器所应用的任何默认值(估算尺度、完成状态等)。

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Add OAuth login for Google",
"description": "## Acceptance\n- Google button on /login\n- Redirect back to original URL",
"story_type": "feature",
"estimate": "3",
"labels": ["auth"]
}'

estimate 是尺度值的标签,以字符串形式给出——"3",或 Fibonacci 尺度上的 "13"——因为它必须与项目尺度上的某个点对应。JSON 数字会被拒绝。

流转端点会校验所请求的移动,并在出错时返回所允许的下一批状态:

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/transitions \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "to": "started" }'

字段是 to(不是 to_state)。如果这个移动非法——比如你试图从 unstarted 直接跳到 accepted——响应会是 422 invalid_transition,并附带结构化的错误详情:

{
"code": "invalid_transition",
"error": "Cannot move story from `unstarted` to `accepted`",
"details": { "from": "unstarted", "to": "accepted", "allowed": ["started"] }
}

这是让 API 对智能体友好的小细节之一:智能体可以读取 details.allowed,并选出正确的下一步移动,而无需去抓取散文。

对流转端点而言,rejected 是终态。要让一个被拒绝的故事重新开工,请 POST …/stories/{sid}/restartPOST …/stories/{sid}/reject 则是拒绝一个已交付故事的动词形式。

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/comments \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "text": "Investigation done. Picking this up." }'

评论会被归因于持有该 API 密钥的人——如果是智能体密钥,评论的作者就是该智能体。

每个写入端点都接受一个 Idempotency-Key 请求头。用同一个密钥配同一个请求体重试,会拿回同一个响应。用同一个密钥配不同的请求体重试,会得到 409 idempotency_conflict

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "name": "Refactor auth middleware", "story_type": "chore" }'

这对处于重试循环中的智能体至关重要——写入途中崩溃,用同一个密钥重试,不会产生重复的故事。

一次移动许多故事。每个故事都被独立裁决;一个非法的移动不会让其余的失败。

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/bulk_transition \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"story_ids": [101, 102, 103],
"to": "delivered"
}'

对于想要对人类所做之事作出反应的智能体,轮询 events 端点:

Terminal window
curl "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/events?since=$LAST_CURSOR&types=story.created,story.transitioned,comment.added" \
-H "X-TrackerToken: $TRACKER_TOKEN"

响应是一个以游标分页的事件流,包含操作者、资源和变更。每个事件都有一个 ID;把你看到的最后一个 ID 作为 since 传入,即可从你上次停下的地方继续。没有 webhook,没有抓取,没有遗漏的事件。事件流需要 member 角色——viewer 会得到 403

GET /projects/{id}/search?q=<query> 对项目的故事运行一次强大的全文 + 结构化搜索。查询语言以 GitHub 的 issue 搜索限定符为蓝本——所以你(或 AI 智能体)已经从 GitHub 熟悉的语法大多可以直接沿用。

Terminal window
curl -G "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/search" \
-H "X-TrackerToken: $TRACKER_TOKEN" \
--data-urlencode 'q=payment crash type:bug,chore owner:@me created:>2026-05-01'

响应是一个 JSON 信封,故事按相关度排序:

{ "results": [ /* canonical story objects */ ], "total": 42, "limit": 50, "offset": 0 }

total 是完整的匹配数,而非页大小。用 limit(默认 50,最大 1000)和 offset 分页;用 sort=relevance(默认)、createdcreated_ascupdatedstate 排序。

  • 自由文本匹配故事的标题、引用和描述(全文、经词干化并排序)。把精确短语用 "引号" 括起来。
  • 限定符的形式是 field:value。用逗号分隔备选值(同一字段内为 OR):type:bug,chore。用空格分隔多个限定符(它们之间为 AND)。
  • 在任何词项或限定符前加 - 即可取反-label:wontfix
  • 日期和点数支持范围:闭区间 a..b,或开区间 >x / <x
QualifierExampleMatches
type:type:bug,chore故事类型
state:state:started,finished工作流状态
label:label:"my label"某个标签
epic:epic:"Checkout"某个史诗中的故事
priority:priority:p1优先级
points:points:3 · points:1..5 · points:>3估算值或范围
iteration:iteration:42迭代 id
created: updated: started: completed: release:created:2026-05-01..2026-06-01 · updated:>2026-06-01某个日期或范围(精确到天);release: 是故事的发布日期
owner: requester: follower: reviewer: commenter: mention:owner:claire · owner:@me按姓名或邮箱指定的人——成员智能体,mention: 也不例外;@me 指你自己
has:blockerhas:blocker有未解决的阻碍
is:is:unestimated · is:icebox · is:backlog · is:blocked一个标志

mywork:owner: 的别名——mywork:meowner:@me。旧的 scheduled: 限定符已退役并被静默忽略;请改用 release:

逗号 OR(type:bug,chore)适用于 facet 限定符;人员限定符(owner: requester: follower: reviewer: commenter: mention:)只接受单个值。

payment crash full text "payment" AND "crash"
"exact phrase" a phrase
type:bug,chore state:started bugs or chores that are started
owner:@me -label:wontfix mine, excluding the wontfix label
points:3..8 created:2026-05-01..2026-06-01 estimated 3-8, created in May
follower:tomas has:blocker tomas follows it and it's blocked
is:backlog updated:>2026-06-01 backlog items touched since Jun 1

同一个查询字符串既驱动看板的搜索框(它会打开一个实时结果列),也驱动这个 API——人类和智能体共用一套语法。搜索评论、任务和阻碍的内容已列入路线图;目前自由文本只覆盖故事自身的标题、引用和描述。

实时的 OpenAPI 3 规范在:

https://api.eastagiletracker.com/api/v1/openapi.json

Swagger UI 在:

https://api.eastagiletracker.com/api/v1/docs/

/openapi.json/docs 无需认证——智能体在拥有密钥之前就能读到契约。一旦它持有了密钥,/api/v1/meta(它需要一个有效的密钥)会返回它的身份和逐故事类型的流转图;参考数据查询(/story_types/story_states/effort_scales/priority_scales)同样无需认证。它们合在一起,让智能体无需靠反复试错碰 403,就能回答“我在这里能做什么?”。

所提供的 openapi.json 为各写入端点附带了请求体 schema,包括每个字段的 maxLength,因此客户端可以在发送前先行校验。规范对同样的形态做了概述。

对于交互式自动化——从脚本驱动一个已登录的浏览器会话,或者为教程远程控制 UI——有一个 WebSocket 通道:

const ws = new WebSocket('wss://eastagiletracker.com/ws/control?token=SESSION_JWT')
ws.send(JSON.stringify({ action: 'get_state', id: 'req-1' }))

这里的 token 是浏览器会话的 JWT,而不是 API 密钥——ea_user_*ea_agent_* 密钥会在升级之前就被拒绝。大多数用户从不需要它;它是为那些 REST 不够用的情形而准备的。

如果你正在脚本化一次批量迁移:

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/import \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-F "source=pivotal" \
-F "file=@pivotal_export.csv"

支持的文件来源:pivotaljiraasanagitlabshortcuttrellolinearplaneplane_jsoneat(East Agile Tracker 自己的导出格式——往返互通格式)。multipart 端点同步运行,并以结果计数作答。

GitHub 从 API 而非文件导入,通过 JSON 端点——无需 file,只要仓库坐标:

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/import/json \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": "github",
"owner": "octocat",
"repo": "hello-world",
"token": "ghp_…",
"include_pull_requests": false,
"include_milestones": false,
"include_releases": false,
"include_dependencies": false
}'

JSON 端点是异步的:它以 202{ "import_id", "status" } 作答,你轮询 GET /projects/{id}/imports/{import_id},直到作业到达 donefailed。每个项目同一时间只运行一个导入——在一个导入进行中再次调用会得到 409 import_already_running。完整的轮询循环,连同作业的进度字段,见从 GitHub 仓库填充项目

token 在请求上是可选的,但抓取本身始终会认证——它走 GitHub 的 GraphQL API,而该 API 没有匿名层级。省略 token,服务器会替换成它的平台令牌:仅限公开仓库,由所有调用方共享,并在其 GraphQL 额度低于 500 点时以 import_github_shared_quota_low 拒绝。私有仓库,或者未配置平台令牌的部署(import_github_no_token),需要你自己的令牌。无论用的是哪个令牌,它都仅用于向上游 GitHub 发起调用,绝不会被存储或回显。完整细节,包括 GitHub 未认证时 60 次请求的 REST 上限,见从 GitHub 仓库填充项目

**试运行预览。**为任意来源加上 "dry_run": true(JSON)或 -F "dry_run=true"(multipart)。导入会像真实运行一样完整地解析、解析映射并去重,产生相同的结果计数(importedskippederrorsunmatched),然后把一切回滚——什么都不会写入。在 JSON 端点上,无论是否空跑,计数都随被轮询的作业送达。

**限制。**上传体积上限为 10 MiB,单次导入上限为 5,000 个故事;超出任一者都会返回 400 且不写入任何内容。重新导入一个文件是安全的——已导入的行(按来源 id 匹配)会被跳过,而非重复。

任何项目角色都能列出格式;下载则仅限所有者:

Terminal window
# 已注册的导出格式:{ id, name, content_type, drops, includes_archived }
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/export/formats \
-H "X-TrackerToken: $TRACKER_TOKEN"
# 下载某一种格式(eat 是全保真的往返 CSV)
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/export/eat \
-H "X-TrackerToken: $TRACKER_TOKEN" -o project-export.csv

互通格式 id:eatjirapivotalshortcuttrelloasanagitlablinearplaneplane_json,以及文档格式 pdfdocx。每个附件都可从 GET /projects/{id}/export/attachments 以一个 zip 的形式下载。

所有错误都是 JSON,至少包含:

{
"code": "invalid_transition",
"error": "Cannot move story from `unstarted` to `accepted`"
}

许多错误响应还包含一个 details 对象——在 validation_failed 上有 details.fields(一个由出错字段名组成的数组),在 422 invalid_transition 上有 details.allowed(连同 from/to)。请善用它们。429 rate_limited 在同样的 JSON 信封中附带一个 Retry-After 请求头。

列表端点接受 limitcursor。游标是不透明的;把上一个响应中的 next_cursor 传入。limit 的上限按端点而异——故事、评论和项目为 200,事件为 500,搜索和审计日志为 1000。一个不得不截断响应的普通(非游标)列表会通过响应头说明这一点:X-Tracker-Pagination-Truncated-Limit-Offset-Next-Offset,你把最后一个作为 offset= 传回即可获取下一页。没有总数响应头。

  • API 规范——每个端点、每个动词、每种数据形态。
  • 使用说明 → 智能体——UI 这一侧:铸造智能体密钥、为智能体命名、撤销。
  • 简介——API 背后的概念:故事、状态、迭代、速率、智能体。