ข้ามไปยังเนื้อหา

คู่มือ API

API ของ East Agile Tracker ออกแบบมาสำหรับเอเจนต์พอ ๆ กับมนุษย์ ทุกอย่างที่คุณทำได้ใน UI คุณทำได้ผ่าน API — และมีบางอย่างที่ UI ไม่ได้เปิดเผยอยู่ที่นี่ด้วย

คู่มือนี้พาคุณจากศูนย์ไปสู่ “การเขียนสคริปต์ backlog ของคุณ” ในเวลาไม่ถึงสิบนาที สำหรับเอกสารอ้างอิง endpoint แบบเต็ม ดู ข้อกำหนด API

คุณยืนยันตัวตนด้วยคีย์ใน header X-TrackerToken มีคีย์สองชนิดที่คุณสร้างเอง และชนิดที่สามที่ไคลเอนต์ MCP ขอมาให้คุณ:

  • คีย์ผู้ใช้ (User keys) (ea_user_…) — ทำหน้าที่เป็น คุณ สร้างมันใน Account Settings → API Keys ใช้สำหรับสคริปต์ส่วนตัว เครื่องมือ CLI การผสานรวม
  • คีย์เอเจนต์ (Agent keys) (ea_agent_…) — ทำหน้าที่เป็น เอเจนต์ที่มีชื่อในหนึ่งโปรเจกต์ สร้างมันใน Project Settings → Agents ใช้สำหรับเอเจนต์ AI — Claude Code, Codex หรือของคุณเอง — ที่ควรมีส่วนร่วมในโปรเจกต์ในฐานะเพื่อนร่วมทีมที่มีชื่อ
  • โทเคน MCP (MCP tokens) (ea_mcp_…) — โทเคนการเข้าถึงแบบ OAuth 2.1 ที่ออกให้ไคลเอนต์ MCP (Claude, IDE) หลังจากคุณอนุมัติมันบนหน้าให้ความยินยอม พวกมันทำหน้าที่เป็นคุณ และคุณเพิกถอนมันได้ใน Account Settings → Connected apps

กล่องโต้ตอบที่แสดงครั้งเดียวหลังสร้างคีย์ API ส่วนตัวในการตั้งค่าบัญชี โดยปิดบังคีย์ไว้ในภาพนี้

ฟอร์มสร้างคีย์ในแท็บ Agent ที่กรอกชื่อและเลือกบทบาท member ใต้คำแนะนำการตั้งค่า

ความแตกต่างระหว่างสองชนิดที่คุณสร้างเอง:

คีย์ผู้ใช้คีย์เอเจนต์
ขอบเขตทุกโปรเจกต์ของคุณหนึ่งโปรเจกต์เฉพาะ
ตัวตนในบันทึกการตรวจสอบชื่อของคุณชื่อของเอเจนต์
บทบาทบทบาทของคุณในแต่ละโปรเจกต์กำหนดตอนสร้างคีย์ (viewer, member หรือ manager — ไม่สูงกว่าบทบาทของสมาชิกผู้สร้างคีย์)
การเพิกถอนเพิกถอนคีย์ คุณยังเข้าถึงได้ผ่านคีย์/เซสชันอื่นเพิกถอนหรือหมุนคีย์ เอเจนต์เสียสิทธิ์เข้าถึงทันที
เหมาะที่สุดสำหรับการทำงานอัตโนมัติส่วนตัว สคริปต์เอเจนต์ AI ที่ควรแยกแยะจากคุณได้ในประวัติ

Authorization: Bearer … ก็ใช้ได้หากคุณชอบสไตล์ header นั้น

ดึงโปรเจกต์ของคุณ:

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" หรือ "13" บนมาตรวัดแบบ Fibonacci — เพราะมันต้องตรงกับจุดใดจุดหนึ่งบนมาตรวัดของโปรเจกต์ ตัวเลข JSON จะถูกปฏิเสธ

endpoint การเปลี่ยนสถานะ (transition) ตรวจสอบการย้ายที่ร้องขอและคืนสถานะถัดไปที่อนุญาตเมื่อเกิดข้อผิดพลาด:

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 เป็นสถานะปลายทางสำหรับ endpoint การเปลี่ยนสถานะ หากต้องการนำ story ที่ถูกปฏิเสธกลับมาทำงานต่อ ให้ POST …/stories/{sid}/restart ส่วน POST …/stories/{sid}/reject คือรูปแบบคำกริยาของการปฏิเสธ story ที่ delivered แล้ว

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 — หากเป็นคีย์เอเจนต์ ผู้เขียนความคิดเห็นคือเอเจนต์

ทุก endpoint การเขียนรับ header Idempotency-Key ลองใหม่ด้วยคีย์เดียวกันและ body เดียวกัน จะได้การตอบกลับเดิม ลองใหม่ด้วยคีย์เดียวกันแต่ body ต่างกัน จะได้ 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" }'

นี่สำคัญมากสำหรับเอเจนต์ในลูปลองใหม่ — แครชกลางการเขียน ลองใหม่ด้วยคีย์เดียวกัน ไม่มี story ซ้ำ

ย้ายหลาย story พร้อมกัน แต่ละ story ถูกตัดสินอย่างอิสระ การย้ายที่ไม่ถูกต้องหนึ่งครั้งไม่ทำให้อันอื่นล้มเหลว

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

สำหรับเอเจนต์ที่ต้องการตอบสนองต่อสิ่งที่มนุษย์ทำ ให้ 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"

การตอบกลับเป็นสตรีมเหตุการณ์ที่แบ่งหน้าด้วย cursor พร้อมผู้กระทำ ทรัพยากร และการเปลี่ยนแปลง แต่ละเหตุการณ์มี ID ส่ง ID สุดท้ายที่คุณเห็นเป็น since เพื่อกลับมาทำต่อจากที่ค้างไว้ ไม่มี webhook ไม่มีการขูดข้อมูล ไม่มีเหตุการณ์ที่พลาด สตรีมนี้ต้องใช้บทบาท member — viewer จะได้ 403

GET /projects/{id}/search?q=<query> รันการค้นหาแบบเต็มข้อความผสมกับแบบมีโครงสร้าง ที่ทรงพลังบน story ของโปรเจกต์ ภาษาคิวรีถอดแบบมาจาก qualifier ของการค้นหา issue บน GitHub — ไวยากรณ์ที่คุณ (หรือเอเจนต์ 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 โดย story ถูกจัดอันดับตามความเกี่ยวข้อง:

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

total คือจำนวนผลลัพธ์ที่ตรงทั้งหมด ไม่ใช่ขนาดของหน้า แบ่งหน้าด้วย limit (ค่าเริ่มต้น 50 สูงสุด 1000) และ offset จัดลำดับด้วย sort=relevance (ค่าเริ่มต้น), created, created_asc, updated หรือ state

  • ข้อความอิสระ จับคู่กับชื่อเรื่อง เลขอ้างอิง และคำอธิบายของ story (เต็มข้อความ ตัดรากศัพท์และจัดอันดับ) ใส่วลีที่ต้องการให้ตรงเป๊ะไว้ใน "เครื่องหมายคำพูด"
  • Qualifier อยู่ในรูป field:value คั่นตัวเลือกด้วยจุลภาค (OR ภายในฟิลด์ เดียวกัน): type:bug,chore คั่น qualifier ด้วยช่องว่าง (AND ระหว่างกัน)
  • ปฏิเสธ term หรือ qualifier ใดก็ได้ด้วย - นำหน้า: -label:wontfix
  • ช่วง สำหรับวันที่และพอยต์: รวมปลายทั้งสองด้วย a..b หรือปลายเปิดด้วย >x / <x
Qualifierตัวอย่างจับคู่กับ
type:type:bug,choreประเภทของ story
state:state:started,finishedสถานะในเวิร์กโฟลว์
label:label:"my label"ป้ายกำกับ
epic:epic:"Checkout"story ที่อยู่ใน epic
priority:priority:p1ลำดับความสำคัญ
points:points:3 · points:1..5 · points:>3ค่าหรือช่วงของการประเมิน
iteration:iteration:42id ของรอบงาน
created: updated: started: completed: release:created:2026-05-01..2026-06-01 · updated:>2026-06-01วันที่หรือช่วงวันที่ (ละเอียดระดับวัน) โดย release: คือวันที่ปล่อยของ story
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:me คือ owner:@me ส่วน qualifier scheduled: แบบเก่าถูกเลิกใช้แล้วและถูกเพิกเฉยอย่างเงียบ ๆ ให้ใช้ release: แทน

การใช้จุลภาคแบบ OR (type:bug,chore) ใช้ได้กับ qualifier แบบแง่มุม ส่วน qualifier ที่เป็นบุคคล (owner: requester: follower: reviewer: commenter: mention:) รับได้ค่าเดียว

payment crash เต็มข้อความ "payment" และ "crash"
"exact phrase" วลีหนึ่งวลี
type:bug,chore state:started bug หรือ chore ที่เริ่มแล้ว
owner:@me -label:wontfix ของฉัน ยกเว้นป้ายกำกับ wontfix
points:3..8 created:2026-05-01..2026-06-01 ประเมินไว้ 3-8 สร้างในเดือนพฤษภาคม
follower:tomas has:blocker tomas ติดตามอยู่ และมันถูกขัดขวาง
is:backlog updated:>2026-06-01 รายการใน backlog ที่ถูกแตะตั้งแต่ 1 มิ.ย.

คิวรีสตริงเดียวกันนี้ขับทั้งช่องค้นหาบนบอร์ด (ซึ่งเปิดคอลัมน์ผลลัพธ์แบบสด) และ API นี้ — ไวยากรณ์เดียวสำหรับทั้งมนุษย์และเอเจนต์ การค้นหาเนื้อหาของความคิดเห็น task และ ตัวขัดขวางอยู่ในแผนงาน วันนี้ข้อความอิสระครอบคลุมชื่อเรื่อง เลขอ้างอิง และคำอธิบาย ของ story เองเท่านั้น

ข้อกำหนด 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 การค้นหาข้อมูลอ้างอิง (/story_types, /story_states, /effort_scales, /priority_scales) ก็ไม่ต้องยืนยันตัวตนเช่นกัน เมื่อรวมกันแล้ว พวกมันให้เอเจนต์ตอบ “ฉันทำอะไรได้บ้างที่นี่?” โดยไม่ต้องเจอ 403 จากการลองผิดลองถูก

openapi.json ที่ให้บริการมีสคีมาของ request body สำหรับ endpoint การเขียนมาด้วย รวมถึง 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"

แหล่งที่มาแบบไฟล์ที่รองรับ: pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat (รูปแบบส่งออกของ East Agile Tracker เอง — รูปแบบที่วนกลับได้) endpoint แบบ multipart ทำงานแบบซิงโครนัสและตอบกลับพร้อมจำนวนผลลัพธ์

GitHub นำเข้าจาก API แทนไฟล์ ผ่าน endpoint แบบ JSON — ไม่มี file มีเพียงพิกัดของ 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 ทำงานแบบอะซิงโครนัส: มันตอบกลับ 202 พร้อม { "import_id", "status" } แล้วคุณ poll GET /projects/{id}/imports/{import_id} จนกว่างานจะถึง done หรือ failed การนำเข้ารันได้ครั้งละหนึ่งงานต่อโปรเจกต์ — การเรียกครั้งที่สองขณะที่มีงานหนึ่งกำลังรันอยู่จะได้ 409 import_already_running ลูปทั้งหมด พร้อมฟิลด์ความคืบหน้าของงาน อยู่ใน สร้างโปรเจกต์จากรีโพ GitHub

token ไม่บังคับในคำขอ แต่การดึงข้อมูลเองยืนยันตัวตนเสมอ — มันวิ่งบน GraphQL API ของ GitHub ซึ่งไม่มีชั้นแบบไม่ระบุตัวตน ละ token ไว้ เซิร์ฟเวอร์จะแทนที่ด้วย token ของแพลตฟอร์ม: เฉพาะรีโพสาธารณะ ใช้ร่วมกันโดยผู้เรียกทุกราย และถูกปฏิเสธด้วย import_github_shared_quota_low เมื่องบประมาณ GraphQL ของมันลดต่ำกว่า 500 พอยต์ รีโพส่วนตัว หรือดีพลอยเมนต์ที่ไม่ได้ตั้งค่า token ของแพลตฟอร์มไว้ (import_github_no_token) ต้องใช้ token ของคุณเอง ไม่ว่าจะใช้ token ใด มันถูกใช้เฉพาะกับการเรียก GitHub ต้นทางเท่านั้น และจะไม่ถูกเก็บหรือส่งกลับมา รายละเอียดครบถ้วน รวมถึงเพดาน REST แบบไม่ยืนยันตัวตนที่ 60 คำขอของ GitHub อยู่ใน สร้างโปรเจกต์จากรีโพ GitHub

ตัวอย่างแบบ dry-run เพิ่ม "dry_run": true (JSON) หรือ -F "dry_run=true" (multipart) กับแหล่งใดก็ได้ การนำเข้าจะแยกวิเคราะห์ แก้ปัญหาการอ้างอิง และตัดข้อมูลซ้ำเหมือนการรันจริงทุกประการ คืนจำนวนผลลัพธ์เดียวกัน (imported, skipped, errors, unmatched) จากนั้นย้อนกลับทุกอย่าง — ไม่มีอะไรถูกเขียน บน endpoint แบบ JSON จำนวนเหล่านี้จะมากับงานที่ถูก poll ไม่ว่าจะเป็น dry run หรือไม่

ข้อจำกัด body ของการอัปโหลดถูกจำกัดที่ 10 MiB และการนำเข้าครั้งเดียวที่ 5,000 story เกินอย่างใดอย่างหนึ่งจะได้ 400 โดยไม่เขียนอะไร การนำเข้าไฟล์ซ้ำนั้นปลอดภัย — แถวที่ถูกนำเข้าไปแล้ว (จับคู่ด้วย source id) จะถูกข้าม ไม่ถูกสร้างซ้ำ

บทบาทใดในโปรเจกต์ก็แสดงรายการรูปแบบได้ ส่วนการดาวน์โหลดสงวนไว้ให้เจ้าของ:

Terminal window
# The registered export formats: { id, name, content_type, drops, includes_archived }
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/export/formats \
-H "X-TrackerToken: $TRACKER_TOKEN"
# Download one format (eat is the full-fidelity round-trip CSV)
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/export/eat \
-H "X-TrackerToken: $TRACKER_TOKEN" -o project-export.csv

id ของรูปแบบสำหรับแลกเปลี่ยน: eat, jira, pivotal, shortcut, trello, asana, gitlab, linear, plane, plane_json บวกกับรูปแบบเอกสาร pdf และ docx ไฟล์แนบทุกอันดาวน์โหลดได้เป็น zip เดียวจาก GET /projects/{id}/export/attachments

ข้อผิดพลาดทั้งหมดเป็น JSON ที่อย่างน้อยมี:

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

การตอบกลับข้อผิดพลาดหลายแบบยังรวมออบเจกต์ details ด้วย — details.fields (อาร์เรย์ ของชื่อฟิลด์ที่ผิด) บน validation_failed และ details.allowed (คู่กับ from/to) บน 422 invalid_transition ใช้พวกมัน 429 rate_limited มาพร้อม header Retry-After ในซอง JSON เดียวกัน

endpoint แบบรายการรับ limit และ cursor cursor เป็นแบบทึบ ส่ง next_cursor จากการตอบกลับก่อนหน้า เพดานของ limit ต่างกันไปตาม endpoint — 200 สำหรับ story ความคิดเห็น และโปรเจกต์ 500 สำหรับ events และ 1000 สำหรับการค้นหาและบันทึกการตรวจสอบ รายการแบบธรรมดา (ไม่ใช้ cursor) ที่ต้องตัดการตอบกลับจะแจ้งไว้ใน header: X-Tracker-Pagination-Truncated, -Limit, -Offset และ -Next-Offset ซึ่งคุณส่งกลับเป็น offset= สำหรับหน้าถัดไป ไม่มี header จำนวนรวม