FAQ по API

Как пользоваться API таск-менеджера /api/task: ключи, права, методы и готовые примеры, которые можно скопировать и выполнить.

Коротко
Адрес API — https://cms.dolinais.ru/api. Каждый запрос авторизуется ключом из раздела «Ключи для /api/task»: у ключа свой набор прав, поэтому один ключ можно дать боту на создание задач, а другой — только на чтение.

Быстрый старт

  1. Создайте ключ

    Личный кабинет → API → Ключи для /api/task: укажите название, срок действия и отметьте нужные права. Ключ показывается один раз — скопируйте его сразу.

  2. Проверьте ключ

    Запрос «кто я» вернёт владельца ключа и список его прав:

    Проверка ключа Bash
    # Ключ подставляется из переменной окружения — так он не попадёт в историю команд
    export DOLINAIS_TOKEN="dls_ваш_ключ"
    
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" \
         "https://cms.dolinais.ru/api/task/profile"
  3. Узнайте project_id

    Все операции с задачами привязаны к проекту — возьмите его id из списка своих проектов.

    Проекты, разделы и участники Bash
    # Кто я и что можно этому ключу
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" "https://cms.dolinais.ru/api/task/profile"
    
    # Мои проекты: id нужен для всех остальных запросов
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" "https://cms.dolinais.ru/api/task/projects?limit=100"
    
    # Разделы (колонки) проекта
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" \
         "https://cms.dolinais.ru/api/task/sections?project_id=81"
    
    # Кого можно назначить исполнителем
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" \
         "https://cms.dolinais.ru/api/task/users?project_id=81"
  4. Читайте и создавайте задачи

    Дальше — обычные запросы к задачам. Понадобится право task.tasks.read (чтение) или task.tasks.create (создание).

    Список задач с фильтрами Bash
    # Открытые задачи проекта, свежие сверху — сортировка задаётся на канбане
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" \
         "https://cms.dolinais.ru/api/task/tasks?project_id=81&status=open&limit=50"
    
    # Фильтры: раздел, исполнитель, поиск по заголовку, только изменённые после даты
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" \
         "https://cms.dolinais.ru/api/task/tasks?project_id=81&section_id=187&executor_id=5&search=договор&updated_since=1790000000"
    
    # Подзадачи конкретной задачи
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" \
         "https://cms.dolinais.ru/api/task/tasks?project_id=81&parent_id=1793396105504"
    
    # Одна задача
    curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" \
         "https://cms.dolinais.ru/api/task/task?id=1793396105504"

Авторизация

Ключ передаётся в заголовке запроса. Cookie и сессии личного кабинета API не использует, поэтому запросы можно отправлять с сервера, из скрипта или из мобильного приложения.

Заголовок Когда использовать
Authorization: Bearer <ключ> Основной способ, стандарт для REST-клиентов.
X-Api-Token: <ключ> Если клиент не умеет задавать Authorization.
Не передавайте ключ в URL. Параметры запроса попадают в логи серверов и прокси, а заголовок — нет. В примерах ключ берётся из переменной окружения DOLINAIS_TOKEN.

Пример на JavaScript

Универсальная обёртка над fetch с разбором ошибок:

JavaScript
const API = 'https://cms.dolinais.ru/api/task';
const KEY = process.env.DOLINAIS_TOKEN; // ключ из /account/tokens

async function api(path, options = {}) {
  const response = await fetch(API + path, {
    ...options,
    headers: {
      'Authorization': 'Bearer ' + KEY,
      'Content-Type': 'application/json',
      ...(options.headers || {}),
    },
  });

  const data = await response.json();

  if (!response.ok) {
    // error_code: unauthorized | insufficient_scope | forbidden | rate_limited ...
    throw new Error(data.error_code + ': ' + data.error);
  }

  return data;
}

const { tasks, total } = await api('/tasks?project_id=81&status=open&limit=20');
console.log('Открытых задач:', total);

Права ключа

Права выдаются при создании ключа и меняются в любой момент — сам ключ при этом не меняется. Всего 8 прав, плюс «Полный доступ» (*).

Право Что открывает
task.projects.read Просмотр проектов и разделов Проекты и разделы
task.tasks.read Просмотр задач и карточки задачи Задачи
task.tasks.create Создание задач Задачи
task.tasks.update Изменение задачи (заголовок, описание, исполнитель, приоритет, срок) Задачи
task.tasks.move Перемещение задачи между разделами Задачи
task.tasks.delete Удаление задачи Задачи
task.history.read Просмотр истории задачи История
task.users.read Просмотр участников проекта Участники
  • Любое право task.* открывает список проектов и разделов (task.projects.read): без project_id остальные запросы не выполнить. В списке — только проекты, где вы участвуете.
  • Права ключа — первый уровень доступа. Второй — ваши права в самом проекте: наблюдатель не сможет создать задачу, даже если у ключа есть право task.tasks.create.
  • Ключ из раздела «Ключи доступа» (account.accessToken) — старый ключ аккаунта: он работает с полным доступом и не имеет настроек прав.

Методы

Метод Маршрут Право Параметры
GET /task/profile любое task.* —
GET /task/projects task.projects.read limit, offset
GET /task/sections task.projects.read project_id
GET /task/users task.users.read project_id
GET /task/tasks task.tasks.read project_id, status (all/open/completed), section_id, executor_id, search, parent_id, include_subtasks, updated_since, limit (≤200), offset
POST /task/tasks task.tasks.create project_id, title (обязательны), comment, section_id, executor_id, priority (1–3), time_limit, date_start
GET /task/task task.tasks.read id
POST /task/task task.tasks.update id + любые из title, comment, executor_id, priority, time_limit, date_start, progress, completed
POST /task/move task.tasks.move id, section_id
POST /task/delete task.tasks.delete id
GET /task/history task.history.read task_id, limit (≤500)

Маршруты указаны относительно https://cms.dolinais.ru/api. Изменяющие операции выполняются только методом POST.

Примеры запросов

Создание задачи

POST /task/tasks Bash
curl -s -X POST "https://cms.dolinais.ru/api/task/tasks" \
     -H "Authorization: Bearer $DOLINAIS_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
           "project_id": 81,
           "title": "Проверить договор",
           "comment": "Срок — до пятницы",
           "priority": 3,
           "executor_id": 5,
           "time_limit": "2027-01-15"
         }'
Ответ Ответ 201
{
  "code": 201,
  "success": true,
  "task": {
    "task_id": 1793396105504,
    "project_id": 81,
    "section_id": 187,
    "section_title": "В работе",
    "title": "Проверить договор",
    "comment": "Срок — до пятницы",
    "executor_id": 5,
    "executor_name": "Иван Петров",
    "priority": 3,
    "progress": 0,
    "completed": false,
    "time_limit": 1800057600,
    "time_limit_date": "2027-01-15T00:00:00+03:00",
    "created_at_date": "2026-10-31T00:55:00+03:00"
  }
}

Изменение, перемещение, история и удаление

POST /task/task, /task/move, /task/history, /task/delete Bash
# Изменение: только переданные поля, остальные не трогаются
curl -s -X POST "https://cms.dolinais.ru/api/task/task?id=1793396105504" \
     -H "Authorization: Bearer $DOLINAIS_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"title": "Проверить договор (финал)", "priority": 2, "progress": 50}'

# Перемещение в другой раздел того же проекта
curl -s -X POST "https://cms.dolinais.ru/api/task/move?id=1793396105504&section_id=221" \
     -H "Authorization: Bearer $DOLINAIS_TOKEN"

# История изменений: кто, что и когда менял
curl -s -H "Authorization: Bearer $DOLINAIS_TOKEN" \
     "https://cms.dolinais.ru/api/task/history?task_id=1793396105504&limit=100"

# Удаление
curl -s -X POST "https://cms.dolinais.ru/api/task/delete?id=1793396105504" \
     -H "Authorization: Bearer $DOLINAIS_TOKEN"

Выгрузка задач страницами

За один запрос возвращается не больше 200 задач, поэтому полную выгрузку делают циклом по limit/offset. Пример использует $api из PHP-клиента ниже.

PHP
<?php
// Полная выгрузка задач проекта страницами по 200 (лимит API).
$offset = 0;
$all = [];

do {
    $page = $api->request('GET', '/tasks?project_id=81&limit=200&offset=' . $offset);
    $all = array_merge($all, $page['tasks']);
    $offset += 200;
} while (count($page['tasks']) === 200 && $offset < $page['total']);

echo 'Задач выгружено: ' . count($all);

Готовые клиенты

Мини-клиенты без зависимостей: скопируйте и подставьте свой ключ. Для PHP достаточно curl, для Python — requests.

PHP

PHP 8+ PHP
<?php
declare(strict_types=1);

/**
 * Мини-клиент /api/task: один ключ, один запрос — без зависимостей.
 */
final class TaskApiClient
{
    public function __construct(
        private string $token,
        private string $base = 'https://cms.dolinais.ru/api/task'
    ) {
    }

    /** @return array<string, mixed> */
    public function request(string $method, string $path, ?array $body = null): array
    {
        $curl = curl_init($this->base . $path);
        curl_setopt_array($curl, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST  => $method,
            CURLOPT_TIMEOUT        => 15,
            CURLOPT_HTTPHEADER     => [
                'Authorization: Bearer ' . $this->token,
                'Content-Type: application/json',
            ],
        ]);

        if ($body !== null) {
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body, JSON_UNESCAPED_UNICODE));
        }

        $raw = curl_exec($curl);
        $status = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
        curl_close($curl);

        $data = json_decode((string) $raw, true);

        if (!is_array($data)) {
            throw new RuntimeException('Ответ API не JSON (HTTP ' . $status . ')');
        }

        if ($status >= 400) {
            throw new RuntimeException($data['error_code'] . ': ' . $data['error']);
        }

        return $data;
    }
}

$api = new TaskApiClient(getenv('DOLINAIS_TOKEN'));

$projects = $api->request('GET', '/projects');
$projectId = (int) $projects['projects'][0]['id'];

$task = $api->request('POST', '/tasks', [
    'project_id' => $projectId,
    'title'      => 'Проверить договор',
    'priority'   => 3,
    'time_limit' => '2027-01-15', // строка или unix-время
]);

echo $task['task']['task_id'];

Python

Python 3 Python
import os
import requests

BASE = 'https://cms.dolinais.ru/api/task'
HEADERS = {'Authorization': f"Bearer {os.environ['DOLINAIS_TOKEN']}"}

# Список открытых задач проекта
page = requests.get(
    f'{BASE}/tasks',
    params={'project_id': 81, 'status': 'open', 'limit': 20},
    headers=HEADERS,
    timeout=15,
)

page.raise_for_status()
data = page.json()

for task in data['tasks']:
    print(task['task_id'], task['title'], task['executor_name'])

Ошибки и коды

Ответ всегда JSON. При ошибке приходят HTTP-статус, короткий текст и машинный error_code — по нему удобно строить обработку.

Формат ошибки Ошибка
{
  "code": 403,
  "success": false,
  "error": "Недостаточно прав у ключа",
  "error_code": "insufficient_scope",
  "required_scope": "task.tasks.create"
}
Код Причина и что делать
401 unauthorized Ключ не передан, неверен, отключён или удалён. Проверьте его в списке ключей.
403 insufficient_scope У ключа нет нужного права; в ответе есть required_scope. Добавьте право — перевыпускать ключ не нужно.
403 forbidden Права ключа есть, но у вас как у пользователя нет доступа к этому проекту или задаче.
404 not_found Задачи нет или она уже удалена; также — неизвестный маршрут.
405 method_not_allowed Изменяющие операции — только POST, чтение — только GET.
422 invalid_* Параметры: invalid_project, invalid_task, invalid_title, invalid_section, invalid_executor, nothing_to_update.
429 rate_limited Лимит частоты; подождите Retry-After секунд.
500 server_error Внутренняя ошибка CMS. Повторите позже; если повторяется — сообщите администратору.

Лимиты

Что ограничено Лимит
Все запросы с одного IP 120 в минуту (общий лимит /api)
Чтение по одному ключу 300 в минуту
Создание и изменение по одному ключу 60 в минуту

Если нужно много данных, выгружайте страницами по 200 записей и используйте фильтр updated_since вместо частых полных выгрузок.

Безопасность

  • Ключ — это пароль. Храните его в переменных окружения или в секретах CI, не в коде и не в git.
  • Отдельный ключ на каждую интеграцию: отзыв одного не затрагивает остальные.
  • Давайте минимальные права: отчёту на чтение не нужен task.tasks.delete.
  • Ставьте срок действия (30/90/180/365 дней) — просроченный ключ перестаёт работать сам.
  • В базе хранится только SHA-256-хеш ключа, а в списке видно лишь его начало — по дампу базы ключ не восстановить.
  • Следите за колонкой «Использован»: время последнего запроса и IP помогают заметить чужое использование.
  • Подозрение на утечку — удалите ключ: интеграция сразу получит 401.

Частые вопросы

Приходит 403 insufficient_scope. Что делать?

У ключа нет права, которое требует метод. В теле ответа есть required_scope — откройте список ключей, нажмите «Изменить» и отметьте это право. Сам ключ останется прежним.

Права есть, но проект или задача «не найдены». Почему?

Доступ проверяется дважды: по правам ключа и по вашим правам в проекте. Если вы не участник проекта (или у вас точечный доступ к отдельным задачам), API вернёт 403 forbidden либо не покажет задачу в списке. Проверить можно по полю can_edit в GET /task/projects.

Откуда взять project_id и task_id?

project_id — из GET /task/projects. task_id — из списка задач или из ответа на создание задачи. Это глобальный идентификатор; он же используется во всех запросах с параметром id.

Как создать подзадачу через API?

Подзадачи (чек-лист в карточке задачи) через API пока не создаются: POST /task/tasks создаёт обычную задачу верхнего уровня. Подзадачи и их отметки ведутся в интерфейсе задачи.

В каком виде приходят даты и как передавать срок?

В ответах — unix-время (time_limit, created_at) и готовая ISO-строка с часовым поясом сервера (time_limit_date). Принимается и то, и другое: число-метка времени или строка "2027-01-15" / "2027-01-15 18:00".

Чем «Ключи для /api/task» отличаются от «Ключей доступа»?

«Ключи доступа» — один старый ключ на аккаунт (account.accessToken) с полным доступом. Он продолжает работать, но не даёт гибких прав и отзыва. Для интеграций лучше выпускать ключи в «Ключи для /api/task»: их может быть много, у каждого свои права и срок действия.

Где посмотреть машинное описание API?

OpenAPI/Swagger — /api/doc. Там перечислены все методы /api/task с параметрами и правами.

Можно ли получать события CMS, а не опрашивать API?

Да, для исходящих уведомлений есть модуль Webhook (REST Hook): подписки на события задач с HMAC-подписью. Настроить — /webhook.