Справка по API

Публичный REST API для интеграций и скриптов. Базовый URL: https://taskid.app/v1/api

Подключаете AI-ассистент (Claude, ChatGPT)? MCP-коннектор → проще и не требует вручную собирать HTTP-запросы.

Обзор

API принимает и отдаёт JSON. Тела запросов - application/json; charset=utf-8.

Даты - строки в формате ISO-8601 в UTC, без миллисекунд: 2026-04-18T12:34:56Z.

Идентификаторы - UUID v4, строки в каноническом формате.

API работает в паре с фоновой синхронизацией клиентов. Созданная через API задача появится в iOS/веб-интерфейсе после следующего sync-цикла (обычно пара секунд).

Аутентификация

Каждый запрос требует заголовок:

Authorization: Bearer tkd_xxxxxxxxxxxxxxxxxxxx

Токены создаются на странице API-токены.

Права (scope)
  • read - разрешены только GET-запросы.
  • write - разрешены GET и POST для задач, заметок, списков и групп.
  • write_notifications - изолированный scope только для отправки уведомлений через POST /v1/api/notifications. Не даёт доступа к задачам, заметкам и спискам - удобно выдавать интеграциям мониторинга и алертов.

При создании токена можно ограничить его конкретными списками - тогда запросы к другим спискам вернут 403.

Ошибки

Ошибки возвращаются со стандартными HTTP-кодами и JSON-телом вида:

{ "message": "list is not accessible by this token" }
Код Когда
400Некорректное тело запроса (нет title, невалидная дата).
401Нет заголовка Authorization или токен не найден / отозван / истёк.
403Не хватает scope (write для POST) или список недоступен токену.
404Списка не существует или он удалён.
429Превышен rate limit (касается отправки уведомлений). Заголовки Retry-After и X-RateLimit-* подскажут, через сколько секунд можно повторить.
500Ошибка на сервере - стоит повторить позже.

Группы

Получение групп

GET /v1/api/groups

Группа - контейнер для обычных списков. Сама она задач и записей не содержит, но позволяет объединять несколько списков под одной крышей. Токены с ограниченным доступом видят только те группы, в которых лежит хотя бы один из их разрешённых списков.

Требуемый scope
read
Query-параметры
Нет. Эндпоинт возвращает все видимые группы одним массивом - пагинация не предусмотрена.
Пример
curl -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/groups
Ответ 200 OK
{ "groups": Group[] }

Создание группы

POST /v1/api/groups
Требуемый scope
write (токен должен иметь доступ «Все списки»)
Тело запроса
ПолеТипОписание
namestring *Название группы. Обязательное поле, не пустое.
colorstring | nullHEX-цвет или имя токена темы. Опционально.
iconstring | nullИмя иконки (SF Symbol). Опционально.
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Работа", "icon": "briefcase" }' \
  https://taskid.app/v1/api/groups
Ответ 201 Created
{ "group": Group }

Получение одной группы

GET /v1/api/groups/:id
Требуемый scope
read
Ответ 200 OK
{ "group": Group }

Редактирование группы

PATCH /v1/api/groups/:id
Требуемый scope
write (all_lists)
Тело запроса - все поля опциональны, обновляются только те, что присутствуют
ПолеТипОписание
namestringНовое название. Пустая строка не допускается.
colorstring | nullHEX или имя токена темы. null - сбросить.
iconstring | nullИмя иконки (SF Symbol). null - сбросить.
archivedbooleanАрхивировать / вернуть из архива.
Пример
curl -X PATCH \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Рабочие проекты" }' \
  https://taskid.app/v1/api/groups/GROUP_ID
Ответ 200 OK
{ "group": Group }

Удаление группы

DELETE /v1/api/groups/:id

Мягкое удаление. Списки, которые входили в группу, останутся - после sync они отобразятся в корне (parent_id указывает на удалённую группу). Requires scope=write (all_lists).

Ответ 204 No Content
Тело пустое.

Списки

Получение списков

GET /v1/api/lists

Возвращает все списки, к которым у этого токена есть доступ. Архивированные списки тоже приходят - флаг archived.

Требуемый scope
read
Query-параметры
Нет. Пагинация не предусмотрена - возвращается весь видимый набор списков одним массивом.
Пример запроса
curl -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/lists
Ответ 200 OK
{
  "lists": [
    {
      "id":        "6f8a6f4e-9b0e-4a82-9f6b-2a3f1e4a5d1a",
      "parent_id": null,
      "name":      "Работа",
      "color":     "#0a84ff",
      "icon":      "briefcase",
      "archived":  false,
      "is_owner":  true,
      "is_shared": false
    }
  ]
}
Признаки общего/личного списка

Списками можно делиться (на сайте - кнопка «Поделиться»). В ответе одновременно приходят и собственные, и шаренные; различить помогают два булевых поля:

  • is_owner - true: вы владелец списка; false: участник чужого. Только владелец может редактировать сам список (имя, цвет, иконка, архивация, удаление, привязка к группе) - попытка участника даст 403. Содержимое (задачи и заметки) могут править оба.
  • is_shared - true: у списка есть участники (расшарен), независимо от вашей роли; false: сугубо личный.

В общих списках поля completed_user_id / deleted_user_id у задач показывают, кто реально закрыл/удалил заметку (а не её владельца).

Создание списка

POST /v1/api/lists

Создаёт новый список у пользователя-владельца токена.

Требуемый scope
write
Метод доступен только токенам с доступом «Все списки». Токены, привязанные к конкретным спискам, не могут создавать новые - это нарушало бы их границу доступа.
Тело запроса
ПолеТипОписание
namestring *Название списка. Обязательное поле.
colorstring | nullHEX-цвет или имя токена темы.
iconstring | nullИмя иконки (SF Symbol).
parent_idUUID | nullUUID группы, в которую сразу положить список. Группы создаются через /v1/api/groups.
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Покупки", "color": "#0a84ff" }' \
  https://taskid.app/v1/api/lists
Ответ 201 Created
{
  "list": {
    "id":        "6f8a6f4e-...",
    "parent_id": null,
    "name":      "Покупки",
    "color":     "#0a84ff",
    "icon":      null,
    "archived":  false
  }
}

Получение одного списка

GET /v1/api/lists/:id

Возвращает один список по идентификатору.

Требуемый scope
read
Пример
curl -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/lists/LIST_ID
Ответ 200 OK
{ "list": List }

Редактирование списка

PATCH /v1/api/lists/:id

Частичное обновление: в теле только те поля, которые нужно изменить.

Требуемый scope
write
Тело запроса
ПолеТипОписание
namestringНовое название. Пустая строка не допускается.
colorstring | nullHEX или имя токена темы. null - сбросить.
iconstring | nullИмя иконки (SF Symbol). null - сбросить.
archivedbooleanАрхивировать / вернуть из архива.
Привязка списка к группе делается отдельным методом POST /v1/api/lists/:id/attach.
Пример
curl -X PATCH \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Покупки на неделю" }' \
  https://taskid.app/v1/api/lists/LIST_ID
Ответ 200 OK
{ "list": List }

Привязка к группе

POST /v1/api/lists/:id/attach

Привязывает существующий список к группе или отвязывает его. В URL - id списка, в теле - только parent_id. Сам список не редактируется - меняется только его принадлежность группе.

Требуемый scope
write
Тело запроса
{
  "parent_id": UUID | null   // null - вынести в корень
}
Пример: привязать
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "parent_id": "GROUP_ID" }' \
  https://taskid.app/v1/api/lists/LIST_ID/attach
Пример: отвязать
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "parent_id": null }' \
  https://taskid.app/v1/api/lists/LIST_ID/attach
Ответ 200 OK
{ "list": List }

Удаление списка

DELETE /v1/api/lists/:id

Мягкое удаление списка (deleted_at = now). Задачи этого списка тоже перестанут показываться у клиентов после sync.

Требуемый scope
write
Пример
curl -X DELETE \
  -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/lists/LIST_ID
Ответ 204 No Content
Тело пустое.

Задачи

Получение задач

GET /v1/api/lists/:id/tasks

Возвращает задачи из конкретного списка.

Требуемый scope
read
Query-параметры
ПараметрПо умолчаниюЗначения
completed00 - скрыть завершённые, 1 - только завершённые, all - все.
limit1001..500
offset0≥ 0
Пример
curl -H "Authorization: Bearer tkd_xxx" \
  "https://taskid.app/v1/api/lists/6f8a6f4e-.../tasks?completed=0&limit=50"
Ответ 200 OK
{
  "list":   { "id": "...", "name": "Работа" },
  "total":  42,
  "limit":  50,
  "offset": 0,
  "tasks":  [ Task, Task, ... ]
}

total - число задач, попавших под фильтр до применения limit/offset.

Прикреплённые файлы у задачи

У каждой задачи (а также заметки и уведомления) есть массив files - вложения. Если ничего не прикреплено - массив пустой.

"files": [
  {
    "id":     "9f1c...",
    "name":   "contract.pdf",
    "size":   184320,                                 // байты
    "url":    "https://taskid.app/files/aa/bb/cc/9f1c....pdf",
    "source": "upload"                                // 'upload' | 'link'
  },
  {
    "id":     "1a2b...",
    "name":   "Status page",
    "size":   0,                                      // 0, если HEAD не вернул Content-Length
    "url":    "https://status.example.com/incidents/42",
    "source": "link"
  }
]
  • source: "upload" - реально загруженный файл в нашем хранилище. url ведёт на taskid.app, скачивается прямым GET без заголовков (capability-токен зашит в путь). Учитывается в файловой квоте пользователя.
  • source: "link" - внешний HTTPS-URL (наш сервер ничего не скачивает и не хранит). url ведёт на сторонний ресурс как есть. В квоте не учитывается; size может быть 0, если сервер ресурса не отдал Content-Length на HEAD-запросе при прикреплении.
  • Удалённые/откреплённые файлы и ссылки в массиве не возвращаются.
  • Прикрепить/открепить - см. «Прикрепить файлы и ссылки к задаче» и «Открепить файл/ссылку от задачи». Для заметок и уведомлений семантика идентичная.

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

POST /v1/api/lists/:id/tasks

Создаёт задачу в указанном списке.

Требуемый scope
write
Тело запроса
ПолеТипОписание
titlestring *Заголовок задачи. Обязательное поле.
notestring | nullЗаметка (многострочный текст).
due_atstring | nullISO-8601 в UTC, момент дедлайна.
due_has_timebooleanФлаг «у даты есть время». Если false, в UI показывается только дата.
flaggedbooleanМетка «Важно». По умолчанию false.
priorityinteger0 (none), 1 (low), 2 (med), 3 (high). По умолчанию 0.
parent_idUUID | nullUUID родительской задачи - тогда создаётся сразу подзадача. Родитель должен быть в том же списке и сам не быть подзадачей (одноуровневая иерархия). Для привязки уже существующей задачи к другой - см. POST /v1/api/tasks/:id/attach.
Пример: обычная задача
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Позвонить врачу",
    "due_at": "2026-04-20T08:00:00Z",
    "due_has_time": true,
    "flagged": true,
    "priority": 2
  }' \
  https://taskid.app/v1/api/lists/LIST_ID/tasks
Пример: сразу подзадача
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Купить молоко", "parent_id": "PARENT_TASK_UUID" }' \
  https://taskid.app/v1/api/lists/LIST_ID/tasks
Ответ 201 Created
{
  "task": {
    "id": "3c6b...-...-...",
    "list_id": "6f8a6f4e-...",
    "title": "Позвонить врачу",
    "note": null,
    "due_at": "2026-04-20T08:00:00Z",
    "due_has_time": true,
    "completed_at": null,
    "flagged": true,
    "priority": 2,
    "sort_order": 12000,
    "files": [],
    "version": "2026-04-18T12:34:56Z",
    "updated_at": "2026-04-18T12:34:56Z"
  }
}
Хочешь сразу прикрепить файлы?
Через тело POST /v1/api/lists/:id/tasks файлы не прикрепляются. Сделай в два шага: 1) создай задачу, 2) загрузи файлы через POST /v1/api/files и привяжи через POST /v1/api/tasks/:id/files.

Получение одной задачи

GET /v1/api/tasks/:id

Возвращает одну задачу по её идентификатору.

Требуемый scope
read
Пример
curl -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/tasks/TASK_ID
Ответ 200 OK
{ "task": Task }

404, если задача не найдена или принадлежит списку, недоступному токену.

Редактирование задачи

PATCH /v1/api/tasks/:id

Частичное обновление: в теле указываешь только те поля, которые хочешь изменить. Остальные поля задачи остаются как есть.

Требуемый scope
write
Семантика полей: поле передано - обновляем; значение null - очищаем (для nullable-полей); поля нет в теле - не трогаем.
При одновременной правке с разных устройств применяется LWW - побеждает более поздний client_updated_at.
Тело запроса
ПолеТипОписание
titlestringЗаголовок. Пустая строка не допускается.
notestring | nullЗаметка. null очищает.
due_atstring | nullISO-8601 UTC или null для сброса даты.
due_has_timebooleanУчитывать ли время в дате.
completedbooleantrue → completed_at = now, false → очистить.
flaggedbooleanМетка «Важно».
priorityinteger0, 1, 2 или 3.
in_my_daybooleantrue добавляет в «Мой день» на сегодня, false убирает.
Пример
curl -X PATCH \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Новое имя", "flagged": true }' \
  https://taskid.app/v1/api/tasks/TASK_ID
Ответ 200 OK
{ "task": Task }

Полная структура полей задачи - в разделе «Типы данных».

Файлы через PATCH не меняются
Этот эндпоинт меняет только текстовые поля, дату, важность и приоритет. Прикрепить файл к задаче - POST /v1/api/tasks/:id/files, открепить - DELETE /v1/api/tasks/:id/files/:fileId.

Удаление задачи

DELETE /v1/api/tasks/:id

Мягкое удаление: задача остаётся в БД с пометкой deleted_at - это нужно для корректной синхронизации с клиентами. Для пользователя задача пропадает из всех представлений.

Требуемый scope
write
Пример
curl -X DELETE \
  -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/tasks/TASK_ID
Ответ 204 No Content
Тело пустое.

Отметить выполненной

POST /v1/api/tasks/:id/complete

Удобный алиас для частого случая: устанавливает completed_at = now. Тело запроса не требуется. Идемпотентно: уже выполненная задача остаётся как есть.

Требуемый scope
write
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/tasks/TASK_ID/complete
Ответ 200 OK
{ "task": Task }

Вернуть в активные

POST /v1/api/tasks/:id/reopen

Снимает отметку о выполнении: completed_at = null. Идемпотентно.

Требуемый scope
write
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/tasks/TASK_ID/reopen
Ответ 200 OK
{ "task": Task }

Привязка к родительской задаче

POST /v1/api/tasks/:id/attach

Делает существующую задачу :id подзадачей задачи parent_id, либо - если parent_id: null - отвязывает её от родителя (снова верхнеуровневая задача). Сама задача остаётся в том же списке.

Требуемый scope
write
Тело запроса
{
  "parent_id": UUID | null   // null - отвязать
}
Ограничения
  • родитель должен быть в том же списке, что и задача;
  • родитель сам не должен быть подзадачей (иерархия одноуровневая);
  • задача :id не должна иметь собственных подзадач;
  • нельзя сделать задачу подзадачей самой себя.
Пример: привязать
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "parent_id": "PARENT_TASK_ID" }' \
  https://taskid.app/v1/api/tasks/CHILD_TASK_ID/attach
Пример: отвязать
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "parent_id": null }' \
  https://taskid.app/v1/api/tasks/CHILD_TASK_ID/attach
Ответ 200 OK
{ "task": Task }

Прикрепить файлы и ссылки к задаче

POST /v1/api/tasks/:id/files

Прикрепляет к задаче (а) ранее загруженные файлы по их id и/или (б) внешние HTTPS-ссылки. Минимум один из двух массивов должен быть непустым; можно слать оба одновременно.

Файлы: сначала залейте на сервер - см. «Загрузка файла» - и сохраните полученный id. Имя/размер/ссылку для скачивания сервер подтянет из БД сам. Ссылки: просто URL внешнего ресурса (картинка, дашборд, лог) - наш сервер ничего не скачивает и не кэширует, размер/MIME пытается определить HEAD-запросом.

Требуемый scope
write
Тело запроса
ПолеТипОписание
file_idsUUID[]Массив id ранее загруженных файлов. Каждый id - результат POST /v1/api/files. Файлы должны принадлежать вызывающему пользователю. Опционально, если есть links.
links{url, name?}[]Массив внешних ссылок. У каждой обязательное поле url (http/https) и опциональное name для отображения. Если имя не задано - сервер возьмёт его из Content-Disposition HEAD-ответа или из последнего сегмента URL. Опционально, если есть file_ids.
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "file_ids": ["9f1c-...", "5b2e-..."],
    "links": [
      { "url": "https://grafana.example.com/d/api", "name": "Dashboard" },
      { "url": "https://status.example.com/incidents/42" }
    ]
  }' \
  https://taskid.app/v1/api/tasks/TASK_ID/files
Что вернёт сервер

Полную обновлённую задачу с уже прикреплёнными файлами и ссылками в поле files (см. «Типы данных» - формат единый, с маркером source):

{
  "task": {
    "id":     "TASK_ID",
    "title":  "Договор с подрядчиком",
    "note":   null,
    "files": [
      {
        "id":     "9f1c-...",
        "name":   "contract.pdf",
        "size":   184320,
        "url":    "https://taskid.app/files/aa/bb/cc/9f1c....pdf",
        "source": "upload"
      },
      {
        "id":     "1a2b-...",
        "name":   "Dashboard",
        "size":   0,
        "url":    "https://grafana.example.com/d/api",
        "source": "link"
      }
    ],
    ...                            // остальные поля задачи - см. «Типы данных»
  }
}

Идемпотентно по file_ids - если файл уже прикреплён к этой задаче, повторный вызов оставит его как есть. Для links дедупликации по url нет: можно намеренно прикрепить один URL дважды с разными именами, у каждой ссылки свой id.

Пустые оба массива - 400. Хотя бы один должен содержать элементы.

Ссылки не учитываются в файловой квоте пользователя - у них нет загруженного содержимого. Учитываются только source: "upload" файлы.

Открепить файл/ссылку от задачи

DELETE /v1/api/tasks/:id/files/:fileId

Убирает файл или ссылку из массива files задачи. :fileId - значение поля id прикрепления (одинаковое для upload и link, тип определяется по source).

Если откреплённый source: "upload" файл загружали вы - он также помечается на удаление и физически сносится вскоре, квота освобождается сразу. Если файл загружал другой участник общего списка - у вас он просто исчезает из задачи; владелец остаётся прежним. Для source: "link" ничего физически не удаляется - ссылка просто перестаёт быть прикреплённой.

Требуемый scope
write
Пример
curl -X DELETE \
  -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/tasks/TASK_ID/files/FILE_ID
Что вернёт сервер

Полную обновлённую задачу - в массиве files этого файла больше нет:

{
  "task": {
    "id":    "TASK_ID",
    "title": "Договор с подрядчиком",
    "files": [],         // или массив с другими, оставшимися файлами
    ...
  }
}

Если такого файла к задаче не прикреплено (или его уже открепили раньше) - вернётся 404.

Заметки

Получение заметок списка

GET /v1/api/lists/:id/info

Заметки - отдельная сущность внутри списка: только заголовок и текст, без даты, важности, статуса выполнения. В task-эндпоинты и системные представления они не попадают.

Требуемый scope
read
Query-параметры
  • limit - 1..500, по умолчанию 100
  • offset - с какой заметки, по умолчанию 0
Пример
curl -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/lists/LIST_ID/info
Ответ 200 OK
{
  "list":    { "id": UUID, "name": string },
  "total":   number,
  "limit":   number,
  "offset":  number,
  "records": InfoRecord[]
}
Прикреплённые файлы у заметки

У заметки есть массив files с теми же полями, что у задачи: id, name, size, url (абсолютный, Authorization не нужен). Откреплённые/удалённые файлы не возвращаются. Прикрепить/открепить файл - см. «Прикрепить файлы к заметке» и «Открепить файл от заметки».

Создание заметки

POST /v1/api/lists/:id/info
Требуемый scope
write
Тело запроса
ПолеТипОписание
titlestring *Заголовок заметки. Обязательное поле, не пустое.
notestring | nullМногострочный текст заметки. Опционально. Это единственное содержательное поле кроме заголовка - полей вроде content, type, даты, важности или статуса выполнения у заметок нет.
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Wi-Fi пароль", "note": "Secret1234" }' \
  https://taskid.app/v1/api/lists/LIST_ID/info
Что вернёт сервер
{
  "record": {
    "id":         "INFO_ID",
    "list_id":    "LIST_ID",
    "title":      "Wi-Fi пароль",
    "note":       "Secret1234",
    "sort_order": 12000,
    "files":      [],
    "version":    "2026-04-18T12:34:56Z",
    "updated_at": "2026-04-18T12:34:56Z"
  }
}
Хочешь сразу прикрепить файлы?
Через тело POST /v1/api/lists/:id/info файлы не прикрепляются. Сделай в два шага: 1) создай заметку, 2) загрузи файлы через POST /v1/api/files и привяжи через POST /v1/api/info/:id/files.

Получение одной заметки

GET /v1/api/info/:id
Требуемый scope
read
Ответ 200 OK
{ "record": InfoRecord }

Редактирование заметки

PATCH /v1/api/info/:id
Требуемый scope
write
Тело запроса - все поля опциональны, обновляются только присутствующие
ПолеТипОписание
titlestringНовый заголовок. Пустая строка не допускается.
notestring | nullТекст заметки. null - очистить.
Что вернёт сервер
{ "record": InfoRecord }   // полная заметка после изменений

Структура полей - в разделе «Типы данных».

Файлы через PATCH не меняются
Этот эндпоинт меняет только заголовок и текст заметки. Прикрепить файл - POST /v1/api/info/:id/files, открепить - DELETE /v1/api/info/:id/files/:fileId.

Удаление заметки

DELETE /v1/api/info/:id

Мягкое удаление - такая же семантика, как у задач.

Требуемый scope
write
Ответ 204 No Content
Тело пустое.

Прикрепить файлы и ссылки к заметке

POST /v1/api/info/:id/files

Прикрепляет к заметке загруженные файлы и/или внешние HTTPS-ссылки. Семантика и контракт - идентичны «Прикрепить файлы и ссылки к задаче»: принимаются file_ids и links (хотя бы один непустой), ответ - обновлённая заметка с полем files.

Требуемый scope
write
Тело запроса
{
  "file_ids": ["UUID", ...],            // опционально
  "links":    [{ "url": "...", "name": "..." }, ...]  // опционально
}
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "file_ids": ["9f1c-..."],
    "links": [{ "url": "https://wiki.example.com/wifi", "name": "Wiki" }]
  }' \
  https://taskid.app/v1/api/info/INFO_ID/files
Что вернёт сервер

Полную обновлённую заметку - в массиве files уже видны прикреплённые файлы и ссылки:

{
  "record": {
    "id":    "INFO_ID",
    "title": "Wi-Fi пароль",
    "note":  "Secret1234",
    "files": [
      {
        "id":     "9f1c-...",
        "name":   "router-photo.jpg",
        "size":   92210,
        "url":    "https://taskid.app/files/aa/bb/cc/9f1c....jpg",
        "source": "upload"
      },
      {
        "id":     "1a2b-...",
        "name":   "Wiki",
        "size":   0,
        "url":    "https://wiki.example.com/wifi",
        "source": "link"
      }
    ],
    ...
  }
}

Открепить файл/ссылку от заметки

DELETE /v1/api/info/:id/files/:fileId

Убирает файл или ссылку из массива files заметки. Поведение и условия - см. «Открепить файл/ссылку от задачи»: для source: "upload" освобождается квота, для source: "link" ничего физически не удаляется.

Требуемый scope
write
Пример
curl -X DELETE \
  -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/info/INFO_ID/files/FILE_ID
Что вернёт сервер

Полную обновлённую заметку - этого файла в массиве files уже нет:

{
  "record": {
    "id":    "INFO_ID",
    "title": "Wi-Fi пароль",
    "files": [],         // или другие, оставшиеся файлы
    ...
  }
}

Если такого файла к заметке не прикреплено - вернётся 404.

Уведомления

Отправка уведомления

POST /v1/api/notifications

Создаёт запись типа "уведомление" и присылает на устройства пользователя видимый push-баннер с заголовком и текстом. Замена Telegram-боту для алертов мониторинга, серверных событий и любых внешних сообщений, которые должны быстро доходить до телефона.

Уведомление физически хранится в той же таблице, что задачи и заметки, но имеет отдельный тип (kind=2). На клиенте оно появляется в системном списке "Уведомления" и в указанном пользовательском списке. Из любого уведомления можно одним тапом сделать задачу.

Требуемый scope
write_notifications
Заголовки
ЗаголовокОписание
AuthorizationBearer tkd_... со scope=write_notifications.
Content-Typeapplication/json
Idempotency-KeyОпционально. Если интеграция ретраит запрос при сетевых сбоях, передавайте один и тот же ключ - повторный запрос вернёт уже созданное уведомление со статусом 200, без дубликата. Ключ живёт 24 часа.
Тело запроса
ПолеТипОписание
titlestring *Заголовок уведомления. Обязательное поле, не пустое. Отображается жирной строкой в push-баннере и в списке.
messagestring | nullТекст уведомления. Любые URL-ы внутри клиент рендерит кликабельно - можно класть ссылки на дашборд, тикет, лог. Опционально.
list_idstring (uuid) | nullUUID списка, к которому привязать уведомление. Если не передан, уведомление попадает во "Входящие" (без списка). Для токенов с ограниченным доступом к спискам поле обязательно.
priorityinteger 0..3Severity. Используется клиентом для иконки/цвета: 0=info, 1=low, 2=warn, 3=error. По умолчанию 0.
file_idsUUID[]Опционально. Прикрепить к создаваемому уведомлению ранее загруженные файлы. См. «Загрузка файла». Требует, чтобы токен также имел scope=write (на сами файлы), но конкретно этот POST принимается и со scope=write_notifications, если массив пустой/отсутствует.
links{url, name?}[]Опционально. Прикрепить внешние HTTPS-ссылки (дашборд, лог, скриншот). В файловой квоте не учитываются. Формат как у «Прикрепить файлы и ссылки к задаче».
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: alert-12345" \
  -d '{
    "title":    "Прод упал",
    "message":  "503 на api.example.com",
    "priority": 3,
    "links": [
      { "url": "https://grafana.example.com/d/api", "name": "Dashboard" },
      { "url": "https://status.example.com/incidents/42" }
    ]
  }' \
  https://taskid.app/v1/api/notifications
Что вернёт сервер
{
  "notification": {
    "id":           "NOTIF_ID",
    "list_id":      null,
    "title":        "Прод упал",
    "note":         "503 на api.example.com",
    "priority":     3,
    "completed_at": null,
    "sort_order":   12000,
    "files": [
      {
        "id":     "1a2b-...",
        "name":   "Dashboard",
        "size":   0,
        "url":    "https://grafana.example.com/d/api",
        "source": "link"
      }
    ],
    "version":      "2026-04-18T12:34:56Z",
    "updated_at":   "2026-04-18T12:34:56Z",
    "date_create":  "2026-04-18T12:34:56Z"
  }
}

HTTP 201 при создании. Если запрос повторно пришёл с тем же Idempotency-Key - HTTP 200 с тем же телом (новая запись не создаётся).

Лимит частоты
До 60 уведомлений в минуту на один токен. При превышении сервер вернёт HTTP 429 с заголовком Retry-After - интегрируйте экспоненциальный backoff. Лимит защищает от штормового потока (упавший монитор → тысячи алертов в минуту).
Поведение на iOS
Push приходит как видимый баннер - покажется даже если приложение не запущено или убито свайпом. Тап по баннеру открывает уведомление в приложении; одной кнопкой можно превратить его в задачу. Уведомление также синхронизируется на все устройства пользователя (iPhone, iPad, Mac, Android) и сохраняется в облаке.

Прикрепить файлы и ссылки к уведомлению

POST /v1/api/notifications/:id/files

Добавляет файлы и/или внешние ссылки к уже существующему уведомлению. Полезно, когда интеграция шлёт алерт первым же запросом (текст мгновенно доходит до телефона), а скриншоты/дампы/ссылки на дашборды подгружает следом, не дожидаясь окончания загрузки.

Семантика и тело запроса - идентичны «Прикрепить файлы и ссылки к задаче». Возвращается обновлённое уведомление (объект notification, а не task).

Требуемый scope
write

Не путать с write_notifications - тот разрешает только создавать уведомления (POST /notifications). Для прикрепления файлов нужен полноценный write.

Тело запроса
{
  "file_ids": ["UUID", ...],            // опционально
  "links":    [{ "url": "...", "name": "..." }, ...]  // опционально
}
Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "links": [
      { "url": "https://logs.example.com/alert/12345", "name": "Логи инцидента" }
    ]
  }' \
  https://taskid.app/v1/api/notifications/NOTIF_ID/files

Открепить файл/ссылку от уведомления

DELETE /v1/api/notifications/:id/files/:fileId

Убирает файл или ссылку из массива files уведомления. Поведение и условия - см. «Открепить файл/ссылку от задачи»: для source: "upload" освобождается квота, для source: "link" ничего физически не удаляется.

Требуемый scope
write
Пример
curl -X DELETE \
  -H "Authorization: Bearer tkd_xxx" \
  https://taskid.app/v1/api/notifications/NOTIF_ID/files/FILE_ID

Файлы

Загрузка файла

POST /v1/api/files

Заливает один или несколько файлов на сервер. Эндпоинт сам по себе ничего не привязывает к задачам/заметкам/уведомлениям - он только возвращает id, по которому файл потом можно прикрепить через /v1/api/tasks/:id/files, /v1/api/info/:id/files или /v1/api/notifications/:id/files.

Если ваш контент - уже доступный по HTTPS URL ресурс (картинка в CDN, ссылка на дашборд, скриншот в S3), грузить его к нам не нужно. Используйте поле links в attach-эндпоинтах - URL сохранится как есть, файловая квота не задействуется.

Требуемый scope
write
Тело запроса

multipart/form-data. Поле формы - files (можно несколько) или file (одиночный). Принимаются оба варианта.

Пример
curl -X POST \
  -H "Authorization: Bearer tkd_xxx" \
  -F "files=@/path/to/contract.pdf" \
  -F "files=@/path/to/photo.jpg" \
  https://taskid.app/v1/api/files
Ответ 201 Created
{
  "files": [
    { "id": "9f1c-...", "name": "contract.pdf", "size": 184320 },
    { "id": "5b2e-...", "name": "photo.jpg",    "size":  92210 }
  ]
}

URL для скачивания на этом шаге не отдаётся - он понадобится только когда файл будет прикреплён к задаче или заметке; там он уже придёт абсолютным в массиве files.

Ошибки
  • 400 - тело не multipart или нет файлов / пустой файл.
  • 413 - превышен максимальный размер запроса или одного файла.
  • 507 - превышена квота хранилища пользователя.

Типы данных

List
{
  "id":        UUID,
  "parent_id": UUID | null,   // UUID группы, в которой лежит список
  "name":      string,
  "color":     string | null, // HEX или имя токена темы
  "icon":      string | null, // SF Symbol
  "archived":  boolean,
  "is_owner":  boolean,       // вы владелец списка
  "is_shared": boolean        // у списка есть участники
}
Подробно про is_owner и is_shared - в разделе «Общие списки».
Group
{
  "id":       UUID,
  "name":     string,
  "color":    string | null,
  "icon":     string | null,
  "archived": boolean
}
Task
{
  "id":            UUID,
  "list_id":       UUID | null,
  "parent_id":     UUID | null,   // для подзадач
  "title":         string,
  "note":          string | null,
  "due_at":        string | null, // ISO-8601 UTC
  "due_has_time":  boolean,
  "completed_at":  string | null, // ISO-8601 UTC
  "flagged":       boolean,
  "priority":      0 | 1 | 2 | 3,
  "rrule_freq":     0 | 1 | 2 | 3 | 4 | 5, // 0=нет, HOURLY/DAILY/WEEKLY/MONTHLY/YEARLY
  "rrule_interval": number,  // >=1
  "rrule_byday":    number,  // битмаска Пн=1..Вс=64
  "rrule_bymonth":  number,  // битмаска янв=1..дек=2048
  "rrule_bysetpos": number,  // 1..4 или -1, 0=не задан
  "rrule_end_kind": 0 | 1 | 2, // 0=никогда, 1=до даты, 2=после N
  "rrule_until":    string | null, // ISO-8601 UTC
  "rrule_count":    number,
  "rrule_done":     number,
  "rrule_anchor":   0 | 1, // 0=schedule, 1=completion
  "in_my_day":     boolean,
  "in_my_day_date": string | null, // YYYY-MM-DD
  "sort_order":    number,
  "collapsed":     0 | 1,          // 1 = подзадачи свёрнуты
  "files":         FileRef[],      // см. «Прикреплённые файлы»
  "version":       string,    // ISO-8601 UTC, обновляется на сервере
  "updated_at":    string,    // ISO-8601 UTC
  "date_create":   string,    // ISO-8601 UTC
  "completed_user_id": UUID | null, // кто закрыл (важно в общих списках)
  "deleted_user_id":   UUID | null  // кто удалил
}
InfoRecord
{
  "id":         UUID,
  "list_id":    UUID,        // всегда привязан к конкретному списку
  "title":      string,
  "note":       string | null,
  "sort_order": number,
  "files":      FileRef[],   // см. «Прикреплённые файлы»
  "version":    string,      // ISO-8601 UTC
  "updated_at": string       // ISO-8601 UTC
}
FileRef
{
  "id":   UUID,
  "name": string,    // оригинальное имя файла
  "size": number,    // размер в байтах
  "url":  string     // абсолютный URL (https://taskid.app/files/...)
}
У заметок нет полей content, type, дедлайна, статуса выполнения, флагов, priority и «Мой день» - по замыслу. Содержательная часть только в title и note. В task-эндпоинты и системные представления заметки не попадают.
Вопросы и предложения - пиши в аккаунт поддержки.