API Quevell состоит из тех же методов, которыми пользуется интерфейс продукта, открытых для интеграций. Он принимает и отдает JSON и работает только от имени сервисного аккаунта: у людей личных токенов нет. Ниже описано, как к нему обращаться и что он возвращает, а в конце перечислены методы, которые можно вызывать.
Адрес
https://<ключ>.quevell.com/api
<ключ> - это ключ вашей компании, тот же, что в адресной строке продукта. Обращайтесь к адресу своей компании: токен выдан одной компанией, и на адресе другой компании запрос отклоняется с кодом auth.tenant_mismatch (403). Номера версии в адресе нет.
Вход
В каждом запросе передается токен сервисного аккаунта:
Authorization: Bearer qvl_...
Как выпустить токен, как сузить его права и как получить временный токен через OAuth-клиент, описано в статье Сервисные аккаунты. Запрос без токена, с неизвестным, истекшим или отозванным токеном отклоняется с ответом 401 auth.required. Если токену не хватает прав на действие, ответ будет 403 authorization.forbidden.
Ответы и ошибки
Успешный ответ содержит сам объект, список или страницу, без обертки. Ошибка всегда приходит в одном и том же формате:
{
"code": "concurrency.version_conflict",
"message": "Issue was modified concurrently",
"status": 409,
"path": "/api/issues/6f1c.../transitions/...",
"correlationId": "9b2e...",
"timestamp": "2026-09-17T08:00:00Z",
"details": {}
}
code: неизменный код, по нему и выбирайте, как обработать ошибку.message: предложение для человека, по-английски. Оно может измениться в любой день, поэтому наmessageне опирайтесь.details: подробности, если они есть: ошибки полей вdetails.fieldErrors, время ожидания вdetails.retryAfterSeconds.correlationId: номер запроса. Он же приходит в заголовкеX-Correlation-Idкаждого ответа; укажите его, когда пишете в поддержку.
Частые коды:
| Код | Статус | Что значит |
|---|---|---|
request.malformed | 400 | тело или параметр не читаются: неверный JSON, UUID, число |
request.validation | 400 | поле не прошло проверку, подробности в details.fieldErrors |
request.unknown_parameter | 400 | параметр строки запроса, которого метод не знает; список допустимых в сообщении |
query.syntax | 400 | ошибка в запросе QQL |
auth.required | 401 | нет токена или он не действует |
authorization.forbidden | 403 | не хватает прав |
auth.tenant_mismatch | 403 | токен другой компании |
*.not_found | 404 | объекта нет или он вам не виден |
concurrency.version_conflict | 409 | устаревшая версия, см. Версии и конфликты |
files.storage_quota_exceeded | 409 | вложения компании заняли весь объем по тарифу |
tenant.rate_limited | 429 | слишком частые вызовы, см. Лимиты |
tenant.record_quota_exceeded | 429 | исчерпан суточный лимит записей |
internal.error | 500 | сбой на нашей стороне; сообщите correlationId |
Модули добавляют свои коды в своем пространстве имен: note.*, sprint.*, identity.* и другие. Незнакомый код обрабатывайте по статусу.
Даты и время
Моменты времени приходят и принимаются в UTC, строкой ISO-8601 с Z на конце. Календарные дни, например срок задачи или день записи времени, передаются как год-месяц-день без времени. Часовой пояс сервера и человека на ответ не влияет: перевод в местное время остается за программой.
Страницы и курсор
Длинные списки отдаются страницами. Ответ содержит items и nextCursor, у части методов еще total. Следующую страницу просят тем же запросом с cursor=<nextCursor>; когда nextCursor пуст, страниц больше нет. Размер страницы задает limit, у каждого метода свой предел, он указан в справочнике. Номеров страниц и смещений нет.
Курсор привязан к порядку сортировки. Курсор, полученный при одном порядке, с другим отклоняется.
Поиск и QQL
Задачи по всем доступным проектам ищет GET /api/issues/search. В text передается либо обычный текст, либо запрос на QQL:
curl -G https://<ключ>.quevell.com/api/issues/search \
-H "Authorization: Bearer qvl_..." \
--data-urlencode 'text=project = OFFICE and status != Done order by updated desc' \
--data-urlencode 'mode=QUERY'
Без mode сервер сам решает, текст это или запрос, и сообщает решение в поле mode ответа; в интеграции лучше указывать mode=QUERY явно. Порядок задает ORDER BY внутри запроса, по умолчанию сначала недавно измененные. Сохраненный фильтр запускается параметром filterId.
Задачи, которые токен видеть не может, в ответ не попадают вовсе: их нет ни в items, ни в total.
Версии и конфликты
У изменяемых объектов есть поле version. Изменяя объект, передайте версию, которую вы прочитали, в expectedVersion. Если кто-то успел изменить объект раньше, ответ будет 409 concurrency.version_conflict или доменный код с version_conflict в конце. Перечитайте объект и решите, применять ли изменение снова.
Повтор того же изменения задачи ничего не меняет и нового события не пишет. А вот создание не идемпотентно: повторенный POST создаст второй объект. Если запрос на создание оборвался, сначала проверьте, создался ли объект.
Лимиты
| Что считается | Лимит | Ответ при превышении |
|---|---|---|
| вызовы одного сервисного аккаунта | 120 в минуту | 429 tenant.rate_limited |
| вызовы всех сервисных аккаунтов компании | 600 в минуту | 429 tenant.rate_limited |
| записи одного сервисного аккаунта | 10 000 в сутки | 429 tenant.record_quota_exceeded |
| записи всех сервисных аккаунтов компании | 50 000 в сутки | 429 tenant.record_quota_exceeded |
| выдача токенов OAuth-клиенту | 10 в минуту на клиента, 30 с одного адреса | 429 oauth.rate_limited |
| объем вложений компании | по тарифу компании | 409 files.storage_quota_exceeded |
Как считается:
- Минута: календарная минута по UTC, не скользящее окно. Считается каждый запрос с действующим токеном, в том числе отклоненный из-за прав.
- Сутки: календарные сутки по UTC. Запись означает каждое событие, которое аккаунт оставил в журнале: создание и изменение задачи, комментарий, запись времени, а также скачивание вложения и выгрузка CSV. Чтение без события запись не расходует.
- Все токены одного аккаунта, выпущенные вручную и выданные OAuth-клиентом, расходуют один общий лимит.
В каждом ответе 429 сказано, сколько ждать: в заголовке Retry-After и тем же числом в details.retryAfterSeconds. Для минутного лимита это секунды до новой минуты, для суточного время до полуночи по UTC.
HTTP/1.1 429 Too Many Requests
Retry-After: 17
{"code":"tenant.rate_limited","status":429,"details":{"retryAfterSeconds":17},...}
Подождите указанное время и повторите запрос. Повторять раньше бесполезно, такие запросы тоже считаются. При 409 files.storage_quota_exceeded в details приходят usedBytes и limitBytes.
Примеры
Создать задачу:
curl -X POST https://<ключ>.quevell.com/api/projects/<projectId>/issues \
-H "Authorization: Bearer qvl_..." \
-H "Content-Type: application/json" \
-d '{"summary": "Заменить картридж", "description": "Принтер на третьем этаже"}'
Перевести задачу по статусу: сначала узнать доступные переходы, затем выполнить нужный с версией задачи.
curl https://<ключ>.quevell.com/api/issues/<issueId>/transitions \
-H "Authorization: Bearer qvl_..."
curl -X POST https://<ключ>.quevell.com/api/issues/<issueId>/transitions/<transitionId> \
-H "Authorization: Bearer qvl_..." \
-H "Content-Type: application/json" \
-d '{"expectedVersion": 3}'
Добавить комментарий:
curl -X POST https://<ключ>.quevell.com/api/issues/<issueId>/comments \
-H "Authorization: Bearer qvl_..." \
-H "Content-Type: application/json" \
-d '{"body": "Картридж заменен"}'
Справочник методов
Список собран из кода продукта и сверяется с ним при каждой сборке, поэтому в нем нет методов, которых уже не существует. Методы входа, администрирования компании и вспомогательные методы экранов сюда не входят: их форма меняется вместе с интерфейсом. Право в описании требуется и от роли аккаунта, и от токена; просмотр проекта требуется везде и не указан.
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Возвращает задачи по списку ключей в keys (до 50); ключи несуществующих или недоступных задач молча пропускаются |
PUT | / | Сохраняет поля задачи целиком: summary, description, issueTypeId и прочие. Право issue.edit, при устаревшем expectedVersion ответ 409 |
GET | / | Возвращает историю задачи в хронологическом порядке: кто, что и когда изменил, включая действия правил автоматизации |
GET | / | Возвращает чеклист задачи по порядку: пункты с отметкой выполнения, кто и когда отметил, и число выполненных |
POST | / | Добавляет пункт в конец чеклиста, текст в text до 500 символов. Право issue.edit, в ответе весь чеклист |
PUT | / | Меняет порядок пунктов чеклиста по списку itemIds; не названные пункты остаются после названных. Право issue.edit |
DELETE | / | Удаляет пункт из чеклиста задачи и возвращает оставшийся чеклист. Право issue.edit |
PUT | / | Меняет текст пункта (text) и/или отмечает его выполненным (done), запоминая, кто и когда отметил. Право issue.edit |
GET | / | Возвращает дочерние задачи на один уровень ниже; задачи, скрытые от вызывающего уровнем безопасности, молча пропускаются |
GET | / | Возвращает команды, участвующие в задаче, с признаком mine для команд, в которых состоит вызывающий |
PUT | / | Задает набор команд задачи списком teamIds; добавлять и убирать можно только команды, в которых вы состоите |
GET | / | Возвращает метки задачи в алфавитном порядке |
PUT | / | Заменяет метки задачи списком слов в names (до 30, каждая до 60 символов); новое слово становится меткой. Право issue.edit |
GET | / | Возвращает связи задачи в обоих направлениях; связи с задачами, которые вызывающий не видит, молча пропускаются |
POST | / | Связывает задачу с другой: typeId, issueKey и direction. Нужно право issue.edit на обе задачи |
DELETE | / | Удаляет связь задач и возвращает оставшиеся связи. Право issue.edit |
GET | / | Считает задачи под этой по категориям статусов, всего и по каждой дочерней; учитываются только видимые вызывающему |
PUT | / | Назначает задаче уровень безопасности securityLevelId или снимает его (null). Право issue.security.manage, при устаревшем expectedVersion ответ 409 |
GET | / | Возвращает переходы, доступные из текущего статуса задачи по ее рабочему процессу |
POST | / | Устаревший метод: переводит задачу в статус категории "готово". Право issue.transition, в теле expectedVersion |
POST | / | Выполняет переход статуса задачи, доступный из текущего статуса. Право issue.transition, в теле expectedVersion |
GET | / | Возвращает наблюдателей задачи с отображаемыми именами и датой начала наблюдения |
DELETE | / | Отписывает вызывающего от задачи: он перестает быть наблюдателем |
GET | / | Сообщает, наблюдает ли вызывающий за задачей |
POST | / | Делает вызывающего наблюдателем задачи |
GET | / | Возвращает задачу по UUID или ключу вида PROJ-12; прежний ключ задачи тоже находит ее |
GET | / | Возвращает задачи проекта от новых к старым, limit от 1 до 200 (по умолчанию 100); скрытые уровнем безопасности молча пропускаются |
POST | / | Создает задачу в проекте: обязательны summary и description, пропущенные поля берутся из значений по умолчанию проекта. Право issue.create |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Список полей, доступных в запросе QQL: тип, допустимые операторы, возможность сортировки и признак пользовательского поля |
GET | / | Те же подсказки значений, что и values, но каждая с пометкой: если имя спринта есть в нескольких проектах, рядом стоит ключ проекта; в запрос вставляется только имя |
GET | / | Подсказки значений для поля в запросе QQL: проекты и значения берутся только из проектов, доступных вызывающему |
GET | / | Поиск задач по всем доступным проектам: текст или запрос QQL через mode=QUERY, limit по умолчанию 40, максимум 1000, ответ items, nextCursor, total |
GET | / | Выгрузка CSV найденных задач по тем же критериям, что и поиск: limit по умолчанию 1000, максимум 10000 |
GET | / | Поиск задач внутри одного проекта с фильтрами и курсором: limit по умолчанию 40, максимум 100, задачи без доступа молча не попадают в ответ |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Список проектов, которые вызывающий может открыть, с датой последней активности и числом задач: issueCount всего и openIssueCount не в состоянии "Готово", считаются только задачи, видимые вызывающему; архивные проекты отдаются с archived=true |
POST | / | Создает проект с ключом и названием и конфигурацией по умолчанию, создатель становится администратором проекта: право projects.create |
DELETE | / | Безвозвратно удаляет проект, который уже в архиве: только администратор компании, expectedVersion передается в строке запроса |
PUT | / | Меняет название и ключ проекта с expectedVersion, 409 при устаревшей версии: право project.access.manage, смена ключа только администратору компании |
POST | / | Переносит проект в архив и назначает дату окончательного удаления: право project.access.manage, expectedVersion в теле, 409 при устаревшей версии |
GET | / | Конфигурация проекта: поля, типы задач, тип задачи по умолчанию и значения полей по умолчанию для каждого типа |
PUT | / | Задает уровень безопасности задач для новых задач проекта, null снимает его: право issue.security.manage |
GET | / | Список уровней безопасности задач проекта с их доступами и числом закрытых ими задач: право issue.security.manage |
POST | / | Создает уровень безопасности задач с названием и доступами для пользователей, ролей проекта и групп: право issue.security.manage |
DELETE | / | Удаляет уровень безопасности задач, только если он не закрывает ни одной задачи: право issue.security.manage |
PUT | / | Полностью перезаписывает название и доступы уровня безопасности задач: право issue.security.manage, expectedVersion, 409 при устаревшей версии |
GET | / | Участники проекта с именами и ролями: limit по умолчанию 50, максимум 200, ответ items, nextCursor, total |
PUT | / | Пакетно назначает, меняет или снимает роли до 500 участников за один вызов: право project.access.manage |
GET | / | Группы, у которых есть роль в проекте, с названиями и ролями |
DELETE | / | Снимает роль группы в проекте, личные роли ее участников сохраняются: право project.access.manage |
PUT | / | Назначает группе роль в проекте: viewer, contributor или admin, право project.access.manage |
DELETE | / | Убирает участника из проекта: право project.access.manage, свою роль снять нельзя, последний администратор проекта остается |
PUT | / | Назначает пользователю роль в проекте: viewer, contributor или admin, право project.access.manage, свою роль менять нельзя |
POST | / | Возвращает проект из архива: право project.access.manage, expectedVersion в теле, 409 при устаревшей версии |
GET | / | Возвращает проект: {projectReference} принимает ключ проекта, прежний ключ или id |
GET | / | Число задач проекта по статусам, только среди задач, видимых вызывающему: {projectReference} принимает ключ проекта или id |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Список досок компании, видимых вызывающему, и доски по умолчанию для проектов; archived=true вернет архивные |
POST | / | Создает доску KANBAN или SCRUM по набору проектов projectIds или по запросу query, ровно одно из двух |
PUT | / | Назначает доску по умолчанию для проекта (boardId, null снимает); доска должна включать проект, право board.manage (или создатель доски) |
DELETE | / | Удаляет архивную доску вместе с колонками, фильтрами и спринтами, задачи остаются; право board.manage (или создатель доски) |
GET | / | Возвращает доску с колонками, карточками и дорожками; filters применяет быстрые фильтры по их id |
POST | / | Переносит доску в архив или возвращает из него по полю archived; доску по умолчанию архивировать нельзя, право board.manage (или создатель доски) |
GET | / | Бэклог доски в порядке ранга и открытые спринты с задачами и суммами оценок |
PUT | / | Заменяет колонки доски (columns, enforceWip); нужен expectedVersion, при устаревшей версии 409, право board.manage (или создатель доски) |
PUT | / | Кладет карточку issueId в колонку columnId без статуса, не меняя статус задачи; право issue.rank |
DELETE | / | Возвращает карточку в колонку, соответствующую статусу задачи; право issue.rank |
PUT | / | Заменяет быстрые фильтры доски (filters: name, query, до 20); нужен expectedVersion, 409 при устаревшей версии, право board.manage (или создатель доски) |
POST | / | Меняет порядок (ранг): ставит issueId перед beforeIssueId; нужен expectedVersion, 409 при устаревшей версии, право issue.rank |
PUT | / | Задает дорожки доски: mode и для QUERIES список lanes; нужен expectedVersion, 409 при устаревшей версии, право board.manage (или создатель доски) |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Отчет по спринту для SCRUM-доски: закрытые спринты с итогами и средняя скорость за три последних |
POST | / | Создает запланированный спринт на SCRUM-доске с name и необязательной goal; право board.manage (или создатель доски) |
GET | / | Текущий спринт задачи: активный, иначе запланированный; null, если задача не в открытом спринте |
GET | / | Все спринты задачи, включая закрытые, с названием доски |
PUT | / | Заменяет набор открытых спринтов задачи списком sprintIds; закрытые остаются, право issue.rank |
GET | / | Начатые спринты (активные и закрытые) на SCRUM-досках проекта, для диаграммы сгорания |
GET | / | Диаграмма сгорания спринта: число оставшихся задач по дням и идеальная линия |
POST | / | Закрывает активный спринт, незавершенные задачи можно перенести в спринт moveOpenTo; нужен expectedVersion, 409 при устаревшей версии, право board.manage (или создатель доски) |
GET | / | Задачи спринта, видимые вызывающему, с суммой оценок и затраченного времени |
POST | / | Добавляет задачу issueId в открытый спринт; задача может быть только в одном открытом спринте доски, право issue.rank |
DELETE | / | Убирает задачу из открытого спринта обратно в бэклог; право issue.rank |
POST | / | Запускает запланированный спринт с endsAt и необязательным startsAt; нужен expectedVersion, 409 при устаревшей версии, право board.manage (или создатель доски) |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Возвращает комментарии задачи в порядке добавления |
POST | / | Добавляет комментарий к задаче, текст в body до 10000 символов; упоминания в тексте запоминаются. Право comment.create |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Возвращает вложения задачи: имя файла, тип, размер, кто и когда приложил |
POST | / | Прикладывает файл к задаче (multipart, поле file, до 10 МиБ) в пределах объема, который разрешает план компании. Право attachment.create |
DELETE | / | Удаляет вложение из хранилища, история сохраняет имя файла. С правом attachment.delete только свои файлы, чужие: администратор проекта (project.access.manage) |
GET | / | Скачивает файл вложения; каждое скачивание записывается в историю как событие, повторные скачивания разрешены |
GET | / | Отдает миниатюру вложения-изображения (PNG, длинная сторона 256). Есть только у файлов, чьи байты оказались изображением; для прочих 404. Те же права, что у скачивания |
GET | / | Отдает оригинал изображения для просмотра: Content-Disposition: inline и тип по определенному формату, а не по заявленному. Не изображение отвечает 404. Те же права, что у скачивания |
| Метод | Адрес | Что делает |
|---|---|---|
PUT | / | Задает оценку originalEstimate и оставшееся время remainingEstimate строками вида "1w 2d 4h 30m"; нужен expectedVersion, 409 при устаревшей версии, право issue.edit |
GET | / | Учет времени по задаче: оценка, оставшееся время, затраченное время и все записи времени |
POST | / | Добавляет запись времени: spent строкой вида "2h 30m", необязательные spentOn и note; уменьшает оставшееся время, право work.log |
DELETE | / | Удаляет запись времени, оставшееся время не восстанавливается; право work.log, для чужой записи project.access.manage |
PUT | / | Исправляет запись времени: spent строкой длительности и note; право work.log, для чужой записи project.access.manage |
GET | / | Отчет по времени: минуты по авторам за дни с from по to (не больше года); без projectId нужно право компании reports.view |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Страницы базы знаний, связанные с задачей: только те, которые вызывающий может открыть |
GET | / | Дерево страниц базы знаний проекта при projectId (право project.view) или личного пространства вместе со страницами, открытыми вам другими; архивные страницы приходят с флагом archived |
POST | / | Создает страницу в базе знаний проекта (projectId, право note.edit) или в личном пространстве (personal); также title, body, parentId, draft, linkedIssueKeys |
GET | / | Ищет строку q в названии и тексте страниц проекта (projectId) или личного пространства; архивные страницы в результат не попадают |
DELETE | / | Удаляет страницу вместе с ревизиями, доступом к странице и связями с задачами; страницу с дочерними страницами удалить нельзя |
GET | / | Возвращает страницу с текстом, версией и признаком canEdit; без доступа к странице отвечает 403 |
PUT | / | Сохраняет title и body страницы с expectedVersion, при устаревшей версии 409; сохранение без изменения названия и текста не создает ревизию |
GET | / | Список доступа к странице: люди и группы с уровнем READ или EDIT |
PUT | / | Выдает человеку или группе доступ к странице или меняет его уровень; тело: subjectKind, subjectId, level; нужно право на изменение страницы |
DELETE | / | Отзывает доступ к странице у человека или группы и возвращает оставшийся список доступа |
POST | / | Переносит страницу в архив или возвращает из него вместе со всеми дочерними страницами; тело: archived |
POST | / | Создает копию страницы рядом с оригиналом: тот же текст, к названию добавляется "(копия)" |
GET | / | Связанные задачи страницы: ключ, название и статус каждой |
POST | / | Связывает страницу с задачей по ключу key; задача должна быть видна вызывающему |
DELETE | / | Убирает связь страницы с задачей и возвращает оставшиеся связанные задачи |
POST | / | Переносит страницу под другого родителя (parentId) или в другое пространство вместе с дочерними; нужен expectedVersion, при устаревшей версии 409 |
POST | / | Передает личную страницу с дочерними другому владельцу (ownerId); может текущий владелец страницы или администратор |
GET | / | Список ревизий страницы от новой к старой: версия, название, автор и время правки |
GET | / | Возвращает ревизию страницы с указанной версией вместе с названием и текстом |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Справочник типов полей, доступных в компании |
GET | / | Справочник полей компании без архивных, с обязательностью и значением по умолчанию |
GET | / | Справочник уровней иерархии компании, начиная с верхнего |
GET | / | Справочник типов задач компании без архивных, упорядоченный по уровням иерархии |
GET | / | Справочник типов связи между задачами без архивных, с прямой и обратной формулировкой |
GET | / | Справочник статусов, определенных в компании |
GET | / | Справочник рабочих схем компании |
GET | / | Метки компании по алфавиту; с параметром query только совпадающие по части названия |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Названия групп компании по алфавиту, для выбора группы в формах |
GET | / | Список людей компании: имя, состояние и тип учетной записи |
GET | / | Карточка человека: контакты, отсутствие, заместитель и заполненные поля профиля |
PUT | / | Меняет значения полей профиля человека, тело: объект из id поля и значения, пустое значение очищает поле; право people.edit |
GET | / | Все команды компании с числом участников и ролью вызывающего в каждой |
POST | / | Создает команду с name и description; вызывающий становится создателем команды |
GET | / | Команды, в которых состоит человек, и его роль в каждой |
DELETE | / | Удаляет команду и снимает ее со всех задач; может только создатель команды или администратор |
GET | / | Команда со списком участников и их ролями |
PUT | / | Меняет название и описание команды с expectedVersion, при устаревшей версии 409; может только создатель команды или администратор |
POST | / | Добавляет человека в команду (userId, role); может создатель команды, менеджер или администратор |
DELETE | / | Убирает человека из команды; выйти сам может любой, кроме создателя команды, других убирает создатель, менеджер или администратор |
PUT | / | Меняет роль участника команды (role); роль создателя команды изменить нельзя |
| Метод | Адрес | Что делает |
|---|---|---|
GET | / | Ваши личные фильтры и общие фильтры других людей, с текстом запроса и признаками mine и shared |
POST | / | Сохраняет фильтр: name, query и shared, чтобы сделать его общим фильтром; имя должно быть уникальным среди ваших фильтров |
DELETE | / | Удаляет фильтр; удалить может только тот, кто его сохранил |
PUT | / | Меняет name, query и shared фильтра с expectedVersion, при устаревшей версии 409; только автор фильтра |