Bỏ qua để đến nội dung

Hướng dẫn API

API của East Agile Tracker được thiết kế cho agent ngang bằng với cho con người. Mọi thứ bạn có thể làm trong giao diện, bạn đều có thể làm qua API — và một vài thứ mà giao diện không phơi bày cũng có ở đó.

Hướng dẫn này đưa bạn từ con số không đến “viết script cho backlog của bạn” trong chưa đầy mười phút. Để có tham chiếu endpoint đầy đủ, xem Đặc tả API.

Bạn xác thực bằng một key trong header X-TrackerToken. Có hai loại key bạn tự phát hành, và một loại thứ ba mà một client MCP lấy thay cho bạn:

  • User key (ea_user_…) — Hành động với tư cách bạn. Tạo chúng trong Account Settings → API Keys. Dùng những key này cho các script cá nhân, công cụ CLI, tích hợp.
  • Agent key (ea_agent_…) — Hành động với tư cách một agent có tên trong một dự án. Tạo chúng trong Project Settings → Agents. Dùng những key này cho các AI agent — Claude Code, Codex, của riêng bạn — vốn nên tham gia vào dự án như những đồng đội có tên.
  • MCP token (ea_mcp_…) — Access token OAuth 2.1 được cấp cho một client MCP (Claude, một IDE) sau khi bạn phê duyệt nó trên trang đồng ý. Chúng hành động với tư cách bạn, và bạn có thể thu hồi chúng dưới Account Settings → Connected apps.

Hộp thoại chỉ hiện một lần sau khi tạo khóa API cá nhân trong Cài đặt tài khoản, khóa được che trong ảnh chụp này

Biểu mẫu tạo khóa trong tab Agent với tên và vai trò member đã chọn, bên dưới hướng dẫn thiết lập

Sự khác biệt giữa hai loại bạn tự phát hành:

User keyAgent key
Phạm viTất cả các dự án của bạnMột dự án cụ thể
Danh tính trong audit logTên của bạnTên của agent
Vai tròVai trò của bạn trong mỗi dự ánĐược đặt khi tạo key (viewer, member, hoặc manager — không bao giờ cao hơn vai trò của chính thành viên phát hành)
Thu hồiThu hồi một key; bạn vẫn giữ quyền truy cập qua các key/phiên khácThu hồi hoặc xoay vòng một key; agent mất quyền truy cập ngay lập tức
Phù hợp nhất choTự động hóa cá nhân, scriptCác AI agent cần được phân biệt với bạn trong lịch sử

Authorization: Bearer … cũng hoạt động nếu bạn thích kiểu header đó hơn.

Lấy các dự án của bạn:

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

Hoặc với một agent key, liệt kê dự án mà nó được giới hạn phạm vi vào:

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

API là JSON, kiểu REST, được phiên bản hóa tại /api/v1/. Cùng cấu trúc cho con người và agent.

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
}'

Phản hồi bao gồm project_id và bất kỳ giá trị mặc định nào mà máy chủ đã áp dụng (thang ước lượng, done state, v.v.).

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"]
}'

estimatenhãn của giá trị trên thang đo, dưới dạng chuỗi — "3", hoặc "13" trên thang Fibonacci — vì nó phải khớp với một điểm trên thang đo của dự án. Một số JSON sẽ bị từ chối.

Endpoint chuyển đổi xác thực bước di chuyển được yêu cầu và trả về các trạng thái tiếp theo được phép khi xảy ra lỗi:

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" }'

Trường là to (không phải to_state). Nếu bước di chuyển không hợp lệ — chẳng hạn bạn cố nhảy từ unstarted thẳng đến accepted — phản hồi là 422 invalid_transition với chi tiết lỗi có cấu trúc:

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

Đây là một trong những điều nhỏ khiến API thân thiện với agent: một agent có thể đọc details.allowed và chọn bước di chuyển tiếp theo đúng đắn mà không cần phải trích xuất từ văn xuôi.

rejected là trạng thái cuối đối với endpoint chuyển đổi. Để đưa một story bị từ chối trở lại làm việc, dùng POST …/stories/{sid}/restart; POST …/stories/{sid}/reject là dạng động từ để từ chối một story đã được giao.

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

Bình luận được quy cho bất kỳ ai sở hữu API key — nếu là một agent key, tác giả của bình luận là agent.

Mọi endpoint ghi đều chấp nhận một header Idempotency-Key. Thử lại cùng một key với cùng một body, nhận lại cùng một phản hồi. Thử lại cùng một key với một body khác, nhận một 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" }'

Điều này rất quan trọng đối với các agent trong vòng lặp thử lại — gặp sự cố giữa chừng một thao tác ghi, thử lại với cùng key, không có story trùng lặp.

Di chuyển nhiều story cùng lúc. Mỗi story được đánh giá độc lập; một bước di chuyển không hợp lệ không làm hỏng các bước còn lại.

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"
}'

Đối với các agent muốn phản ứng với những gì con người làm, hãy poll endpoint 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"

Phản hồi là một luồng sự kiện được phân trang theo cursor với tác nhân, tài nguyên, và sự thay đổi. Mỗi sự kiện có một ID; truyền ID cuối cùng bạn đã thấy làm since để tiếp tục từ nơi bạn dừng lại. Không webhook, không trích xuất, không bỏ lỡ sự kiện. Luồng này cần vai trò member — một viewer nhận 403.

GET /projects/{id}/search?q=<query> chạy một phép tìm kiếm toàn văn + có cấu trúc mạnh mẽ trên các story của dự án. Ngôn ngữ truy vấn được mô phỏng theo các qualifier tìm kiếm issue của GitHub — nên cú pháp mà bạn (hoặc một AI agent) đã biết từ GitHub phần lớn đều dùng được ở đây.

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'

Phản hồi là một phong bì JSON, các story được xếp hạng theo mức độ liên quan:

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

total là tổng số kết quả khớp, không phải kích thước trang. Phân trang bằng limit (mặc định 50, tối đa 1000) và offset; sắp xếp bằng sort=relevance (mặc định), created, created_asc, updated, hoặc state.

  • Văn bản tự do khớp với tiêu đề, mã tham chiếu, và mô tả của story (toàn văn, có tách gốc từ và xếp hạng). Bọc một cụm từ chính xác trong "dấu ngoặc kép".
  • Qualifier có dạng field:value. Phân tách các lựa chọn thay thế bằng dấu phẩy (OR trong một trường): type:bug,chore. Phân tách các qualifier bằng khoảng trắng (AND giữa chúng).
  • Phủ định bất kỳ thuật ngữ hay qualifier nào bằng dấu - ở đầu: -label:wontfix.
  • Khoảng cho ngày và điểm: bao gồm hai đầu a..b, hoặc mở một đầu >x / <x.
QualifierVí dụKhớp với
type:type:bug,chore(các) loại story
state:state:started,finished(các) trạng thái quy trình
label:label:"my label"một nhãn
epic:epic:"Checkout"các story trong một epic
priority:priority:p1độ ưu tiên
points:points:3 · points:1..5 · points:>3giá trị hoặc khoảng ước lượng
iteration:iteration:42id của iteration
created: updated: started: completed: release:created:2026-05-01..2026-06-01 · updated:>2026-06-01một ngày hoặc một khoảng (độ chi tiết theo ngày); release: là ngày phát hành của story
owner: requester: follower: reviewer: commenter: mention:owner:claire · owner:@memột người theo tên hoặc email — thành viên agent, kể cả mention:; @me là bạn
has:blockerhas:blockercó một blocker đang mở
is:is:unestimated · is:icebox · is:backlog · is:blockedmột cờ

mywork: là bí danh của owner:mywork:meowner:@me. Qualifier scheduled: cũ đã bị loại bỏ và bị bỏ qua âm thầm; hãy dùng release:.

OR bằng dấu phẩy (type:bug,chore) áp dụng cho các qualifier facet; các qualifier về người (owner: requester: follower: reviewer: commenter: mention:) chỉ nhận một giá trị.

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

Cùng một chuỗi truy vấn điều khiển ô tìm kiếm của board (nơi mở một cột kết quả trực tiếp) và API này — một ngữ pháp chung cho cả con người lẫn agent. Tìm kiếm trong nội dung bình luận, task, và blocker đang nằm trong lộ trình; hiện tại văn bản tự do bao gồm tiêu đề, mã tham chiếu, và mô tả của chính story.

Đặc tả OpenAPI 3 trực tiếp nằm tại:

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

Swagger UI nằm tại:

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

/openapi.json/docs không cần xác thực — một agent có thể đọc hợp đồng trước khi nó có key. Khi đã giữ một key, /api/v1/meta (vốn yêu cầu một key hợp lệ) trả về danh tính của nó và đồ thị chuyển đổi theo từng loại story; các lượt tra cứu dữ liệu tham chiếu (/story_types, /story_states, /effort_scales, /priority_scales) cũng không cần xác thực. Cùng nhau, chúng cho phép agent trả lời “tôi có thể làm gì ở đây?” mà không cần thử-và-sai với các lỗi 403.

File openapi.json được phục vụ mang theo schema request body cho các endpoint ghi, bao gồm maxLength của từng trường, để client có thể kiểm tra hợp lệ trước khi gửi. Đặc tả tóm tắt cùng các cấu trúc đó.

Đối với tự động hóa tương tác — điều khiển một phiên trình duyệt đã đăng nhập từ một script, hoặc điều khiển từ xa giao diện cho các bài hướng dẫn — có một kênh WebSocket:

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

token là JWT của phiên trình duyệt, không phải một API key — một key ea_user_* hoặc ea_agent_* bị từ chối trước khi nâng cấp kết nối. Hầu hết người dùng không bao giờ cần đến nó; nó ở đó cho các trường hợp mà REST chưa đủ.

Nếu bạn đang viết script cho một cuộc di chuyển hàng loạt:

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"

Các nguồn từ tệp được hỗ trợ: pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat (bản xuất của chính East Agile Tracker — định dạng khứ hồi). Endpoint multipart chạy đồng bộ và trả lời bằng các bộ đếm kết quả.

GitHub nhập từ API thay vì từ một tệp, qua endpoint JSON — không có file, chỉ cần tọa độ của repository:

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
}'

Endpoint JSON là bất đồng bộ: nó trả lời 202 với { "import_id", "status" } và bạn poll GET /projects/{id}/imports/{import_id} cho đến khi job đạt done hoặc failed. Mỗi dự án chỉ chạy một lần nhập tại một thời điểm — một lời gọi thứ hai trong khi một lần nhập đang chạy sẽ nhận 409 import_already_running. Toàn bộ vòng lặp, cùng các trường tiến độ của job, nằm ở Tạo dự án từ một repo GitHub.

token là tùy chọn trên đường truyền, nhưng bản thân việc lấy dữ liệu luôn xác thực — nó chạy trên API GraphQL của GitHub, nơi không có bậc ẩn danh. Bỏ token đi và máy chủ sẽ thay bằng token nền tảng: chỉ repo công khai, dùng chung cho mọi lời gọi, và bị từ chối với import_github_shared_quota_low khi ngân sách GraphQL của nó rơi xuống dưới 500 điểm. Repo riêng tư, hoặc một bản triển khai không cấu hình token nền tảng (import_github_no_token), đòi hỏi token của bạn. Dù token nào chạy đi nữa, nó chỉ được dùng cho các lời gọi lên GitHub và không bao giờ được lưu trữ hay trả lại. Chi tiết đầy đủ, gồm cả trần REST 60 yêu cầu khi không xác thực của GitHub, nằm ở Tạo dự án từ một repo GitHub.

Xem trước dry-run. Thêm "dry_run": true (JSON) hoặc -F "dry_run=true" (multipart) cho bất kỳ nguồn nào. Việc nhập sẽ phân tích, đối chiếu, và khử trùng lặp y hệt một lần chạy thật, trả về cùng các bộ đếm kết quả (imported, skipped, errors, unmatched), rồi hoàn tác tất cả — không có gì được ghi. Trên endpoint JSON, các bộ đếm đến trên job được poll, dù là dry run hay không.

Giới hạn. Thân của bản tải lên bị giới hạn ở 10 MiB, và một lần nhập ở 5.000 story; vượt quá một trong hai sẽ là 400 mà không ghi gì. Nhập lại một tệp là an toàn — các hàng đã được nhập (đối chiếu theo id nguồn) sẽ bị bỏ qua, không nhân đôi.

Mọi vai trò dự án đều có thể liệt kê các định dạng; tải xuống một định dạng chỉ dành cho owner:

Terminal window
# Các định dạng xuất đã đăng ký: { id, name, content_type, drops, includes_archived }
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/export/formats \
-H "X-TrackerToken: $TRACKER_TOKEN"
# Tải xuống một định dạng (eat là CSV khứ hồi đầy đủ độ trung thực)
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/export/eat \
-H "X-TrackerToken: $TRACKER_TOKEN" -o project-export.csv

Các id định dạng trao đổi: eat, jira, pivotal, shortcut, trello, asana, gitlab, linear, plane, plane_json, cùng các định dạng tài liệu pdfdocx. Mọi tệp đính kèm có thể tải xuống dưới dạng một zip từ GET /projects/{id}/export/attachments.

Mọi lỗi đều là JSON với tối thiểu:

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

Nhiều phản hồi lỗi cũng bao gồm một đối tượng detailsdetails.fields (một mảng tên các trường vi phạm) trên validation_failed, và details.allowed (cùng với from/to) trên 422 invalid_transition. Hãy dùng chúng. Một 429 rate_limited mang header Retry-After trong cùng phong bì JSON đó.

Các endpoint danh sách chấp nhận limitcursor. Cursor là không trong suốt (opaque); truyền next_cursor từ phản hồi trước. Trần của limit tùy theo endpoint — 200 cho story, bình luận, và dự án, 500 cho sự kiện, 1000 cho tìm kiếm và audit log. Một danh sách thường (không dùng cursor) phải cắt bớt phản hồi sẽ báo điều đó qua các header: X-Tracker-Pagination-Truncated, -Limit, -Offset, và -Next-Offset, giá trị cuối bạn truyền lại làm offset= cho trang tiếp theo. Không có header tổng số đếm.