Referensi endpoint REST lengkap. Untuk tutorial dan contoh, lihat Panduan API.
Segala sesuatu yang dapat dilakukan member proyek di UI web tersedia di sini — SPA mengonsumsi API yang sama ini. Operasi yang memerlukan peran manager ditandai (manager); selebihnya hanya membutuhkan keanggotaan proyek (atau, untuk pembacaan yang ditandai (viewer), tingkat akses apa pun). Tabel-tabel di bawah menyebutkan setiap grup route yang dipasang server; grup yang diringkas dalam satu baris dijelaskan lengkap di openapi.json langsung.
https://eastagiletracker.com/api/v1https://api.eastagiletracker.com/api/v1 menyajikan API yang identik. Semua request dan respons berupa JSON, kecuali beberapa endpoint unggah-file yang menerima multipart.
Dua grup berada satu tingkat di atasnya, di bawah /api alih-alih /api/v1: permukaan autentikasi (/api/auth/*) dan formulir publik (/api/contact, /api/feedback). Ejaan /api/v1/… mereka mengembalikan 404.
Autentikasi
Section titled “Autentikasi”Setiap request terautentikasi mengirim kredensial melalui salah satu dari:
X-TrackerToken: <key>Authorization: Bearer <key>
Kunci pengguna dimulai dengan ea_user_, kunci agen dengan ea_agent_, dan token akses MCP dengan ea_mcp_. Lihat Panduan API → Tiga jenis kredensial.
Endpoint tidak terautentikasi: /openapi.json, /docs, endpoint /api/auth/*, dan lookup data-referensi (/story_types, /story_states, /effort_scales, /priority_scales). /meta bersifat terautentikasi — kunci valid apa pun berfungsi, tetapi tidak dicakup-proyek (kunci agen yang terikat-proyek pun menjangkaunya).
Empat tingkat menggerbangi endpoint yang dicakup-proyek:
| Tingkat | Siapa yang lolos | Operasi tipikal |
|---|---|---|
| public viewer | siapa pun, pada proyek yang visibilitasnya publik | pembacaan papan: story, iterasi, pencarian, aktivitas story dan epic (dengan detail aktor disamarkan) |
| viewer | viewer, member, manager | pembacaan (daftar/dapatkan story, pencarian, metrik, daftar format ekspor) |
| member | member, manager | semua write work-item (story, task, komentar, …), aliran event |
| manager | hanya manager | pengaturan proyek, manajemen keanggotaan, kunci agen, hapus, impor, unduhan ekspor, cadangan, log audit |
Agen memegang peran yang sama dengan anggota — viewer, member, atau manager — dibatasi pada peran anggota yang mencetak kuncinya. Non-member menerima 404 unfound_resource (bukan 403) pada path proyek privat, sehingga ID proyek tidak dapat dienumerasi.
Endpoint yang mendeskripsikan diri
Section titled “Endpoint yang mendeskripsikan diri”| Metode | Path | Deskripsi |
|---|---|---|
| GET | /openapi.json | Spesifikasi OpenAPI 3 langsung, termasuk request body. Tidak terautentikasi. |
| GET | /docs | Swagger UI. Tidak terautentikasi. |
| GET | /meta | Identitas pemanggil (auth.kind/key_id/agent_id/project_id) + graf transisi tipe-story. Terautentikasi (kunci valid apa pun; tidak dicakup-proyek). Panggil ini lebih dulu. |
| GET | /api/health · /api/config | Liveness, dan konfigurasi publik deployment (mode organisasi-tunggal, fitur opsional yang aktif, nama instans). Tidak terautentikasi, di luar /v1. |
Auth (/api/auth/*, di luar /v1)
Section titled “Auth (/api/auth/*, di luar /v1)”Endpoint sesi, tidak terautentikasi kecuali dinyatakan lain. SPA yang menggerakkannya; skrip biasanya memakai kunci API sebagai gantinya.
| Metode | Path | Deskripsi |
|---|---|---|
| POST | /auth/register | Daftarkan akun baru — dijaga reCAPTCHA; akun kemudian melewati tantangan SMS |
| POST | /auth/sms/challenge · /auth/sms/status · /auth/sms/bypass | Kirim / periksa kode SMS pendaftaran (bypass digerbangi operator) |
| GET | /auth/config | Metode masuk mana yang ditawarkan deployment |
| POST | /auth/login | Masuk dengan email + kata sandi; mengembalikan JWT sesi, atau tantangan TOTP |
| POST | /auth/login/totp | Selesaikan proses masuk dengan kode autentikator atau kode pemulihan |
| POST | /auth/passkey/login/start · /auth/passkey/login/finish | Masuk WebAuthn tanpa kata sandi |
| GET | /auth/oauth/github/start · /auth/oauth/github/callback · /auth/oauth/google/start · /auth/oauth/google/callback · POST /auth/oauth/exchange | Masuk OAuth dengan GitHub atau Google |
| POST | /auth/refresh · /auth/refresh/revoke | Rotasi refresh token / cabut |
| POST | /auth/logout | Keluar (mencabut refresh token) |
| POST | /auth/forgot-password · /auth/reset-password | Minta email reset / gunakan token reset |
| POST | /auth/accept-invite/lookup · /auth/accept-invite | Selesaikan token undangan → email / terima undangan proyek (setelah autentikasi) |
Akun / identitas
Section titled “Akun / identitas”Ini bertindak pada pemanggil dan hanya membutuhkan kunci valid (tanpa peran proyek).
| Metode | Path | Deskripsi |
|---|---|---|
| GET | /me | Profil pengguna saat ini |
| PUT | /me | Perbarui profil |
| DELETE | /me | Hapus akun — ditolak selama Anda satu-satunya owner sebuah organisasi atau proyek yang memiliki anggota lain |
| GET | /me/deletion-impact | Apa yang akan dihapus bila akun dihapus dan apa yang menghalanginya |
| PUT | /me/password | Ubah kata sandi |
| PUT | /me/settings | Perbarui pengaturan (tema, preferensi notifikasi) |
| POST | /me/avatar | Unggah avatar (multipart) |
| POST | /me/api-token/regenerate | Rotasi token API Anda — membatalkan sesi/kunci yang ada |
| GET | /me/api_keys · POST /me/api_keys · DELETE /me/api_keys/{id} | Kelola kunci API pengguna (ea_user_) |
| GET | /me/totp · POST /me/totp/setup · /me/totp/verify · /me/totp/disable | Pendaftaran dua faktor (TOTP); verify mengembalikan kode pemulihan satu kali |
| GET | /me/passkeys · POST /me/passkeys/register/start · /me/passkeys/register/finish · DELETE /me/passkeys/{credential_id} | Pendaftaran dan penghapusan passkey |
| GET | /me/oauth_grants · DELETE /me/oauth_grants/{grant_id} | Connected apps — klien MCP dan aplikasi OAuth yang telah Anda otorisasi |
| GET | /me/activity | Aktivitas Anda di semua proyek |
| GET | /me/stories | Story yang Anda miliki, minta, atau ikuti di setiap proyek yang dapat dijangkau token — role=owned|requested|following, state=, cursor= / limit= (maks 200) |
| GET | /me/mentions · POST /me/mentions/{mention_id}/ack | Kotak masuk @-sebutan (unacked=true untuk memfilter) dan pengakuannya — juga dilebur ke feed notifikasi di bawah |
| GET | /me/data-export | Ekspor-mandiri GDPR atas data Anda |
| GET | /me/consent · POST /me/consent | Baca / catat persetujuan ({ consent_type, granted }) |
| GET | /legal/pending · POST /legal/accept | Dokumen clickwrap tertunda / catat penerimaan |
| GET / PUT | /agent/me | Identitas dan profil milik kunci agen itu sendiri, dapat dibaca dan diedit oleh agen (padanan sisi-agen dari /me) |
| POST | /api/contact · /api/feedback · /api/feedback/with-screenshot | Kontak + umpan balik dalam-aplikasi. Di luar /v1; dibatasi laju per IP |
Data referensi (tidak terautentikasi)
Section titled “Data referensi (tidak terautentikasi)”Lookup benih yang digunakan saat membuat/mengestimasi story. ID stabil.
| Metode | Path | Deskripsi |
|---|---|---|
| GET | /story_types | feature, bug, chore, release (+ allow_points) |
| GET | /story_states | unstarted … accepted, rejected |
| GET | /effort_scales | skala estimasi yang tersedia |
| GET | /effort_scales/{scale_id}/values | nilai poin dalam suatu skala |
| GET | /priority_scales · /priority_scales/{scale_id}/values | skala prioritas dan nilainya (priority_id pada story diselesaikan di sini) |
Organisasi
Section titled “Organisasi”Hanya layanan yang di-host — instalasi self-hosted berjalan dalam mode organisasi-tunggal dan tidak memasang endpoint ini (kecuali daftar organisasi). Perannya adalah peran organisasi: owner, admin, member.
| Metode | Path | Deskripsi |
|---|---|---|
| GET / POST | /organizations | Daftar organisasi Anda / buat satu |
| GET / PUT / DELETE | /organizations/{oid} | Baca, ganti nama (nama + slug; owner atau admin), hapus |
| GET / POST | /organizations/{oid}/memberships · PUT / DELETE …/memberships/{member_id} | Anggota dan undangan; undangan membawa plafon peran (tidak pernah di atas peran pemanggil; owner tidak pernah diundang) |
| POST | /organizations/{oid}/memberships/bulk-role · …/memberships/bulk-remove | Ubah peran atau keluarkan hingga 200 anggota sekaligus. Semua atau tidak sama sekali: batch yang akan mengeluarkan owner terakhir atau membuat proyek tanpa pemilik ditolak seluruhnya; dengan reassign_confirmed Anda menjadi pemilik proyek tersebut |
| DELETE | /organizations/{oid}/invitations/{invitation_id} | Cabut undangan tertunda |
| POST | /organizations/{oid}/transfer-ownership | Serahkan peran owner ke anggota lain |
| PUT | /organizations/{oid}/memberships/{member_id}/anonymization | Samarkan nama / email / avatar seorang anggota di seluruh organisasi |
| GET | /organization-invitations/{token} · POST …/{token}/accept | Selesaikan / terima undangan organisasi yang dikirim lewat email |
| POST | /organizations/{oid}/export · GET / POST …/export/jobs · GET …/export/jobs/{job_id} · …/export/jobs/{job_id}/download | Ekspor organisasi khusus-owner: zip berisi dump SQL dan setiap lampiran, dijalankan sebagai job |
Proyek
Section titled “Proyek”| Metode | Path | Deskripsi |
|---|---|---|
| GET | /projects | Daftar proyek Anda (limit ≤ 200) |
| POST | /projects | Buat proyek |
| GET | /projects/{id} | Dapatkan detail proyek (viewer) |
| PUT | /projects/{id} | Perbarui pengaturan proyek (manager) |
| DELETE | /projects/{id} | Hapus proyek (manager) |
| POST | /projects/{id}/pin | Sematkan / lepas sematan proyek di daftar proyek Anda |
| POST | /projects/{id}/transfer-organization | Pindahkan proyek ke organisasi lain (manager) |
| POST | /projects/{id}/slack/test | Kirim pesan uji ke feed Slack proyek (manager) |
| GET / POST | /projects/{id}/showcase_claim_eligibility · /projects/{id}/showcase_claim · /projects/{id}/showcase_seed | Proyek showcase publik: periksa apakah Anda dapat mengklaimnya, klaim, isi datanya |
| GET | /projects/{id}/audit-log | Pembacaan audit log — riwayat proyek plus aktivitas per-story / per-epic lewat surface=; akses bervariasi menurut surface, lihat di bawah |
| GET | /projects/{id}/events | Aliran event dengan paginasi-kursor (member) — lihat Event |
Parameter query audit log: event_type= (satu tipe atau daftar dipisah koma), limit= (≤ 1000), before= (kursor keyset, created_at ISO-8601), surface= (project_history, story_activities, epic_activities), target_id= (id story/epic — wajib saat surface=story_activities atau epic_activities). Akses: log tanpa filter dan surface=project_history adalah (manager); story_activities / epic_activities dapat dibaca anggota proyek mana pun, dan secara anonim pada proyek publik dengan PII aktor disamarkan.
Anggota, agen, dan kunci agen
Section titled “Anggota, agen, dan kunci agen”| Metode | Path | Deskripsi |
|---|---|---|
| GET | /projects/{id}/memberships | Daftar anggota (viewer) |
| POST | /projects/{id}/memberships | Undang anggota lewat email (manager) |
| PUT | /projects/{id}/memberships/{mid} | Perbarui peran (manager) |
| DELETE | /projects/{id}/memberships/{mid} | Hapus anggota (manager) |
| GET | /projects/{id}/addable-members · POST /projects/{id}/members/add-existing | Anggota organisasi yang belum ada di proyek / tambahkan satu tanpa undangan email (manager) |
| POST | /projects/{id}/members/join | Owner atau admin organisasi bergabung ke proyek di organisasinya sebagai manager, atau menaikkan dirinya menjadi manager (aksi Make me owner di daftar proyek) |
| PUT | /projects/{id}/members/{mid}/anonymization | Samarkan nama / email / avatar seorang anggota di proyek ini (manager) |
| GET / POST | /projects/{id}/agent_keys | Daftar / cetak kunci agen — manager, atau peran yang diizinkan kebijakan creator-roles proyek |
| DELETE | /projects/{id}/agent_keys/{kid} | Cabut kunci agen |
| GET | /projects/{id}/agent_keys/onboarding | Bundel onboarding: prompt dan file konfigurasi untuk klien agen yang umum |
| GET | /projects/{id}/agents · GET / PUT /projects/{id}/agents/{aid} | Agen-agen proyek dan profilnya (nama, inisial, deskripsi, warna) |
| POST | /projects/{id}/agents/{aid}/rotate-key · /projects/{id}/agents/{aid}/avatar | Rotasi kunci agen (identitas dan riwayat tetap) / unggah avatarnya |
Semua write story membutuhkan peran member.
| Metode | Path | Deskripsi |
|---|---|---|
| GET | /projects/{id}/stories | Daftar story (terpaginasi, dapat difilter) (viewer) |
| POST | /projects/{id}/stories | Buat story |
| GET | /projects/{id}/stories/{sid} | Dapatkan satu story (viewer) |
| PUT | /projects/{id}/stories/{sid} | Perbarui story |
| DELETE | /projects/{id}/stories/{sid} | Hapus story |
| POST | /projects/{id}/stories/{sid}/transitions | Ubah status dengan validasi |
| POST | /projects/{id}/stories/{sid}/reject · /projects/{id}/stories/{sid}/restart | Tolak story yang sudah delivered / kembalikan story yang ditolak ke started (rejected bersifat terminal bagi /transitions) |
| POST | /projects/{id}/stories/{sid}/archive · /projects/{id}/stories/{sid}/unarchive | Arsipkan / batalkan arsip satu story |
| POST | /projects/{id}/stories/bulk_transition | Transisikan banyak story (1–100) sekaligus |
| POST | /projects/{id}/stories/bulk-archive · bulk-delete · bulk-duplicate · bulk-move | Arsipkan, hapus, duplikat, atau pindahkan (ke panel / posisi) banyak story |
| POST | /projects/{id}/stories/{sid}/duplicate | Duplikat satu story |
| GET / POST / DELETE | /projects/{id}/stories/{sid}/epics · …/epics/{eid} | Keanggotaan epic dari story |
| GET | /short-links/{code} · /story-references | Selesaikan short link /s/<code> ke story-nya / selesaikan hingga 100 referensi story (#id, URL) ke story yang dapat dibaca pemanggil |
Parameter query daftar-story: archived= (exclude default / include / only — filter arsip tri-status; menggantikan include_archived=true yang usang, yang kini menjadi alias archived=include), include_done=true (mengikutsertakan story panel-Done yang dibekukan pada iterasi lampau, dikecualikan secara default). Paginasi (cursor= / limit= / offset=) dan set field parsial (fields=) mengikuti Paginasi dan Proyeksi field.
Create (POST …/stories): { "name" (required), "story_type": "feature|bug|chore|release", "description"?, "estimate"?, "current_state"?, "icebox"?, "labels"? }. estimate adalah label nilai skala sebagai string ("3", "13"); angka JSON ditolak. labels menerima ["auth"] atau [{ "name": "auth" }]; label yang tidak dikenal akan dibuat. Default: story_type=feature, current_state=unstarted.
Update (PUT …/stories/{sid}): field yang sama, semua opsional, plus "position" (float), "force_state_change" (bool), dan "expected_updated_at" (RFC 3339 — penyimpanan deskripsi ditolak dengan 409 stale_write jika story berubah sejak Anda membacanya). Write story juga menghormati If-Match terhadap ETag story; ketidakcocokan menghasilkan 412 precondition_failed.
Transition (POST …/transitions): { "to": "<state>" }. Field-nya adalah to. Mengembalikan { story_id, state }. Pergerakan ilegal → 422 invalid_transition dengan details: { from, to, allowed }.
Bulk transition (POST …/bulk_transition): { "story_ids": [int,…] (1–100), "to": "<state>" }. Setiap story dinilai secara independen; mengembalikan { results: [ { id, status: "ok" } | { id, status: "failed", error } ] }.
Sub-sumber daya story
Section titled “Sub-sumber daya story”Semua member. List/GET pada sebagian besar adalah (viewer).
| Metode | Path | Body / catatan |
|---|---|---|
| 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) } atau { comment_emoji }. GET menerima fields= (daftar yang diizinkan: comment_id, story_comment_id, story_id, comment_text, comment_emoji, member, created) plus 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; URL GitHub /pull/ dan /tree/ diberi tipe otomatis |
| GET / POST | /projects/{id}/stories/{sid}/reviews · PUT/DELETE …/reviews/{rid} | Buat: { reviewer_id? / reviewer_agent_id?, comment? } — hilangkan keduanya untuk menugaskan diri sendiri. Perbarui: { status, comment? } |
| GET / POST | /projects/{id}/stories/{sid}/owners · DELETE …/owners/{mid} · DELETE …/owners/agents/{aid} | { member_id? / agent_id? } — hilangkan keduanya untuk menambahkan pemanggil |
| 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} | unggah multipart — video ≤ 200 MB, PDF / Word / Excel ≤ 25 MB, gambar / CSV / teks ≤ 10 MB; daftar adalah (viewer) |
| GET / POST | /projects/{id}/stories/{sid}/link-attachments · DELETE …/link-attachments/{laid} | Lampiran tautan — URL eksternal yang disimpan bersama lampiran file, bukan sebagai link kode |
| GET | /attachments/{token} · /api/avatars/{token} | Pembacaan lampiran atau avatar berbasis token — URL yang dibagikan API; tidak perlu X-TrackerToken |
Bentuk yang sama dengan story, tanpa mesin status. member untuk write, (viewer) untuk pembacaan.
| Metode | Path | Deskripsi |
|---|---|---|
| GET / POST | /projects/{id}/epics · GET / PUT / DELETE …/epics/{eid} | Epic membawa nama, deskripsi Markdown, dan label pendukung yang menghubungkan story-story-nya |
| GET / POST / PUT / DELETE | …/epics/{eid}/comments · …/comments/{cid} | Komentar epic |
| GET / POST / DELETE | …/epics/{eid}/owners · …/followers (+ varian /agents/{aid}) | Pemilik dan pengikut, anggota atau agen — pemilik epic diturunkan ke story-story-nya |
| GET / POST / DELETE | …/epics/{eid}/attachments (+ /json) · …/link-attachments | Lampiran, batas yang sama dengan story |
| GET | /projects/{id}/analytics/epics · …/analytics/epics/{eid} | Progres per-epic: burnup, throughput, kesehatan, perkiraan (viewer) |
member untuk write, (viewer) untuk pembacaan.
| Metode | Path | Deskripsi |
|---|---|---|
| GET / POST | /projects/{id}/labels | Daftar / buat label |
| PUT / DELETE | /projects/{id}/labels/{lid} | Perbarui / hapus label |
| POST | /projects/{id}/labels/{lid}/archive | Arsipkan (sembunyikan-lunak) label |
Iterasi
Section titled “Iterasi”Pembacaan terbuka untuk peran proyek apa pun, dan anonim pada proyek publik.
| Metode | Path | Deskripsi |
|---|---|---|
| GET | /projects/{id}/iterations | Daftar iterasi (≤ 500 per halaman; membawa ETag dan header lanjutan X-Tracker-Pagination-* saat terpotong) |
| GET | /projects/{id}/iterations/{itid} | Satu iterasi |
| GET | /projects/{id}/iterations/first-preview | Tanggal yang akan diterima iterasi pertama, ditampilkan di konfirmasi pembuatan awal |
| POST | /projects/{id}/iterations | Buat iterasi manual (member) |
| DELETE | /projects/{id}/iterations/{itid} | Hapus iterasi (manager) |
| PUT | /projects/{id}/iterations/{itid}/velocity | Ganti velocity satu iterasi tanpa mengubah strategi proyek (manager) |
| GET | /projects/{id}/iterations/{itid}/done-stories | Story yang diterima dari iterasi yang sudah ditutup, terpaginasi |
Pencarian, metrik, preferensi
Section titled “Pencarian, metrik, preferensi”| Metode | Path | Deskripsi |
|---|---|---|
| GET | /projects/{id}/search?q=… | Pencarian yang kuat — teks-penuh + qualifier facet / rentang-tanggal / orang (DSL gaya GitHub); mengembalikan { results, total, limit, offset }. query adalah alias untuk q; limit= (default 50, maks 1000) / offset= untuk paginasi; sort= mengurutkan menurut relevance (default), created, created_asc, state, atau updated. (viewer) — lihat Panduan |
| GET | /projects/{id}/metrics/{velocity,burndown,story-types,contributors} | Deret data halaman Metrics (viewer); metrik epic ada di bawah /analytics/epics di atas |
| GET | /projects/{id}/backlog/grouping | Grup iterasi terproyeksi dari Backlog (viewer) |
| GET / PUT | /projects/{id}/preferences | Preferensi papan Anda untuk proyek ini — peran proyek apa pun, hanya baris milik Anda sendiri |
| Metode | Path | Deskripsi |
|---|---|---|
| GET | /projects/{id}/events | Aliran event dengan paginasi-kursor (member) — viewer mendapat 403 |
Parameter kueri: since=<event_id>, types=story.created,story.transitioned,comment.added,…, limit= (≤ 500), cursor=. Respons menyertakan next_cursor. Berikan event_id terakhir yang Anda lihat sebagai since untuk melanjutkan.
Notifikasi
Section titled “Notifikasi”Feed notifikasi terpadu di dalam aplikasi: baris notifikasi kelas satu (permintaan review, aktivitas story, undangan, …) digabung dengan kotak masuk @-sebutan menjadi satu aliran, terbaru lebih dulu. Id feed berawalan sumber (nt-… / sc-… / ec-…). Sesi anggota dan kunci ea_user_* membaca baris sisi-anggota mereka; kunci ea_agent_* baris sisi-agennya.
| Metode | Path | Deskripsi |
|---|---|---|
| GET | /me/notifications | Feed notifikasi Anda. Filter: unread=true, since_id=, kind= (mentions / reviews / stories / invitations); paginasi dengan cursor= / limit= |
| GET | /me/notifications/unread-count | Total belum dibaca — { unread_count, by_category: { mentions, reviews, stories, invitations } } |
| POST | /me/notifications/read-all | Tandai semua telah dibaca; mengembalikan hitungan terbaru |
| POST | /me/notifications/{id}/ack | Tandai satu item telah dibaca (idempoten) |
| POST | /me/notifications/{id}/accept | Terima undangan proyek / organisasi langsung dari feed (khusus token anggota) |
| POST | /me/notifications/{id}/decline | Tolak undangan proyek / organisasi (khusus token anggota) |
| GET | /me/notifications/resolve-invite?token=… | Petakan token undangan dari email ke id notifikasi Anda — { "id": "nt-…" } atau { "id": null } |
| GET | /me/notifications/stream | Push langsung — Server-Sent Events (text/event-stream); lihat di bawah |
Endpoint stream bukan endpoint JSON sehingga tidak ada dalam spesifikasi OpenAPI: ia menjaga koneksi tetap terbuka dan mengirim frame tanpa payload ({"type":"notification","kind":…}) setiap ada yang baru, memberi tahu klien untuk mengambil ulang feed. Koneksi diputus di sisi server setelah 45 menit — sambungkan dan autentikasi ulang. Hanya sesi anggota dan kunci ea_user_*; kunci ea_agent_* menerima 403.
Impor (manager)
Section titled “Impor (manager)”| Metode | Path | Deskripsi |
|---|---|---|
| POST | /projects/{id}/import | Sumber file: source= ∈ pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat. file= multipart. Sinkron — menjawab dengan hitungan hasil. |
| POST | /projects/{id}/import/json | Body JSON; source=github tidak memerlukan file — owner, repo, token opsional, dan flag opt-in include_pull_requests / include_milestones / include_releases / include_dependencies; sumber file mengirim file_base64. Asinkron: mengembalikan 202 { import_id, status }. Server mengambil lewat API GraphQL GitHub, yang menolak pemanggil anonim, jadi selalu ada token yang sampai ke GitHub — milik Anda, atau token bersama milik deployment. Lihat Panduan. |
| GET | /projects/{id}/imports/{import_id} | Poll sebuah job: status berjalan pending → fetching → writing → done | failed, dengan progress_current / progress_total selama pengambilan dan hitungan hasil saat done |
Hanya satu impor berjalan per proyek pada satu waktu; POST kedua saat satu masih berjalan adalah 409 import_already_running. dry_run: true (body JSON atau dry_run=true multipart) mempratinjau sumber apa pun: mengurai, menyelesaikan, mendeduplikasi, mengembalikan hitungan { imported, skipped, errors, unmatched } yang sama, lalu membatalkan — tanpa apa pun yang ditulis. Batas: body 10 MiB dan 5.000 story per impor untuk sumber berbasis file (melampaui salah satunya → 400, tanpa apa pun yang ditulis). Sumber GitHub tanpa plafon — ia menulis per bongkahan alih-alih satu transaksi. Impor ulang idempoten per source id — baris yang sudah diimpor dilewati, bukan diduplikasi.
Ekspor
Section titled “Ekspor”| Metode | Path | Deskripsi |
|---|---|---|
| GET | /projects/{id}/export/formats | Format yang terdaftar: { id, name, content_type, drops, includes_archived }. Peran proyek apa pun. |
| GET | /projects/{id}/export/{format} | Unduh satu (manager). Pertukaran: eat (kesetiaan penuh), jira, pivotal, shortcut, trello, asana, gitlab, linear, plane, plane_json; dokumen: pdf, docx. |
| GET | /projects/{id}/export/attachments | Setiap lampiran sebagai satu zip yang dapat dijelajahi (file mempertahankan nama asli; manifes JSON + CSV) (manager). |
Ekspor dokumen (pdf, docx) menerima parameter query tambahan: page_size= (letter default / a4 / legal / folio), from= / to= (batas jendela-story — RFC 3339 atau YYYY-MM-DD polos; sebuah story masuk rentang saat created atau completed_at-nya jatuh di dalamnya), include_icebox= / include_backlog= (keduanya default false, sehingga ekspor yang dapat dibagikan hanya menampilkan pekerjaan terjadwal / sedang berjalan). Format CSV pertukaran mengabaikannya.
Cadangan dan pemulihan (manager)
Section titled “Cadangan dan pemulihan (manager)”| Metode | Path | Deskripsi |
|---|---|---|
| GET / POST | /projects/{id}/backups · GET …/backups/{snapshot_id} · …/backups/health | Daftar snapshot, ambil satu sekarang, baca satu, dan ringkasan kesehatan retensi |
| GET / POST | /projects/{id}/restores · POST …/restores/partial · GET …/restores/{restore_id} | Pulihkan seluruh snapshot, atau tabel tertentu darinya, dan poll proses pemulihannya |
POST-POST tersebut berada di tingkat batas laju sensitive (di bawah).
MCP dan penyedia OAuth
Section titled “MCP dan penyedia OAuth”East Agile Tracker adalah penyedia OAuth 2.1 untuk klien MCP. Sebuah klien menemukannya di /.well-known/oauth-authorization-server dan /.well-known/oauth-protected-resource/mcp, mengarahkan Anda ke /oauth/authorize (halaman persetujuan), menukar kodenya di /oauth/token, lalu berbicara MCP di /mcp dengan token ea_mcp_* yang dihasilkan. Grant didaftar dan dicabut di /me/oauth_grants. Endpoint penyedia memiliki tingkat batas lajunya sendiri.
WebSocket
Section titled “WebSocket”wss://eastagiletracker.com/ws/control?token=<session JWT>Untuk kontrol-jarak-jauh UI interaktif ({ "action": "get_state", "id": "req-1" }). Tokennya adalah JWT sesi browser — kunci API ditolak dengan 401 sebelum upgrade. Bukan kanal data — semua pembacaan/write melalui REST. Hanya instans-tunggal; tidak disebarkan lintas replika.
Idempotensi
Section titled “Idempotensi”Endpoint write (POST, PUT, DELETE) menerima header Idempotency-Key. Kunci sama + body sama memutar ulang respons yang ter-cache (jendela 24-jam); kunci sama + body berbeda mengembalikan 409 idempotency_conflict. Kunci dicakup pada kredensial yang mengirimnya. Tidak diterapkan pada GET/HEAD/OPTIONS, /openapi.json dan /docs, /api/auth/*, atau unggahan multipart pada path /attachments. Respons yang berhenti sebelum sampai pada jawaban domain tidak pernah di-cache — 401, 403, 404, 429, dan setiap 5xx — sehingga coba-ulang setelah salah satunya mencapai handler; 400, 409, 412, dan 422 adalah jawaban domain dan diputar ulang seperti keberhasilan.
Paginasi
Section titled “Paginasi”Endpoint daftar menerima cursor=<opaque> dan limit=<n>. Saat diatur, responsnya adalah { "items": [...], "next_cursor": "<str|null>" }; berikan next_cursor kembali untuk halaman berikutnya. Batas limit berbeda per endpoint: 200 pada story, komentar, dan proyek; 500 pada event; 1000 pada pencarian dan log audit.
Daftar biasa (tanpa cursor/limit) yang harus memotong responsnya menyatakannya lewat header — X-Tracker-Pagination-Truncated, X-Tracker-Pagination-Limit, X-Tracker-Pagination-Offset, dan X-Tracker-Pagination-Next-Offset; kirim balik yang terakhir sebagai offset= untuk halaman berikutnya. Tidak ada header jumlah total.
Proyeksi field
Section titled “Proyeksi field”Endpoint daftar menerima fields= (dipisahkan koma) untuk mengembalikan hanya field tertentu. story_id selalu disertakan; nama field yang tidak dikenal mengembalikan 400 validation_failed dengan nama yang menyalahi di details.fields.
GET /projects/123/stories?fields=story_id,name,current_state,ownersFormat error
Section titled “Format error”Setiap error JSON memiliki code dan error; beberapa menambahkan details:
{ "code": "invalid_transition", "error": "Cannot move story from `unstarted` to `accepted`", "details": { "from": "unstarted", "to": "accepted", "allowed": ["started"] } }| Status | code | Kapan |
|---|---|---|
| 400 | invalid_parameter | input buruk; pesan di error, tanpa details (sebagian besar validasi: kosong/panjang/null-byte/email) |
| 400 | validation_failed | error input terstruktur; details.fields adalah array nama field yang menyalahi |
| 401 | unauthenticated | token hilang/tidak valid |
| 403 | unauthorized_operation | terautentikasi tetapi peran tidak mencukupi |
| 404 | unfound_resource | tidak ditemukan — juga dikembalikan ke non-member |
| 409 | conflict | konflik sumber daya (mis. duplikat) |
| 409 | idempotency_conflict | Idempotency-Key digunakan ulang dengan body berbeda |
| 409 | stale_write · import_already_running | story berubah sejak expected_updated_at Anda · sebuah impor sedang berjalan |
| 412 | precondition_failed | If-Match tidak cocok dengan ETag sumber daya saat ini; details membawa expected dan current |
| 413 | request_too_large | body melebihi batas ukuran route |
| 422 | invalid_transition | pergerakan status ilegal; details membawa { from, to, allowed } |
| 429 | rate_limited | terlalu banyak request dari IP ini pada route yang dibatasi laju; header Retry-After |
| 500 | internal_error | kesalahan server — pesan generik; aman untuk dicoba-ulang |
| 503 | not_configured | deployment tidak memiliki integrasi yang dibutuhkan route ini (SMS, penyimpanan objek, …) |
details.fields adalah array JSON nama field (mis. ["to"]), kadang dengan kunci tambahan seperti max. Tidak ada peta field→pesan.
{ "code": "validation_failed", "error": "unknown field(s): foo", "details": { "fields": ["foo"] } }Batas laju
Section titled “Batas laju”Per IP klien, pada segelintir route; lalu lintas API terautentikasi di tempat lain tidak dibatasi lajunya. Default (setiap pasangan adalah laju berkelanjutan dan burst, dapat disetel operator):
- Auth —
/api/auth/*: 0,5 req/d, burst 20. - OAuth provider —
/oauth/*: 1 req/d, burst 60. - Public —
/api/contact: 0,2 req/d, burst 10. - Feedback —
/api/feedback: tiga tingkat bertumpuk — satu kiriman per 15 d, 10 per jam, 36 per hari. - Avatars — pengalihan avatar tanpa autentikasi: 20 req/d, burst 200.
- Sensitive —
POSTcadangan dan pemulihan: ~0,002 req/d, burst 5.
Batas yang terlampaui mengembalikan 429 dengan header Retry-After dan amplop error JSON standar, code: "rate_limited".