Полный справочник по REST-эндпоинтам. Туториалы и примеры см. в Руководстве по API.
Всё, что участник проекта может делать в веб-интерфейсе, доступно здесь — SPA потребляет тот же самый API. Операции, требующие роли manager, помечены (manager); всему остальному нужно лишь членство в проекте (или, для операций чтения, помеченных (viewer), любой уровень доступа). В таблицах ниже перечислена каждая группа маршрутов, которую монтирует сервер; те, что сведены к одной строке, полностью описаны в актуальном openapi.json.
https://eastagiletracker.com/api/v1https://api.eastagiletracker.com/api/v1 обслуживает идентичный API. Все запросы и ответы — это JSON, за исключением нескольких эндпоинтов загрузки файлов, которые принимают multipart.
Две группы находятся уровнем выше, под /api, а не /api/v1: поверхность аутентификации (/api/auth/*) и публичные формы (/api/contact, /api/feedback). Их написание через /api/v1/… возвращает 404.
Аутентификация
Заголовок раздела «Аутентификация»Каждый аутентифицированный запрос отправляет учётные данные одним из способов:
X-TrackerToken: <key>Authorization: Bearer <key>
Пользовательские ключи начинаются с ea_user_, ключи агентов — с ea_agent_, а access-токены MCP — с ea_mcp_. См. Руководство по API → Три вида учётных данных.
Эндпоинты без аутентификации: /openapi.json, /docs, эндпоинты /api/auth/* и справочные данные (/story_types, /story_states, /effort_scales, /priority_scales). /meta требует аутентификации — подходит любой действительный ключ, но он не ограничен проектом (привязанный к проекту ключ агента тоже до него дотягивается).
Четыре уровня управляют эндпоинтами, ограниченными проектом:
| Level | Who passes | Typical operations |
|---|---|---|
| public viewer | кто угодно, в проекте с публичной видимостью | чтение доски: истории, итерации, поиск, активность по историям и эпикам (с сокрытыми данными актора) |
| viewer | viewer, member, manager | чтение (список/получение историй, поиск, метрики, список форматов экспорта) |
| member | member, manager | все операции записи рабочих элементов (истории, задачи, комментарии, …), поток событий |
| manager | только manager | настройки проекта, управление членством, ключи агентов, удаление, импорт, скачивание экспорта, резервные копии, журнал аудита |
Агенты держат те же роли, что и участники, — viewer, member или manager, — с потолком в виде роли выпустившего ключ участника. Не-участник получает 404 unfound_resource (а не 403) на путях приватного проекта, так что ID проектов не перечислимы.
Самоописывающиеся эндпоинты
Заголовок раздела «Самоописывающиеся эндпоинты»| Method | Path | Description |
|---|---|---|
| GET | /openapi.json | Актуальная спецификация OpenAPI 3, включая тела запросов. Без аутентификации. |
| GET | /docs | Swagger UI. Без аутентификации. |
| GET | /meta | Идентичность вызывающего (auth.kind/key_id/agent_id/project_id) + граф переходов для типов историй. Требует аутентификации (любой действительный ключ; не ограничен проектом). Вызывайте это первым. |
| GET | /api/health · /api/config | Проверка живости и публичная конфигурация развёртывания (режим одной организации, включённые необязательные функции, название экземпляра). Без аутентификации, вне /v1. |
Auth (/api/auth/*, вне /v1)
Заголовок раздела «Auth (/api/auth/*, вне /v1)»Эндпоинты сессий, без аутентификации, если не указано иное. Ими управляет SPA; скрипты обычно используют вместо этого API-ключ.
| Method | Path | Description |
|---|---|---|
| POST | /auth/register | Зарегистрировать новый аккаунт — защищено reCAPTCHA; затем аккаунт проходит SMS-проверку |
| POST | /auth/sms/challenge · /auth/sms/status · /auth/sms/bypass | Отправить / проверить код регистрации по SMS (bypass открыт только оператору) |
| GET | /auth/config | Какие способы входа предлагает развёртывание |
| POST | /auth/login | Вход по email + паролю; возвращает JWT сессии либо TOTP-запрос |
| POST | /auth/login/totp | Завершить вход кодом из приложения-аутентификатора или кодом восстановления |
| POST | /auth/passkey/login/start · /auth/passkey/login/finish | Беспарольный вход через WebAuthn |
| GET | /auth/oauth/github/start · /auth/oauth/github/callback · /auth/oauth/google/start · /auth/oauth/google/callback · POST /auth/oauth/exchange | Вход через OAuth с GitHub или Google |
| POST | /auth/refresh · /auth/refresh/revoke | Ротировать refresh-токен / отозвать его |
| POST | /auth/logout | Выйти (отзывает refresh-токен) |
| POST | /auth/forgot-password · /auth/reset-password | Запросить письмо для сброса / использовать токен сброса |
| POST | /auth/accept-invite/lookup · /auth/accept-invite | Разрешить токен приглашения → email / принять приглашение в проект (после аутентификации) |
Аккаунт / идентичность
Заголовок раздела «Аккаунт / идентичность»Эти действуют от имени вызывающего и требуют лишь действительного ключа (без роли в проекте).
| Method | Path | Description |
|---|---|---|
| GET | /me | Профиль текущего пользователя |
| PUT | /me | Обновить профиль |
| DELETE | /me | Удалить аккаунт — отклоняется, пока вы единственный владелец организации или проекта, в котором есть другие участники |
| GET | /me/deletion-impact | Что удаление аккаунта уберёт и что ему мешает |
| PUT | /me/password | Сменить пароль |
| PUT | /me/settings | Обновить настройки (тема, предпочтения уведомлений) |
| POST | /me/avatar | Загрузить аватар (multipart) |
| POST | /me/api-token/regenerate | Ротировать ваш API-токен — аннулирует существующие сессии/ключи |
| GET | /me/api_keys · POST /me/api_keys · DELETE /me/api_keys/{id} | Управление пользовательскими (ea_user_) API-ключами |
| GET | /me/totp · POST /me/totp/setup · /me/totp/verify · /me/totp/disable | Подключение двухфакторной аутентификации (TOTP); verify один раз возвращает коды восстановления |
| GET | /me/passkeys · POST /me/passkeys/register/start · /me/passkeys/register/finish · DELETE /me/passkeys/{credential_id} | Регистрация и удаление passkey |
| GET | /me/oauth_grants · DELETE /me/oauth_grants/{grant_id} | Подключённые приложения — MCP-клиенты и OAuth-приложения, которые вы авторизовали |
| GET | /me/activity | Ваша активность по всем проектам |
| GET | /me/stories | Истории, которыми вы владеете, которые запросили или за которыми следите, во всех проектах, доступных токену — role=owned|requested|following, state=, cursor= / limit= (максимум 200) |
| GET | /me/mentions · POST /me/mentions/{mention_id}/ack | Входящие @-упоминания (unacked=true для фильтрации) и подтверждение — также сведены в ленту уведомлений ниже |
| GET | /me/data-export | GDPR-самоэкспорт ваших данных |
| GET | /me/consent · POST /me/consent | Прочитать / записать согласие ({ consent_type, granted }) |
| GET | /legal/pending · POST /legal/accept | Ожидающие clickwrap-документы / запись принятия |
| GET / PUT | /agent/me | Собственная идентичность и профиль ключа агента, доступные агенту на чтение и запись (аналог /me со стороны агента) |
| POST | /api/contact · /api/feedback · /api/feedback/with-screenshot | Контакт + обратная связь внутри приложения. Вне /v1; с ограничением частоты по IP |
Справочные данные (без аутентификации)
Заголовок раздела «Справочные данные (без аутентификации)»Стартовые справочники, используемые при создании/оценке историй. Стабильные ID.
| Method | Path | Description |
|---|---|---|
| GET | /story_types | feature, bug, chore, release (+ allow_points) |
| GET | /story_states | unstarted … accepted, rejected |
| GET | /effort_scales | доступные шкалы оценки |
| GET | /effort_scales/{scale_id}/values | значения баллов в шкале |
| GET | /priority_scales · /priority_scales/{scale_id}/values | шкалы приоритетов и их значения (priority_id истории разрешается здесь) |
Организации
Заголовок раздела «Организации»Только в хостируемом сервисе — self-hosted-установка работает в режиме одной организации и не монтирует эти эндпоинты (кроме списка организаций). Роли здесь организационные: owner, admin, member.
| Method | Path | Description |
|---|---|---|
| GET / POST | /organizations | Список ваших организаций / создать одну |
| GET / PUT / DELETE | /organizations/{oid} | Прочитать, переименовать (имя + slug; owner или admin), удалить |
| GET / POST | /organizations/{oid}/memberships · PUT / DELETE …/memberships/{member_id} | Участники и приглашения; у приглашения есть потолок роли (никогда выше роли самого приглашающего; owner никогда не выдаётся приглашением) |
| POST | /organizations/{oid}/memberships/bulk-role · …/memberships/bulk-remove | Смена роли или удаление до 200 участников за раз. Всё или ничего: пакет, который удалил бы последнего owner или оставил проект без владельца, отклоняется целиком; с reassign_confirmed владельцем этих проектов становитесь вы |
| DELETE | /organizations/{oid}/invitations/{invitation_id} | Отозвать ожидающее приглашение |
| POST | /organizations/{oid}/transfer-ownership | Передать роль owner другому участнику |
| PUT | /organizations/{oid}/memberships/{member_id}/anonymization | Скрыть имя / email / аватар участника во всей организации |
| GET | /organization-invitations/{token} · POST …/{token}/accept | Разрешить / принять присланное по почте приглашение в организацию |
| POST | /organizations/{oid}/export · GET / POST …/export/jobs · GET …/export/jobs/{job_id} · …/export/jobs/{job_id}/download | Экспорт организации, только для владельца: zip с SQL-дампом и каждым вложением, выполняется как задача |
Проекты
Заголовок раздела «Проекты»| Method | Path | Description |
|---|---|---|
| GET | /projects | Список ваших проектов (limit ≤ 200) |
| POST | /projects | Создать проект |
| GET | /projects/{id} | Получить детали проекта (viewer) |
| PUT | /projects/{id} | Обновить настройки проекта (manager) |
| DELETE | /projects/{id} | Удалить проект (manager) |
| POST | /projects/{id}/pin | Закрепить / открепить проект в вашем списке проектов |
| POST | /projects/{id}/transfer-organization | Перенести проект в другую организацию (manager) |
| POST | /projects/{id}/slack/test | Отправить тестовое сообщение в Slack-ленту проекта (manager) |
| GET / POST | /projects/{id}/showcase_claim_eligibility · /projects/{id}/showcase_claim · /projects/{id}/showcase_seed | Публичные витринные проекты: проверить, можете ли вы забрать такой проект, забрать его, наполнить его данными |
| GET | /projects/{id}/audit-log | Чтение журнала аудита — история проекта плюс активность по историям / по эпикам через surface=; доступ зависит от surface, см. ниже |
| GET | /projects/{id}/events | Поток событий с курсорной пагинацией (member) — см. Events |
Query-параметры журнала аудита: event_type= (один тип или список через запятую), limit= (≤ 1000), before= (keyset-курсор, created_at в ISO-8601), surface= (project_history, story_activities, epic_activities), target_id= (id истории/эпика — обязателен, когда surface=story_activities или epic_activities). Доступ: нефильтрованный лог и surface=project_history — (manager); story_activities / epic_activities может читать любой участник проекта, а в публичных проектах — и анонимно, со скрытыми персональными данными актора.
Участники, агенты и ключи агентов
Заголовок раздела «Участники, агенты и ключи агентов»| Method | Path | Description |
|---|---|---|
| GET | /projects/{id}/memberships | Список участников (viewer) |
| POST | /projects/{id}/memberships | Пригласить участника по email (manager) |
| PUT | /projects/{id}/memberships/{mid} | Обновить роль (manager) |
| DELETE | /projects/{id}/memberships/{mid} | Удалить участника (manager) |
| GET | /projects/{id}/addable-members · POST /projects/{id}/members/add-existing | Участники организации, ещё не добавленные в проект / добавить одного без приглашения по почте (manager) |
| POST | /projects/{id}/members/join | Owner или admin организации присоединяется к проекту своей организации как manager либо повышает себя до этой роли (действие Make me owner в списке проектов) |
| PUT | /projects/{id}/members/{mid}/anonymization | Скрыть имя / email / аватар участника в этом проекте (manager) |
| GET / POST | /projects/{id}/agent_keys | Список / выпуск ключей агентов — менеджеры либо те роли, которые допускает политика ролей-создателей проекта |
| DELETE | /projects/{id}/agent_keys/{kid} | Отозвать ключ агента |
| GET | /projects/{id}/agent_keys/onboarding | Стартовый набор: промпты и конфигурационные файлы для распространённых агентских клиентов |
| GET | /projects/{id}/agents · GET / PUT /projects/{id}/agents/{aid} | Агенты проекта и их профили (имя, инициалы, описание, цвет) |
| POST | /projects/{id}/agents/{aid}/rotate-key · /projects/{id}/agents/{aid}/avatar | Ротировать ключ агента (идентичность и история сохраняются) / загрузить его аватар |
Истории
Заголовок раздела «Истории»Всем операциям записи историй нужна роль member.
| Method | Path | Description |
|---|---|---|
| GET | /projects/{id}/stories | Список историй (с пагинацией, фильтруемый) (viewer) |
| POST | /projects/{id}/stories | Создать историю |
| GET | /projects/{id}/stories/{sid} | Получить одну историю (viewer) |
| PUT | /projects/{id}/stories/{sid} | Обновить историю |
| DELETE | /projects/{id}/stories/{sid} | Удалить историю |
| POST | /projects/{id}/stories/{sid}/transitions | Сменить состояние с валидацией |
| POST | /projects/{id}/stories/{sid}/reject · /projects/{id}/stories/{sid}/restart | Отклонить доставленную историю / вернуть отклонённую в started (для /transitions состояние rejected терминально) |
| POST | /projects/{id}/stories/{sid}/archive · /projects/{id}/stories/{sid}/unarchive | Архивировать / разархивировать одну историю |
| POST | /projects/{id}/stories/bulk_transition | Перевести много историй (1–100) сразу |
| POST | /projects/{id}/stories/bulk-archive · bulk-delete · bulk-duplicate · bulk-move | Архивировать, удалить, дублировать или переместить (в панель / на позицию) много историй |
| POST | /projects/{id}/stories/{sid}/duplicate | Дублировать одну историю |
| GET / POST / DELETE | /projects/{id}/stories/{sid}/epics · …/epics/{eid} | Принадлежность истории эпикам |
| GET | /short-links/{code} · /story-references | Разрешить короткую ссылку /s/<code> в её историю / разрешить до 100 ссылок на истории (#id, URL) в истории, доступные вызывающему |
Параметры запроса списка историй: archived= (exclude по умолчанию / include / only — трёхзначный фильтр архивных историй; заменяет устаревший include_archived=true, который теперь является псевдонимом archived=include), include_done=true (допускает истории панели Done, замороженные на прошлых итерациях; по умолчанию исключены). Пагинация (cursor= / limit= / offset=) и разреженные наборы полей (fields=) следуют разделам Пагинация и Проекция полей.
Create (POST …/stories): { "name" (required), "story_type": "feature|bug|chore|release", "description"?, "estimate"?, "current_state"?, "icebox"?, "labels"? }. estimate — это подпись значения шкалы в виде строки ("3", "13"); JSON-число отклоняется. labels принимает ["auth"] или [{ "name": "auth" }]; неизвестные метки создаются. Значения по умолчанию: story_type=feature, current_state=unstarted.
Update (PUT …/stories/{sid}): те же поля, все опциональные, плюс "position" (float), "force_state_change" (bool) и "expected_updated_at" (RFC 3339 — сохранение описания отклоняется с 409 stale_write, если история изменилась с момента вашего чтения). Операции записи истории также учитывают If-Match относительно ETag истории; несовпадение — это 412 precondition_failed.
Transition (POST …/transitions): { "to": "<state>" }. Поле называется to. Возвращает { story_id, state }. Недопустимое перемещение → 422 invalid_transition с details: { from, to, allowed }.
Bulk transition (POST …/bulk_transition): { "story_ids": [int,…] (1–100), "to": "<state>" }. Каждая история оценивается независимо; возвращает { results: [ { id, status: "ok" } | { id, status: "failed", error } ] }.
Подресурсы истории
Заголовок раздела «Подресурсы истории»Все member. List/GET для большинства — (viewer).
| Method | Path | Body / notes |
|---|---|---|
| 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) } или { comment_emoji }. GET принимает fields= (список разрешённых: comment_id, story_comment_id, story_id, comment_text, comment_emoji, member, created) плюс 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/ и /tree/ типизируются автоматически |
| GET / POST | /projects/{id}/stories/{sid}/reviews · PUT/DELETE …/reviews/{rid} | Создание: { reviewer_id? / reviewer_agent_id?, comment? } — опустите оба, чтобы назначить себя. Обновление: { status, comment? } |
| GET / POST | /projects/{id}/stories/{sid}/owners · DELETE …/owners/{mid} · DELETE …/owners/agents/{aid} | { member_id? / agent_id? } — опустите оба, чтобы добавить вызывающего |
| 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} | multipart-загрузка — видео ≤ 200 MB, PDF / Word / Excel ≤ 25 MB, изображения / CSV / текст ≤ 10 MB; список — (viewer) |
| GET / POST | /projects/{id}/stories/{sid}/link-attachments · DELETE …/link-attachments/{laid} | Вложения-ссылки — внешний URL, который хранится рядом с файловыми вложениями, а не как ссылка на код |
| GET | /attachments/{token} · /api/avatars/{token} | Чтение вложения или аватара по токену — именно такие URL выдаёт API; X-TrackerToken не нужен |
Та же форма, что и у историй, только без конечного автомата состояний. member для записи, (viewer) для чтения.
| Method | Path | Description |
|---|---|---|
| GET / POST | /projects/{id}/epics · GET / PUT / DELETE …/epics/{eid} | У эпика есть имя, Markdown-описание и стоящая за ним метка, которая объединяет его истории |
| GET / POST / PUT / DELETE | …/epics/{eid}/comments · …/comments/{cid} | Комментарии к эпику |
| GET / POST / DELETE | …/epics/{eid}/owners · …/followers (+ варианты /agents/{aid}) | Владельцы и подписчики, участники или агенты — владельцы эпика распространяются на его истории |
| GET / POST / DELETE | …/epics/{eid}/attachments (+ /json) · …/link-attachments | Вложения, ограничения те же, что у историй |
| GET | /projects/{id}/analytics/epics · …/analytics/epics/{eid} | Прогресс по каждому эпику: burnup, пропускная способность, здоровье, прогноз (viewer) |
member для записи, (viewer) для чтения.
| Method | Path | Description |
|---|---|---|
| GET / POST | /projects/{id}/labels | Список / создание метки |
| PUT / DELETE | /projects/{id}/labels/{lid} | Обновление / удаление метки |
| POST | /projects/{id}/labels/{lid}/archive | Архивировать (мягко скрыть) метку |
Итерации
Заголовок раздела «Итерации»Чтение открыто для любой роли в проекте, а в публичном проекте — и анонимно.
| Method | Path | Description |
|---|---|---|
| GET | /projects/{id}/iterations | Список итераций (≤ 500 на страницу; несёт ETag, а при усечении — заголовки продолжения X-Tracker-Pagination-*) |
| GET | /projects/{id}/iterations/{itid} | Одна итерация |
| GET | /projects/{id}/iterations/first-preview | Даты, которые получит первая итерация, — показываются в подтверждении при её создании |
| POST | /projects/{id}/iterations | Создать ручную итерацию (member) |
| DELETE | /projects/{id}/iterations/{itid} | Удалить итерацию (manager) |
| PUT | /projects/{id}/iterations/{itid}/velocity | Переопределить velocity одной итерации, не меняя стратегию проекта (manager) |
| GET | /projects/{id}/iterations/{itid}/done-stories | Принятые истории закрытой итерации, с пагинацией |
Поиск, метрики, предпочтения
Заголовок раздела «Поиск, метрики, предпочтения»| Method | Path | Description |
|---|---|---|
| GET | /projects/{id}/search?q=… | Мощный поиск — полнотекстовый + фасетные, датовые и «людские» квалификаторы (DSL в стиле GitHub); возвращает { results, total, limit, offset }. query — псевдоним q; limit= (по умолчанию 50, максимум 1000) / offset= — пагинация; sort= сортирует по relevance (по умолчанию), created, created_asc, state или updated. (viewer) — см. Руководство |
| GET | /projects/{id}/metrics/{velocity,burndown,story-types,contributors} | Ряды данных страницы Metrics (viewer); метрики по эпикам находятся в /analytics/epics выше |
| GET | /projects/{id}/backlog/grouping | Спроецированные группы итераций из Backlog (viewer) |
| GET / PUT | /projects/{id}/preferences | Ваши предпочтения доски для этого проекта — любая роль в проекте, только ваша собственная строка |
События
Заголовок раздела «События»| Method | Path | Description |
|---|---|---|
| GET | /projects/{id}/events | Поток событий с курсорной пагинацией (member) — viewer получает 403 |
Параметры запроса: since=<event_id>, types=story.created,story.transitioned,comment.added,…, limit= (≤ 500), cursor=. Ответ включает next_cursor. Передайте последний увиденный event_id как since, чтобы возобновить.
Уведомления
Заголовок раздела «Уведомления»Единая лента уведомлений в приложении: полноценные строки уведомлений (запросы на ревью, активность по story, приглашения, …), объединённые с входящими @-упоминаниями в один поток, сначала новые. Id в ленте имеют префикс источника (nt-… / sc-… / ec-…). Сессии участников и ключи ea_user_* читают свои строки участника; ключи ea_agent_* — свои строки агента.
| Method | Path | Description |
|---|---|---|
| GET | /me/notifications | Ваша лента уведомлений. Фильтры: unread=true, since_id=, kind= (mentions / reviews / stories / invitations); пагинация через cursor= / limit= |
| GET | /me/notifications/unread-count | Счётчики непрочитанного — { unread_count, by_category: { mentions, reviews, stories, invitations } } |
| POST | /me/notifications/read-all | Отметить всё прочитанным; возвращает свежие счётчики |
| POST | /me/notifications/{id}/ack | Отметить один элемент прочитанным (идемпотентно) |
| POST | /me/notifications/{id}/accept | Принять приглашение в проект / организацию прямо из ленты (только токены участника) |
| POST | /me/notifications/{id}/decline | Отклонить приглашение в проект / организацию (только токены участника) |
| GET | /me/notifications/resolve-invite?token=… | Сопоставить присланный по почте токен приглашения с id вашего уведомления — { "id": "nt-…" } или { "id": null } |
| GET | /me/notifications/stream | Живой push — Server-Sent Events (text/event-stream); см. ниже |
Stream-эндпоинт — не JSON-эндпоинт, поэтому его нет в спецификации OpenAPI: он держит соединение открытым и при каждом новом событии отправляет кадр без полезной нагрузки ({"type":"notification","kind":…}), сигнализируя клиенту перезагрузить ленту. Соединения закрываются сервером через 45 минут — переподключитесь и пройдите аутентификацию заново. Только сессии участников и ключи ea_user_*; ключи ea_agent_* получают 403.
Импорт (manager)
Заголовок раздела «Импорт (manager)»| Method | Path | Description |
|---|---|---|
| POST | /projects/{id}/import | Файловые источники: source= ∈ pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat. Multipart file=. Синхронный — отвечает счётчиками результата. |
| POST | /projects/{id}/import/json | JSON-тело; source=github не требует файла — owner, repo, опциональный token и включаемые по выбору флаги include_pull_requests / include_milestones / include_releases / include_dependencies; файловые источники присылают file_base64. Асинхронный: возвращает 202 { import_id, status }. Сервер выбирает данные через GraphQL API GitHub, который отклоняет анонимных вызывающих, поэтому до GitHub всегда доходит токен — ваш либо общий токен развёртывания. См. Руководство. |
| GET | /projects/{id}/imports/{import_id} | Опросить задачу: status проходит pending → fetching → writing → done | failed, с progress_current / progress_total во время выборки и счётчиками результата при done |
В проекте одновременно выполняется один импорт; второй POST, пока один в работе, даёт 409 import_already_running. dry_run: true (в JSON-теле или dry_run=true в multipart) даёт предпросмотр любого источника: разбирает, сопоставляет, устраняет дубликаты, возвращает те же счётчики { imported, skipped, errors, unmatched }, а затем откатывает — ничего не записывается. Ограничения: тело 10 МиБ и 5000 историй на импорт для файловых источников (сверх любого → 400, ничего не записывается). У источника GitHub потолка нет — он пишет порциями, а не одной транзакцией. Повторный импорт идемпотентен по id в источнике — уже импортированные строки пропускаются, а не дублируются.
Экспорт
Заголовок раздела «Экспорт»| Method | Path | Description |
|---|---|---|
| GET | /projects/{id}/export/formats | Зарегистрированные форматы: { id, name, content_type, drops, includes_archived }. Любая роль в проекте. |
| GET | /projects/{id}/export/{format} | Скачать один (manager). Обмен: eat (полная точность), jira, pivotal, shortcut, trello, asana, gitlab, linear, plane, plane_json; документы: pdf, docx. |
| GET | /projects/{id}/export/attachments | Все вложения одним просматриваемым zip (файлы сохраняют исходные имена; манифест JSON + CSV) (manager). |
Экспорты документов (pdf, docx) принимают дополнительные параметры запроса: page_size= (letter по умолчанию / a4 / legal / folio), from= / to= (границы окна историй — RFC 3339 или просто YYYY-MM-DD; история попадает в диапазон, когда её created или completed_at лежит внутри него), include_icebox= / include_backlog= (оба по умолчанию false, поэтому предназначенный для распространения экспорт показывает только запланированную / текущую работу). Форматы обмена CSV их игнорируют.
Резервные копии и восстановление (manager)
Заголовок раздела «Резервные копии и восстановление (manager)»| Method | Path | Description |
|---|---|---|
| GET / POST | /projects/{id}/backups · GET …/backups/{snapshot_id} · …/backups/health | Список снимков, создать снимок прямо сейчас, прочитать один, а также сводка по здоровью хранения |
| GET / POST | /projects/{id}/restores · POST …/restores/partial · GET …/restores/{restore_id} | Восстановить снимок целиком либо выбранные таблицы из него и опросить ход восстановления |
Эти POST находятся в чувствительном уровне ограничения частоты (см. ниже).
MCP и OAuth-провайдер
Заголовок раздела «MCP и OAuth-провайдер»East Agile Tracker — это OAuth 2.1-провайдер для MCP-клиентов. Клиент обнаруживает его по /.well-known/oauth-authorization-server и /.well-known/oauth-protected-resource/mcp, отправляет вас на /oauth/authorize (страница согласия), обменивает код на /oauth/token, а затем говорит по MCP на /mcp с полученным токеном ea_mcp_*. Выданные разрешения перечисляются и отзываются на /me/oauth_grants. У эндпоинтов провайдера свой уровень ограничения частоты.
WebSocket
Заголовок раздела «WebSocket»wss://eastagiletracker.com/ws/control?token=<session JWT>Для интерактивного удалённого управления интерфейсом ({ "action": "get_state", "id": "req-1" }). Токен — это JWT сессии браузера; API-ключ отклоняется с 401 ещё до апгрейда соединения. Не канал данных — все чтения/записи идут через REST. Только для одного инстанса; не распределяется между репликами.
Идемпотентность
Заголовок раздела «Идемпотентность»Эндпоинты записи (POST, PUT, DELETE) принимают заголовок Idempotency-Key. Тот же ключ + то же тело воспроизводят кэшированный ответ (окно 24 часа); тот же ключ + другое тело возвращают 409 idempotency_conflict. Область действия ключа ограничена теми учётными данными, которые его отправили. Не применяется к GET/HEAD/OPTIONS, /openapi.json и /docs, /api/auth/* или multipart-загрузкам на путях /attachments. Ответы, не дошедшие до доменного ответа, никогда не кэшируются — 401, 403, 404, 429 и любой 5xx, — поэтому повтор после любого из них доходит до обработчика; 400, 409, 412 и 422 являются ответом домена и воспроизводятся так же, как успех.
Пагинация
Заголовок раздела «Пагинация»Эндпоинты списков принимают cursor=<opaque> и limit=<n>. Когда заданы, ответ — это { "items": [...], "next_cursor": "<str|null>" }; передайте next_cursor обратно для перехода на страницу. Потолок limit задаётся для каждого эндпоинта: 200 у историй, комментариев и проектов; 500 у событий; 1000 у поиска и журнала аудита.
Обычный список (без cursor/limit), которому пришлось усечь ответ, сообщает об этом в заголовках — X-Tracker-Pagination-Truncated, X-Tracker-Pagination-Limit, X-Tracker-Pagination-Offset и X-Tracker-Pagination-Next-Offset; последний передайте обратно как offset= для следующей страницы. Заголовка с общим количеством нет.
Проекция полей
Заголовок раздела «Проекция полей»Эндпоинты списков принимают fields= (через запятую), чтобы возвращать только конкретные поля. story_id включается всегда; неизвестное имя поля возвращает 400 validation_failed с нарушающими именами в details.fields.
GET /projects/123/stories?fields=story_id,name,current_state,ownersФормат ошибок
Заголовок раздела «Формат ошибок»У каждой JSON-ошибки есть code и error; некоторые добавляют details:
{ "code": "invalid_transition", "error": "Cannot move story from `unstarted` to `accepted`", "details": { "from": "unstarted", "to": "accepted", "allowed": ["started"] } }| Status | code | When |
|---|---|---|
| 400 | invalid_parameter | плохой ввод; сообщение в error, без details (большинство валидаций: пусто/длина/null-байт/email) |
| 400 | validation_failed | структурированная ошибка ввода; details.fields — это массив имён нарушающих полей |
| 401 | unauthenticated | отсутствующий/недействительный токен |
| 403 | unauthorized_operation | аутентифицирован, но недостаточная роль |
| 404 | unfound_resource | не найдено — также возвращается не-участникам |
| 409 | conflict | конфликт ресурса (например, дубликат) |
| 409 | idempotency_conflict | Idempotency-Key повторно использован с другим телом |
| 409 | stale_write · import_already_running | история изменилась с момента вашего expected_updated_at · импорт уже выполняется |
| 412 | precondition_failed | If-Match не совпал с текущим ETag ресурса; details несёт expected и current |
| 413 | request_too_large | тело превышает лимит размера для этого маршрута |
| 422 | invalid_transition | недопустимое перемещение состояния; details несёт { from, to, allowed } |
| 429 | rate_limited | слишком много запросов с этого IP на маршруте с ограничением частоты; заголовок Retry-After |
| 500 | internal_error | сбой сервера — обобщённое сообщение; безопасно повторять |
| 503 | not_configured | в развёртывании нет интеграции, которая нужна этому маршруту (SMS, объектное хранилище, …) |
details.fields — это JSON-массив имён полей (например, ["to"]), иногда с дополнительными ключами вроде max. Карты «поле→сообщение» нет.
{ "code": "validation_failed", "error": "unknown field(s): foo", "details": { "fields": ["foo"] } }Ограничения частоты
Заголовок раздела «Ограничения частоты»По IP клиента, на нескольких маршрутах; остальной аутентифицированный API-трафик не ограничивается по частоте. Значения по умолчанию (каждая пара — это установившаяся частота и всплеск, настраивается оператором):
- Auth —
/api/auth/*: 0.5 запр/с, всплеск 20. - OAuth provider —
/oauth/*: 1 запр/с, всплеск 60. - Public —
/api/contact: 0.2 запр/с, всплеск 10. - Feedback —
/api/feedback: три уровня друг над другом — одна отправка в 15 с, 10 в час, 36 в сутки. - Avatars — редирект аватара без аутентификации: 20 запр/с, всплеск 200.
- Sensitive —
POST-запросы резервного копирования и восстановления: ~0.002 запр/с, всплеск 5.
Превышенный лимит возвращает 429 с заголовком Retry-After и стандартным JSON-конвертом ошибки, code: "rate_limited".