24 KiB
Devprom ALM REST API — рабочая шпаргалка
Справочник для загрузки Пожеланий, Заявок, Требований и вложений в Devprom ALM
через REST API. Имена сущностей сверены с официальной таблицей справочника
разработчика: /pm/all/apidocs/list (например,
artsaterra.myalm.ru/pm/all/apidocs/list),
где каждая строка — одна сущность с её ReferenceName (используется в REST API)
и русским именем. Ключевые строки, участвующие в режиме Пожеланий из совещания:
| № | ReferenceName | Сущность |
|---|---|---|
| 45 | issue |
Пожелание |
| 18 | request |
Доработка (заявка с типом) |
| 81 | requesttype |
Тип пожелания |
| 92 | requirement |
Требование |
| 57 | attachment |
Приложение (файл) |
| 33 | company |
Компания |
| 46 | user |
Пользователь |
Дополнительные эмпирические детали (поведение, которое в публичной
документации не раскрыто явно) проверены на инстансе artsaterra.myalm.ru
и отмечаются в тексте курсивом (проверено эмпирически).
Связанные ресурсы:
- Публичная документация Devprom: docs.myalm.ru
- Раздел про управление пожеланиями: artsaterra.myalm.ru/docs/8835.html
0. Базовое
- Хост:
https://<host>/pm/<project-slug>/api/latest - Аутентификация: заголовок
Devprom-Auth-Key: <hex>(личный API-ключ пользователя) - Content-Type:
application/json - Ответ: HTTP 200 всегда, ошибки валидации приходят в теле как
{"error":"…"} - PATCH не поддерживается — HTTP 405. Обновление только через PUT.
- Успешный ответ на создание: иногда возвращается как объект, иногда — как массив с одним элементом. Учитывать оба случая.
⚠ Критично: сервер молча отбрасывает незнакомые поля
Devprom REST API не возвращает ошибку, если имя поля в теле POST
не соответствует схеме сущности. Поле просто игнорируется, запись
создаётся с остальными полями, HTTP 200, UID возвращается.
Следствие: ответ POST нельзя считать подтверждением, что данные
сохранены. Успешный HTTP 200 + валидный JSON с UID означают только
что запись появилась, но часть полей может быть потеряна.
Правило: после КАЖДОГО POST на /issue/items (и любой другой
сущности, где критично содержимое) делать контрольный GET и глазами
или ассертом проверять реально сохранённые значения. Минимум:
code, text = call("GET", f"issue/items/{new_id}")
g = json.loads(text)
assert g["UID"].startswith("U-"), "неверный префикс UID"
assert len(g.get("Description","")) > 100, "тело пожелания пустое"
# опционально: проверить Caption, Priority.Id, Function.Id, Company.Id
Известные «тихие ловушки»:
ContentвместоDescriptionв теле POST на/issue/items→ поле игнорируется, запись создаётся с пустым телом.Type: {"Id":""}при POST на/request/items→ игнорируется, сервер ставитType=397(Доработка).Requirementпри POST на/issue/items→ игнорируется (привязку делать через PUT или в UI).
1. Пожелания vs Заявки — КРИТИЧНО
В официальной схеме Devprom это две разные сущности с разными
ReferenceName (см. таблицу выше):
issue(Пожелание) — сущность из строки 45. Создаётся без типа, UID с префиксомU-. В UI живёт в разделе «Пожелания» (/module/requirements/issues).request(Доработка) — сущность из строки 18. Создаётся с обязательным типом (Доработка / Ошибка), UID с префиксомI-. В UI живёт на доске заявок (/issues/board).
| Логический класс | Эндпоинт | Префикс UID | Поле Type | UI-раздел |
|---|---|---|---|---|
Пожелание (issue) |
/issue/items |
U- |
пусто | /module/requirements/issues |
Доработка (request) |
/request/items |
I- |
397 (Доработка) / 398 (Ошибка) | /issues/board |
Проверено эмпирически: GET на /issue/items/{id} и /request/items/{id}
возвращает одну и ту же запись (разные виды на один ресурс — внутренне
это один класс pm_ChangeRequest). Разница проявляется при POST — сервер
применяет разную логику автозаполнения в зависимости от эндпоинта.
Почему попасть в «Доску пожеланий» можно только через /issue/items
Проверено эмпирически: /request/items при POST всегда принудительно
проставляет Type=397 (Доработка), даже если передать Type: null,
Type: {} или Type: {"Id":""}. Все варианты PUT тоже бессильны — сервер
восстанавливает 397. Подтверждено на 8 вариантах тела.
Поэтому для создания «чистого» Пожелания (с пустым Type и префиксом U-)
используется эндпоинт именно сущности issue — POST на /issue/items.
2. Алгоритм создания Пожелания (рабочий рецепт)
Один POST на одно Пожелание. Без PUT, без привязки к требованиям.
post_body = {
"Caption": "<заголовок>",
"Description": "<html-тело>", # ← именно Description, НЕ Content
"Priority": {"Id": "2"}, # 1=Критично, 2=Высокий, 3=Обычный
"Author": {"Id": "<issueauthor.id>"},
"Function": {"Id": "<feature.id>"}, # подсистема (группировка)
"Company": {"Id": "<company.id>"}, # опционально: клиент-источник
}
# POST {BASE}/issue/items → {UID: "U-xxxx", Id: "xxxx", ...}
# ⚠ ОБЯЗАТЕЛЬНЫЙ контрольный GET — сервер может молча отбросить поля
code, text = call("GET", f"issue/items/{new_id}")
g = json.loads(text)
assert g["UID"].startswith("U-"), f"префикс не U-: {g['UID']}"
assert len(g.get("Description","")) > 100, "тело пожелания пустое"
Поля Requirement и RequirementDocument в теле не передаются:
привязка к документу требований — задача пользователя в UI, не API.
На этапе создания Пожелания она и не нужна — заказчик подтверждает
пожелания, формализует требования и уже потом вручную связывает одно
с другим.
Примечание для других сценариев. Если всё-таки нужно привязать Пожелание к существующему требованию из API (например, массовая миграция из внешней системы), это делается вторым шагом через
PUT /issue/items/{id}с тем же телом +Requirement.Id— в одном POST эти поля молча игнорируются. Для режима «Пожелания из совещания» этот путь не нужен.
Retry-политика
Egress-прокси периодически роняет запросы с HTTP 502/503/504 («DNS cache overflow»). Всегда оборачивать вызов в цикл retries=3 с sleep(2..3). Это не связано с Devprom — лечится только ретраями.
3. Поля Пожелания — полный справочник
| Поле | Тип / формат | Обязательность | Комментарий |
|---|---|---|---|
Caption |
string | обязательно | Заголовок пожелания |
Description |
HTML-string | обязательно | Тело пожелания. Имя поля — Description, не Content. Эмпирически: Content на /issue/items при POST молча игнорируется (принимается, но не сохраняется). В публичной документации (/docs/8835.html) упомянуто поле Content — это относится к /request/items и/или документации в целом устаревшее; для /issue/items используйте только Description. Разрешённые теги HTML: <p> <b> <ul> <ol> <li> <a> <blockquote> <code>. После POST обязательно делать GET и проверять len(Description) > 100 — сервер не возвращает ошибку при отброшенном поле. |
Priority.Id |
"1" / "2" / "3" | по смыслу | 1=Критично, 2=Высокий, 3=Обычный |
Author.Id |
issueauthor.id | обязательно | Автор пожелания. Справочник инстанс-уровня. |
Function.Id |
feature.id | рекомендовано | Группировка по подсистемам (создаются через /feature/items) |
Company.Id |
company.id | опционально | Клиент-источник пожелания. Принимается в POST напрямую. |
Requirement.Id |
requirement.id | не передавать в режиме Пожелания из совещания | Привязка к документу требований — задача пользователя в UI. Для других сценариев (миграция) — только через отдельный PUT после POST. |
RequirementDocument |
— | — | Не передавать, заполняется сервером автоматически по родителю Requirement |
Type.Id |
requesttype.id / пусто | НЕ передавать для пожелания | Любая попытка обнулить через API бесполезна; если передать — получится «Заявка» с префиксом I- |
4. Удаление
| Эндпоинт | DELETE работает? | Поведение |
|---|---|---|
DELETE /issue/items/{id} |
ДА — универсальный | HTTP 200, запись пропадает. Работает для ЛЮБОЙ записи — и для U- (созданных через /issue/items), и для I- (созданных через /request/items). Сущности issue и request указывают на один класс pm_ChangeRequest в БД, но DELETE разрешён только на пути issue/items. |
DELETE /request/items/{id} |
НЕТ | HTTP 200 с {"error":"Unable access entity"}, запись не удаляется. Сервер возвращает эту ошибку даже для записей, созданных через /request/items. |
DELETE /requirement/items/{id} |
Не гарантировано | Возвращает HTTP 200 с {"error":"Unable access entity"}, но GET после этого иногда показывает запись пустой (UID='', Caption=''). Эффект — неявное удаление / повреждение записи. Использовать с осторожностью. |
Практический вывод: для удаления любой записи Request/Issue —
всегда DELETE /issue/items/{id}, независимо от того, как она была создана.
5. Справочные эндпоинты (read-only для нашего ключа)
| Эндпоинт | Назначение |
|---|---|
/requesttype/items |
Типы заявок: Доработка, Ошибка |
/priority/items |
Приоритеты |
/feature/items |
Подсистемы/функции (имя "feature", не "function"!) |
/issueauthor/items |
Авторы пожеланий (инстанс-справочник) |
/user/items |
Пользователи проекта |
/company/items |
Компании-клиенты |
/requirement/items |
Требования и документы требований |
/state/items |
Состояния |
6. Что НЕ работает через API (заблокировано политикой прав)
| Операция | Ответ API | Обход |
|---|---|---|
POST /issueauthor/items |
HTTP 200 + {"error":"Lack of permissions to create object of IssueAuthor"} |
Только UI: /pm/<project>/issueauthor или inline-форма в карточке пожелания |
POST /user/items |
То же | Только UI |
DELETE /request/items/{id} |
{"error":"Unable access entity"} |
Не препятствие: удалять через DELETE /issue/items/{id} — он работает для любой записи Request (см. раздел 4). |
Пытаться обойти через write-only ключ проекта, api/v1, api/v2, инстанс-путь без /pm/<project>/ — бесполезно, все варианты дают тот же отказ.
7. Создание документа требований
⚠️ В режиме «Пожелания из совещания» этот путь НЕ используется. Структуру документов требований (
requirement, строка 92 таблицы сущностей) выстраивает владелец проекта/аналитик вручную через UI Devprom — постепенно, по мере формализации требований, согласованных с заказчиком. Привязку Пожеланий (issue) к требованиям пользователь тоже делает вручную в UI. Режим извлечения пожеланий в эту структуру не вмешивается. Раздел оставлен для справки — на случай других задач (миграция требований, импорт из внешней системы и т.п.).
POST /requirement/items
body = {
"Caption": "Корневой документ",
"Content": "<p>описание</p>",
# "ParentPage": {"Id": "..."} # если создаём подстраницу
}
Корневой документ — без ParentPage. Подстраница — с ParentPage.Id = <id_корня>. UID корневых документов присваивается по правилам шаблона проекта (например, О-1, R-35).
8. Attachment (приложить файл)
POST /attachment/items
body = {
"FileExt": "transcript.txt",
"ObjectId": "<request.id>",
"ObjectClass": "Request", # именно Request — общий класс для issue и request
"File": "<base64 содержимого>",
}
9. Альтернативные и несуществующие эндпоинты
Тестировались, но возвращают {"error":"Unknown entity: ..."}:
/userwish/items,/wish/items,/userrequest/items,/suggestion/items/admin/request/items,/api/latest/admin/request/items/pmcustomclass/items,/customclass/items,/class/items
Существующие служебные варианты:
/api/v1/request/items,/api/v2/request/items— принимают POST, но принудительная логикаType=397та же, что на/api/latest/request/items; использовать не нужно.
Примечание: эндпоинт
/issue/items— не алиас/request/items, а отдельная сущностьissue(Пожелание) из таблицы сущностей Devprom, строка 45. Под капотом они указывают на один и тот же классpm_ChangeRequest, но серверная логика автозаполнения при POST у них разная (см. раздел 1).
10. Порядок подготовки проекта для загрузки пожеланий
Граница ответственности: структуру проекта готовит человек через UI, пожелания загружает скрипт через API. Скрипт не создаёт Company, Feature, документы требований, IssueAuthor — только читает их.
Делается вручную через UI (один раз на проект, силами аналитика)
- Company для каждого клиента, который генерирует пожелания.
- Пример: «АРД» с доменом
alreadycom.ru.
- Пример: «АРД» с доменом
- Feature (подсистемы) — 3–5 на проект по подсистемам целевой
конфигурации. Можно создать и скриптом (
POST /feature/items) — наfeatureограничений API нет, но обычно удобнее через UI.- Пример для КА 2.5: «НСИ и администрирование», «Продажи», «Склад», «Казначейство», «Производство».
- IssueAuthor для представителей заказчика — если нужно, чтобы автором пожелания был сам клиент, а не аналитик. Только через UI.
- Документы требований — структуру требований клиент/аналитик выстраивает постепенно, по мере работы над проектом. Режим извлечения Пожеланий в неё не вмешивается.
Делается скриптом через API (каждое новое совещание)
- Цикл по Пожеланиям — для каждого: один POST
/issue/itemsс полями Caption, Content, Priority, Author, Function и опционально Company.Requirementне передаётся. - GET
/issue/items/{id}— верификация, что UID начинается наU-. - Привязка Пожеланий к требованиям — вне скрипта, это ручная работа пользователя в UI, когда требования появятся и согласованы с заказчиком.
11. URL-схема Devprom UI
Прямые ссылки на интерфейс — для отчётов пользователю и связывания сущностей между системами.
| Что | URL-формат |
|---|---|
| Карточка артефакта (любой префикс: U-, I-, R-, T-, TS- и т.д.) | https://<host>/pm/<project>/<UID> |
| Список Пожеланий | https://<host>/pm/<project>/module/requirements/issues |
| Доска Заявок (Доработки/Ошибки) | https://<host>/pm/<project>/issues/board |
| Документы требований | https://<host>/pm/<project>/module/requirements |
Карточка по UID — самый универсальный способ дать прямую ссылку. UID сам определяет тип артефакта, никакая «секция» в URL не нужна.
Проверено эмпирически: ссылки с подразумеваемой «секцией»
(/pm/<project>/issues/<UID>, /pm/<project>/requests/<UID> и т.п.)
возвращают 404. Работает только /pm/<project>/<UID>.
Пример:
https://artsaterra.myalm.ru/pm/test-api-claude/U-6316
Appendix — примеры curl
Создание пожелания (как в документации, с Type=Доработка)
curl -X POST \
-H "Devprom-Auth-Key: <KEY>" -H "Content-Type: application/json" \
https://<host>/pm/<proj>/api/latest/request/items \
-d '{"Caption":"Новая доработка","Content":"<p>Описание</p>","Type":{"Id":"397"}}'
# → UID=I-xxxx, Type=Доработка
Создание пожелания без типа (рекомендуемый путь)
curl -X POST \
-H "Devprom-Auth-Key: <KEY>" -H "Content-Type: application/json" \
https://<host>/pm/<proj>/api/latest/issue/items \
-d '{"Caption":"Пожелание","Description":"<p>Тело</p>","Priority":{"Id":"2"},"Author":{"Id":"1"},"Function":{"Id":"190"},"Company":{"Id":"146"}}'
# → UID=U-xxxx, Type=пусто
# ⚠ После создания — GET и проверить len(Description) > 100
Привязка к документу требований (не нужна в режиме «Пожелания из совещания»)
Используется только для миграционных сценариев:
curl -X PUT \
-H "Devprom-Auth-Key: <KEY>" -H "Content-Type: application/json" \
https://<host>/pm/<proj>/api/latest/issue/items/6179 \
-d '{"Caption":"Пожелание","Description":"<p>Тело</p>","Priority":{"Id":"2"},"Author":{"Id":"1"},"Function":{"Id":"190"},"Requirement":{"Id":"4378"}}'
Удаление
curl -X DELETE \
-H "Devprom-Auth-Key: <KEY>" \
https://<host>/pm/<proj>/api/latest/issue/items/6179
# → HTTP 200, []