# API Klepps

REST API таск-трекера Klepps: задачи, проекты и доски, учёт времени, документация, транскрипты встреч.

- Адрес: https://klepps.ru/api/v1
- Запросы и ответы — JSON в UTF-8; даты — миллисекунды Unix, дни — ГГГГ-ММ-ДД, время — в секундах.
- Ключ — в заголовке `Authorization: Bearer klp_…` (выпускается в Klepps: «API» → «Новый ключ»).
- Ключ действует от имени пользователя и может не больше, чем он сам. Изменения сразу видны коллегам.
- REST API доступен на тарифах «Команда» и «Бизнес», MCP-сервер для ИИ-агентов — на «Бизнесе».
- Лимит — 120 запросов в минуту на ключ (заголовки x-ratelimit-*, при превышении 429 и retry-after).
- Списки: `limit` (до 500, по умолчанию 100) и `cursor`; в ответе `nextCursor` (null — последняя страница) и `total`. Для синхронизации — `updatedSince`.
- Задачу можно указать ключом: `GET /tasks/WEB-42`.
- Описание для генераторов клиентов: https://klepps.ru/api/v1/openapi.json

## ИИ-агенты (MCP)

Klepps подключается к ИИ-агентам (Cursor, Claude, VS Code и другие) как MCP-сервер: https://klepps.ru/api/mcp, транспорт Streamable HTTP, вход — тем же ключом API в заголовке Authorization. Агент видит только инструменты, на которые у ключа есть права, и действует от имени пользователя ключа — как через REST API. MCP доступен на тарифе «Бизнес».

**Любая нейросеть — ваш агент.** Klepps не привязан к одной модели: Claude, GPT, Gemini, DeepSeek, Qwen, Kimi и другие работают с ним одинаково. Подойдёт любой клиент, который подключает MCP-сервер по адресу (Streamable HTTP) с заголовком: Cursor, Claude Code, VS Code, Cline и другие. Если клиент умеет запускать MCP только командой — через мост: npx mcp-remote https://klepps.ru/api/mcp --header "Authorization: Bearer klp_…".

Cursor (`.cursor/mcp.json` или настройки → MCP):

```json
{
  "mcpServers": {
    "klepps": {
      "url": "https://klepps.ru/api/mcp",
      "headers": {
        "Authorization": "Bearer klp_ВАШ_КЛЮЧ"
      }
    }
  }
}
```

Claude Code:

```bash
claude mcp add --transport http klepps https://klepps.ru/api/mcp --header "Authorization: Bearer klp_ВАШ_КЛЮЧ"
```

VS Code (`.vscode/mcp.json`):

```json
{
  "servers": {
    "klepps": {
      "type": "http",
      "url": "https://klepps.ru/api/mcp",
      "headers": {
        "Authorization": "Bearer klp_ВАШ_КЛЮЧ"
      }
    }
  }
}
```

Инструменты:

- `whoami` — Пользователь ключа, компания и права ключа. Вызовите первым, чтобы понять, от чьего имени вы работаете.
- `list_projects` — Проекты с досками и колонками (id и тип колонки: todo, progress, done). Нужен, чтобы создавать и переносить задачи.
- `list_users` — Участники компании: id, имя, логин, должность. Нужен, чтобы назначать исполнителей.
- `search_tasks` — Задачи по фильтрам: текст, проект, исполнитель (me — пользователь ключа), тип колонки, метка. Без фильтров — открытые задачи пользователя ключа. Право: `tasks:read`.
- `get_task` — Задача целиком в Markdown: описание, чек-лист, подзадачи, обсуждение (комментарии с id), связанные документы и договорённости со встреч. Задачу можно указать ключом (WEB-42). Право: `tasks:read`.
- `add_comment` — Комментарий к задаче от имени пользователя ключа. Сюда пишите результат работы: что сделано, ответ на вопрос, отчёт, ссылки. Можно ответить на комментарий (replyTo — id из get_task) и упомянуть людей через @логин. Право: `tasks:write`.
- `create_task` — Новая задача от имени пользователя ключа. Описание — в Markdown. Право: `tasks:write`.
- `update_task` — Меняет только переданные поля: название, приоритет, тип, метки, срок, исполнителей, чек-лист. Описание задачи — постановка от людей, агент его не меняет: результат пишите через add_comment. Право: `tasks:write`.
- `move_task` — Переносит задачу в колонку её доски: по названию колонки, её id или типу (todo, progress, done — первая колонка такого типа). Право: `tasks:write`.
- `log_time` — Записывает потраченное время на задачу от имени пользователя ключа. Право: `time:write`.
- `time_report` — Сколько времени потрачено за период в разрезе людей, задач, проектов или дней. Право: `time:read`.
- `list_docs` — Разделы документации и страницы в них; можно искать по тексту. Право: `docs:read`.
- `get_doc` — Страница документации целиком в Markdown. Право: `docs:read`.
- `create_doc` — Новая страница документации; содержимое — в Markdown. Право: `docs:write`.
- `update_doc` — Заменяет заголовок и/или содержимое страницы (Markdown, целиком). Прежний текст остаётся в истории версий. Право: `docs:write`.
- `list_meetings` — Записанные встречи, новые сверху; поиск по названию и саммари, фильтр по датам. Право: `meetings:read`.
- `get_meeting` — Саммари встречи (темы, решения, договорённости) и, по желанию, полный транскрипт. Право: `meetings:read`.

## Права ключа

| Право | Раздел | Что разрешает |
|---|---|---|
| `tasks:read` | Задачи | Задачи, чек-листы, подзадачи |
| `tasks:write` | Задачи | Создание, правка, перенос, исполнители, удаление |
| `projects:write` | Проекты | Создание проектов, досок и колонок, правка проектов |
| `time:read` | Время | Записи времени и отчёты по задачам, людям, проектам |
| `time:write` | Время | Списание времени на задачи |
| `docs:read` | Документы | Разделы и страницы документации |
| `docs:write` | Документы | Создание и правка страниц |
| `meetings:read` | Транскрипты | Встречи, саммари и транскрипты |

Проекты, доски, колонки, пользователи и метки читает любой ключ. Ключ можно ограничить проектами, сроком и IP-адресами.

## Ошибки

Ошибка — код HTTP и `{"error": {"code": "…", "message": "…"}}`.

| HTTP | code | Когда |
|---|---|---|
| 400 | `invalid_request` | Неверные параметры или тело запроса; в message — какое поле и что не так |
| 401 | `unauthorized` | Ключ не передан |
| 401 | `invalid_key` | Ключ неверный, отозван или его пользователь удалён |
| 401 | `key_expired` | Срок действия ключа истёк |
| 403 | `insufficient_scope` | Ключу не выдано нужное право |
| 403 | `forbidden` | У пользователя ключа нет прав на это действие |
| 403 | `ip_not_allowed` | Запрос пришёл не с разрешённого IP-адреса |
| 403 | `api_disabled` | Администратор отключил ключи участников |
| 403 | `plan_required` | API не входит в тариф компании: он доступен на «Команде» и «Бизнесе» |
| 404 | `not_found` | Объекта нет или он не виден ключу |
| 409 | `archived` | Задача в архиве — менять её можно после возврата из архива в Klepps |
| 422 | `rejected` | Действие не выполнено по правилам Klepps (лимит тарифа, цикл подзадач и т. п.); причина — в message |
| 429 | `rate_limited` | Превышен лимит запросов в минуту |

## Ключ и компания

### Проверить ключ

`GET /me` — любой ключ

От чьего имени работает ключ, в какой компании и с какими правами. Удобно для проверки подключения.

```bash
curl "https://klepps.ru/api/v1/me" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": {
    "user": {
      "id": "u-k3f9a2m1",
      "name": "Анна Смирнова",
      "login": "anna@romashka.ru",
      "role": "Руководитель проекта",
      "isAdmin": true,
      "teamIds": [
        "tm-frontend"
      ]
    },
    "workspace": {
      "id": "ws-5f2c…",
      "name": "Ромашка"
    },
    "key": {
      "id": "key-a1b2c3",
      "scopes": [
        "tasks:read",
        "tasks:write",
        "time:read"
      ],
      "projectIds": null
    },
    "rateLimitPerMinute": 120
  }
}
```

### Пользователи

`GET /users` — любой ключ

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `q` | string | Поиск по имени, логину, должности |
| `limit, cursor` |  | Постраничная выдача |

```bash
curl "https://klepps.ru/api/v1/users" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "u-k3f9a2m1",
      "name": "Анна Смирнова",
      "login": "anna@romashka.ru",
      "role": "Руководитель проекта",
      "isAdmin": true,
      "teamIds": [
        "tm-frontend"
      ]
    },
    {
      "id": "u-p7d2x8q4",
      "name": "Иван Петров",
      "login": "ivan",
      "role": "Разработчик",
      "isAdmin": false,
      "teamIds": [
        "tm-frontend"
      ]
    }
  ],
  "nextCursor": null,
  "total": 2
}
```

### Команды

`GET /teams` — любой ключ

```bash
curl "https://klepps.ru/api/v1/teams" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "tm-frontend",
      "name": "Фронтенд",
      "description": "",
      "memberIds": [
        "u-k3f9a2m1",
        "u-p7d2x8q4"
      ],
      "leadId": "u-k3f9a2m1"
    }
  ],
  "nextCursor": null,
  "total": 1
}
```

### Метки

`GET /labels` — любой ключ

```bash
curl "https://klepps.ru/api/v1/labels" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    "frontend",
    "срочно"
  ]
}
```

## Проекты и доски

Читать структуру может любой ключ. Ключ, ограниченный проектами, видит только их.

### Список проектов

`GET /projects` — любой ключ

```bash
curl "https://klepps.ru/api/v1/projects" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "p-w1e8r5t2",
      "key": "WEB",
      "name": "Сайт",
      "description": "Новый сайт компании",
      "createdAt": 1759300000000
    }
  ],
  "nextCursor": null,
  "total": 1
}
```

### Проект с досками и колонками

`GET /projects/{id}` — любой ключ

Параметры пути:

| Имя | Тип | Описание |
|---|---|---|
| `id` (обязательно) | string | id проекта |

```bash
curl "https://klepps.ru/api/v1/projects/p-w1e8r5t2" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": {
    "id": "p-w1e8r5t2",
    "key": "WEB",
    "name": "Сайт",
    "description": "Новый сайт компании",
    "createdAt": 1759300000000,
    "boards": [
      {
        "id": "b-9h4j2k7l",
        "projectId": "p-w1e8r5t2",
        "name": "Разработка",
        "description": "",
        "statuses": [
          {
            "id": "s-todo1",
            "name": "К выполнению",
            "category": "todo"
          },
          {
            "id": "s-prog1",
            "name": "В работе",
            "category": "progress"
          },
          {
            "id": "s-done1",
            "name": "Готово",
            "category": "done"
          }
        ]
      }
    ]
  }
}
```

### Создать проект

`POST /projects` — право ключа `projects:write`

Создаёт проект с первой доской по шаблону. Лимиты тарифа действуют как в интерфейсе. Ключу, ограниченному проектами, недоступно.

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `name` (обязательно) | string | Название |
| `key` (обязательно) | string | Ключ задач, до 10 символов: WEB → WEB-1, WEB-2… |
| `description` | string | Описание |
| `template` | scrum \| simple \| bugs \| null | Шаблон первой доски, по умолчанию simple; null — без доски |

```bash
curl -X POST "https://klepps.ru/api/v1/projects" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Мобильное приложение",
  "key": "APP",
  "template": "scrum"
}'
```

Ответ:

```json
{
  "data": {
    "id": "p-n3m4b5v6",
    "key": "APP",
    "name": "Мобильное приложение",
    "description": "",
    "createdAt": 1759300000000,
    "boards": [
      {
        "id": "b-c4v5b6n7",
        "projectId": "p-n3m4b5v6",
        "name": "Скрам",
        "description": "",
        "statuses": [
          {
            "id": "s-todo1",
            "name": "К выполнению",
            "category": "todo"
          },
          {
            "id": "s-prog1",
            "name": "В работе",
            "category": "progress"
          },
          {
            "id": "s-done1",
            "name": "Готово",
            "category": "done"
          }
        ]
      }
    ]
  }
}
```

### Изменить проект

`PATCH /projects/{id}` — право ключа `projects:write`

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `name, description` | string | Любые из полей |

```bash
curl -X PATCH "https://klepps.ru/api/v1/projects/p-w1e8r5t2" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "description": "Сайт и лендинги"
}'
```

Ответ:

```json
{
  "data": {
    "id": "p-w1e8r5t2",
    "key": "WEB",
    "name": "Сайт",
    "description": "Сайт и лендинги",
    "createdAt": 1759300000000
  }
}
```

### Доски

`GET /boards` — любой ключ

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `projectId` | string | Только доски проекта |

```bash
curl "https://klepps.ru/api/v1/boards?projectId=p-w1e8r5t2" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "b-9h4j2k7l",
      "projectId": "p-w1e8r5t2",
      "name": "Разработка",
      "description": "",
      "statuses": [
        {
          "id": "s-todo1",
          "name": "К выполнению",
          "category": "todo"
        },
        {
          "id": "s-prog1",
          "name": "В работе",
          "category": "progress"
        },
        {
          "id": "s-done1",
          "name": "Готово",
          "category": "done"
        }
      ]
    }
  ],
  "nextCursor": null,
  "total": 1
}
```

### Доска

`GET /boards/{id}` — любой ключ

```bash
curl "https://klepps.ru/api/v1/boards/b-9h4j2k7l" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": {
    "id": "b-9h4j2k7l",
    "projectId": "p-w1e8r5t2",
    "name": "Разработка",
    "description": "",
    "statuses": [
      {
        "id": "s-todo1",
        "name": "К выполнению",
        "category": "todo"
      },
      {
        "id": "s-prog1",
        "name": "В работе",
        "category": "progress"
      },
      {
        "id": "s-done1",
        "name": "Готово",
        "category": "done"
      }
    ]
  }
}
```

### Создать доску

`POST /boards` — право ключа `projects:write`

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `projectId` (обязательно) | string | Проект |
| `name` (обязательно) | string | Название |
| `description` | string | Описание |
| `template` | scrum \| simple \| bugs | Набор колонок, по умолчанию simple |

```bash
curl -X POST "https://klepps.ru/api/v1/boards" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "projectId": "p-w1e8r5t2",
  "name": "Баги",
  "template": "bugs"
}'
```

Ответ:

```json
{
  "data": {
    "id": "b-x1c2v3b4",
    "projectId": "p-w1e8r5t2",
    "name": "Баги",
    "description": "",
    "statuses": [
      {
        "id": "s-todo1",
        "name": "К выполнению",
        "category": "todo"
      },
      {
        "id": "s-prog1",
        "name": "В работе",
        "category": "progress"
      },
      {
        "id": "s-done1",
        "name": "Готово",
        "category": "done"
      }
    ]
  }
}
```

### Добавить колонку

`POST /boards/{id}/statuses` — право ключа `projects:write`

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `name` (обязательно) | string | Название колонки |

```bash
curl -X POST "https://klepps.ru/api/v1/boards/b-9h4j2k7l/statuses" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "На проверке"
}'
```

Ответ:

```json
{
  "data": {
    "id": "b-9h4j2k7l",
    "projectId": "p-w1e8r5t2",
    "name": "Разработка",
    "description": "",
    "statuses": [
      {
        "id": "s-todo1",
        "name": "К выполнению",
        "category": "todo"
      },
      {
        "id": "s-prog1",
        "name": "В работе",
        "category": "progress"
      },
      {
        "id": "s-done1",
        "name": "Готово",
        "category": "done"
      },
      {
        "id": "s-k8l9z0",
        "name": "На проверке",
        "category": "progress"
      }
    ]
  }
}
```

## Задачи

Задачу можно указывать по id или по ключу (WEB-42). Описание приходит в HTML (description) и простым текстом (descriptionText); при записи можно передать любое из двух. Время — в секундах.

### Список задач

`GET /tasks` — право ключа `tasks:read`

Краткие карточки без описания, по дате создания. Для синхронизации используйте updatedSince.

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `projectId, boardId, statusId` | string | Где лежит задача |
| `category` | todo \| progress \| done | Тип колонки |
| `assigneeId` | string | Исполнитель (любой из assigneeIds); none — без исполнителя |
| `reporterId` | string | Автор |
| `type` | task,bug,story,epic | Тип, можно несколько через запятую |
| `priority` | highest,high,medium,low,lowest | Приоритет, можно несколько |
| `label` | string | Метки через запятую — задача должна иметь все |
| `parentId` | string | Подзадачи задачи; none — только верхнего уровня |
| `dueBefore` | ГГГГ-ММ-ДД | Срок не позже даты |
| `updatedSince` | ISO 8601 \| мс | Изменённые после момента |
| `q` | string | Поиск по названию, ключу, описанию |
| `archived` | false \| true \| all | Архив: по умолчанию только активные |
| `limit, cursor` |  | Постраничная выдача |

```bash
curl "https://klepps.ru/api/v1/tasks?projectId=p-w1e8r5t2&category=progress&assigneeId=u-p7d2x8q4" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "t-m4n8b2v6",
      "key": "WEB-42",
      "projectId": "p-w1e8r5t2",
      "boardId": "b-9h4j2k7l",
      "statusId": "s-prog1",
      "status": {
        "name": "В работе",
        "category": "progress"
      },
      "title": "Форма обратной связи",
      "type": "task",
      "priority": "high",
      "assigneeId": "u-p7d2x8q4",
      "assigneeIds": [
        "u-p7d2x8q4"
      ],
      "reporterId": "u-k3f9a2m1",
      "labels": [
        "frontend"
      ],
      "dueDate": "2026-10-20",
      "parentId": null,
      "timeEstimateSeconds": 28800,
      "timeSpentSeconds": 5400,
      "archived": false,
      "doneAt": null,
      "archivedAt": null,
      "createdAt": 1760000000000,
      "updatedAt": 1760090000000
    }
  ],
  "nextCursor": null,
  "total": 1
}
```

### Задача целиком

`GET /tasks/{ref}` — право ключа `tasks:read`

С описанием, чек-листом, подзадачами, записями времени, вложениями и связанными документами.

Параметры пути:

| Имя | Тип | Описание |
|---|---|---|
| `ref` (обязательно) | string | id или ключ задачи |

```bash
curl "https://klepps.ru/api/v1/tasks/WEB-42" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": {
    "id": "t-m4n8b2v6",
    "key": "WEB-42",
    "projectId": "p-w1e8r5t2",
    "boardId": "b-9h4j2k7l",
    "statusId": "s-prog1",
    "status": {
      "name": "В работе",
      "category": "progress"
    },
    "title": "Форма обратной связи",
    "type": "task",
    "priority": "high",
    "assigneeId": "u-p7d2x8q4",
    "assigneeIds": [
      "u-p7d2x8q4"
    ],
    "reporterId": "u-k3f9a2m1",
    "labels": [
      "frontend"
    ],
    "dueDate": "2026-10-20",
    "parentId": null,
    "timeEstimateSeconds": 28800,
    "timeSpentSeconds": 5400,
    "archived": false,
    "doneAt": null,
    "archivedAt": null,
    "createdAt": 1760000000000,
    "updatedAt": 1760090000000,
    "description": "<p>Поля: имя, контакт, сообщение. Отправка — на <b>/api/feedback</b>.</p>",
    "descriptionText": "Поля: имя, контакт, сообщение. Отправка — на /api/feedback.",
    "checklist": [
      {
        "id": "c-1",
        "text": "Вёрстка",
        "done": true
      },
      {
        "id": "c-2",
        "text": "Валидация",
        "done": false
      }
    ],
    "subtaskIds": [],
    "timeLogs": [
      {
        "id": "tl-a8s7d6f5",
        "taskId": "t-m4n8b2v6",
        "taskKey": "WEB-42",
        "projectId": "p-w1e8r5t2",
        "userId": "u-p7d2x8q4",
        "seconds": 5400,
        "date": "2026-10-09",
        "note": "Вёрстка и валидация"
      }
    ],
    "attachments": [
      {
        "id": "f-u8i9o0",
        "name": "макет.png",
        "size": 182340,
        "type": "image/png"
      }
    ],
    "docIds": [
      "d-feedback"
    ]
  }
}
```

### Контекст для ИИ

`GET /tasks/{ref}/context` — право ключа `tasks:read`

Задача одним Markdown-текстом: свойства, описание, чек-лист, подзадачи, обсуждение (последние 50 комментариев с id), связанные документы (с правом docs:read) и договорённости со встреч (с правом meetings:read). Готовый контекст для ИИ-агента; то же копирует кнопка «Скопировать для ИИ» в карточке задачи.

Параметры пути:

| Имя | Тип | Описание |
|---|---|---|
| `ref` (обязательно) | string | id или ключ задачи |

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `format` | markdown \| json | По умолчанию text/markdown; json — {data: {taskId, key, markdown}} |

```bash
curl "https://klepps.ru/api/v1/tasks/WEB-42/context" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

# WEB-42: Форма обратной связи

- Проект: Сайт (WEB); доска: Разработка; колонка: В работе (в работе)
- Тип: задача; приоритет: высокий
- Исполнители: Иван Петров; автор: Анна Смирнова
- Срок: 2026-10-20; оценка: 1д; потрачено: 1ч 30м

## Описание

Поля: имя, контакт, сообщение. Отправка — на **/api/feedback**.

## Чек-лист

- [x] Вёрстка
- [ ] Валидация

## Связанные документы

### Форма обратной связи (раздел «Техническая документация», id d-feedback)

…

### Создать задачу

`POST /tasks` — право ключа `tasks:write`

Автором становится пользователь ключа. Исполнители получают уведомление, автоматизации доски срабатывают как обычно.

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `title` (обязательно) | string | Название |
| `boardId` | string | Доска; или projectId — тогда первая доска проекта |
| `statusId` | string | Колонка, по умолчанию первая |
| `description / descriptionText` | string | Описание в HTML или простым текстом |
| `type` | task \| bug \| story \| epic | По умолчанию task |
| `priority` | highest \| high \| medium \| low \| lowest | По умолчанию medium |
| `assigneeIds` | string[] | Исполнители |
| `assigneeId` | string | У кого задача сейчас (по умолчанию первый из assigneeIds) |
| `labels` | string[] | Метки (новые создаются) |
| `dueDate` | ГГГГ-ММ-ДД \| null | Срок |
| `timeEstimateSeconds` | number | Оценка времени |
| `checklist` | {text, done}[] | Чек-лист |
| `parentId` | string | Родительская задача (тот же проект) |

```bash
curl -X POST "https://klepps.ru/api/v1/tasks" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "projectId": "p-w1e8r5t2",
  "title": "Форма обратной связи",
  "descriptionText": "Поля: имя, контакт, сообщение.",
  "priority": "high",
  "assigneeIds": [
    "u-p7d2x8q4"
  ],
  "labels": [
    "frontend"
  ],
  "dueDate": "2026-10-20"
}'
```

Ответ:

```json
{
  "data": {
    "id": "t-m4n8b2v6",
    "key": "WEB-42",
    "projectId": "p-w1e8r5t2",
    "boardId": "b-9h4j2k7l",
    "statusId": "s-todo1",
    "status": {
      "name": "К выполнению",
      "category": "todo"
    },
    "title": "Форма обратной связи",
    "type": "task",
    "priority": "high",
    "assigneeId": "u-p7d2x8q4",
    "assigneeIds": [
      "u-p7d2x8q4"
    ],
    "reporterId": "u-k3f9a2m1",
    "labels": [
      "frontend"
    ],
    "dueDate": "2026-10-20",
    "parentId": null,
    "timeEstimateSeconds": 28800,
    "timeSpentSeconds": 0,
    "archived": false,
    "doneAt": null,
    "archivedAt": null,
    "createdAt": 1760000000000,
    "updatedAt": 1760090000000,
    "description": "<p>Поля: имя, контакт, сообщение. Отправка — на <b>/api/feedback</b>.</p>",
    "descriptionText": "Поля: имя, контакт, сообщение. Отправка — на /api/feedback.",
    "checklist": [
      {
        "id": "c-1",
        "text": "Вёрстка",
        "done": true
      },
      {
        "id": "c-2",
        "text": "Валидация",
        "done": false
      }
    ],
    "subtaskIds": [],
    "timeLogs": [],
    "attachments": [
      {
        "id": "f-u8i9o0",
        "name": "макет.png",
        "size": 182340,
        "type": "image/png"
      }
    ],
    "docIds": [
      "d-feedback"
    ]
  }
}
```

### Изменить задачу

`PATCH /tasks/{ref}` — право ключа `tasks:write`

Передавайте только меняющиеся поля. statusId переносит задачу в колонку (наверх), boardId — на другую доску проекта, assigneeIds заменяет список исполнителей, assigneeId передаёт задачу.

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `title, description, descriptionText, type, priority, labels, dueDate, timeEstimateSeconds, checklist` |  | Как при создании |
| `statusId` | string | Новая колонка |
| `boardId` | string | Другая доска того же проекта |
| `assigneeIds` | string[] | Исполнители |
| `assigneeId` | string | Передать задачу |
| `parentId` | string \| null | Сделать подзадачей / отвязать |

```bash
curl -X PATCH "https://klepps.ru/api/v1/tasks/WEB-42" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "statusId": "s-done1",
  "priority": "medium"
}'
```

Ответ:

```json
{
  "data": {
    "id": "t-m4n8b2v6",
    "key": "WEB-42",
    "projectId": "p-w1e8r5t2",
    "boardId": "b-9h4j2k7l",
    "statusId": "s-done1",
    "status": {
      "name": "Готово",
      "category": "done"
    },
    "title": "Форма обратной связи",
    "type": "task",
    "priority": "medium",
    "assigneeId": "u-p7d2x8q4",
    "assigneeIds": [
      "u-p7d2x8q4"
    ],
    "reporterId": "u-k3f9a2m1",
    "labels": [
      "frontend"
    ],
    "dueDate": "2026-10-20",
    "parentId": null,
    "timeEstimateSeconds": 28800,
    "timeSpentSeconds": 5400,
    "archived": false,
    "doneAt": null,
    "archivedAt": null,
    "createdAt": 1760000000000,
    "updatedAt": 1760090000000,
    "description": "<p>Поля: имя, контакт, сообщение. Отправка — на <b>/api/feedback</b>.</p>",
    "descriptionText": "Поля: имя, контакт, сообщение. Отправка — на /api/feedback.",
    "checklist": [
      {
        "id": "c-1",
        "text": "Вёрстка",
        "done": true
      },
      {
        "id": "c-2",
        "text": "Валидация",
        "done": false
      }
    ],
    "subtaskIds": [],
    "timeLogs": [
      {
        "id": "tl-a8s7d6f5",
        "taskId": "t-m4n8b2v6",
        "taskKey": "WEB-42",
        "projectId": "p-w1e8r5t2",
        "userId": "u-p7d2x8q4",
        "seconds": 5400,
        "date": "2026-10-09",
        "note": "Вёрстка и валидация"
      }
    ],
    "attachments": [
      {
        "id": "f-u8i9o0",
        "name": "макет.png",
        "size": 182340,
        "type": "image/png"
      }
    ],
    "docIds": [
      "d-feedback"
    ]
  }
}
```

### Перенести в колонку

`POST /tasks/{ref}/move` — право ключа `tasks:write`

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `statusId` (обязательно) | string | Колонка |
| `position` | number | Место в колонке, 0 — сверху (по умолчанию) |
| `boardId` | string | Другая доска того же проекта |

```bash
curl -X POST "https://klepps.ru/api/v1/tasks/WEB-42/move" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "statusId": "s-prog1",
  "position": 2
}'
```

Ответ:

```json
{
  "data": {
    "id": "t-m4n8b2v6",
    "key": "WEB-42",
    "projectId": "p-w1e8r5t2",
    "boardId": "b-9h4j2k7l",
    "statusId": "s-prog1",
    "status": {
      "name": "В работе",
      "category": "progress"
    },
    "title": "Форма обратной связи",
    "type": "task",
    "priority": "high",
    "assigneeId": "u-p7d2x8q4",
    "assigneeIds": [
      "u-p7d2x8q4"
    ],
    "reporterId": "u-k3f9a2m1",
    "labels": [
      "frontend"
    ],
    "dueDate": "2026-10-20",
    "parentId": null,
    "timeEstimateSeconds": 28800,
    "timeSpentSeconds": 5400,
    "archived": false,
    "doneAt": null,
    "archivedAt": null,
    "createdAt": 1760000000000,
    "updatedAt": 1760090000000,
    "description": "<p>Поля: имя, контакт, сообщение. Отправка — на <b>/api/feedback</b>.</p>",
    "descriptionText": "Поля: имя, контакт, сообщение. Отправка — на /api/feedback.",
    "checklist": [
      {
        "id": "c-1",
        "text": "Вёрстка",
        "done": true
      },
      {
        "id": "c-2",
        "text": "Валидация",
        "done": false
      }
    ],
    "subtaskIds": [],
    "timeLogs": [
      {
        "id": "tl-a8s7d6f5",
        "taskId": "t-m4n8b2v6",
        "taskKey": "WEB-42",
        "projectId": "p-w1e8r5t2",
        "userId": "u-p7d2x8q4",
        "seconds": 5400,
        "date": "2026-10-09",
        "note": "Вёрстка и валидация"
      }
    ],
    "attachments": [
      {
        "id": "f-u8i9o0",
        "name": "макет.png",
        "size": 182340,
        "type": "image/png"
      }
    ],
    "docIds": [
      "d-feedback"
    ]
  }
}
```

### Удалить задачу

`DELETE /tasks/{ref}` — право ключа `tasks:write`

Безвозвратно, вместе со списанным временем.

```bash
curl -X DELETE "https://klepps.ru/api/v1/tasks/WEB-42" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

204 No Content

### Комментарии

`GET /tasks/{ref}/comments` — право ключа `tasks:read`

Обсуждение задачи, старые сверху. Текст — простой, с переносами строк; упоминания — @логин.

Параметры пути:

| Имя | Тип | Описание |
|---|---|---|
| `ref` (обязательно) | string | id или ключ задачи |

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `limit, cursor` |  | Постраничная выдача |

```bash
curl "https://klepps.ru/api/v1/tasks/WEB-42/comments" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "m-z7x6c5v4",
      "authorId": "u-p7d2x8q4",
      "text": "Готово: форма отправляет заявку, валидация полей на клиенте и сервере.",
      "replyTo": null,
      "createdAt": 1760090000000
    },
    {
      "id": "m-q2w3e4r5",
      "authorId": "u-k3f9a2m1",
      "text": "Спасибо, проверю на стенде.",
      "replyTo": "m-z7x6c5v4",
      "createdAt": 1760091200000
    }
  ],
  "nextCursor": null,
  "total": 2
}
```

### Написать комментарий

`POST /tasks/{ref}/comments` — право ключа `tasks:write`

От имени пользователя ключа. Автор и исполнители задачи, упомянутые и автор комментария, на который отвечают, получают уведомление во «Входящих». Сюда ИИ-агенту стоит писать результат работы, не меняя описание задачи.

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `text` (обязательно) | string | Текст, до 20 000 символов |
| `replyTo` | string \| null | id комментария, на который это ответ |

```bash
curl -X POST "https://klepps.ru/api/v1/tasks/WEB-42/comments" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "text": "Готово: форма отправляет заявку, валидация полей на клиенте и сервере. @anna@romashka.ru посмотрите, пожалуйста."
}'
```

Ответ:

```json
{
  "data": {
    "id": "m-z7x6c5v4",
    "authorId": "u-p7d2x8q4",
    "text": "Готово: форма отправляет заявку, валидация полей на клиенте и сервере.",
    "replyTo": null,
    "createdAt": 1760090000000
  }
}
```

## Учёт времени

Записи времени привязаны к дню (ГГГГ-ММ-ДД). В отчёты попадают и задачи из архива.

### Отчёт по времени

`GET /time/report` — право ключа `time:read`

Суммы за период в разрезе людей, задач, проектов или дней — до трёх разрезов сразу (например, user,task — кто сколько потратил на каждую задачу).

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `from, to` | ГГГГ-ММ-ДД | Период включительно, не больше года; по умолчанию с 1-го числа по сегодня |
| `groupBy` | user, task, project, day | Разрезы через запятую, по умолчанию user |
| `userId, projectId, taskId` | string | Фильтры, можно несколько через запятую |

```bash
curl "https://klepps.ru/api/v1/time/report?from=2026-10-01&to=2026-10-31&groupBy=user,project" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "from": "2026-10-01",
  "to": "2026-10-31",
  "groupBy": [
    "user",
    "project"
  ],
  "totalSeconds": 129600,
  "totalHours": 36,
  "data": [
    {
      "user": {
        "id": "u-p7d2x8q4",
        "name": "Иван Петров"
      },
      "project": {
        "id": "p-w1e8r5t2",
        "key": "WEB",
        "name": "Сайт"
      },
      "seconds": 86400,
      "entries": 14,
      "hours": 24
    },
    {
      "user": {
        "id": "u-k3f9a2m1",
        "name": "Анна Смирнова"
      },
      "project": {
        "id": "p-w1e8r5t2",
        "key": "WEB",
        "name": "Сайт"
      },
      "seconds": 43200,
      "entries": 9,
      "hours": 12
    }
  ]
}
```

### Записи времени

`GET /time/entries` — право ключа `time:read`

Отдельные записи, новые сверху — для выгрузки в 1С, BI или табель.

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `from, to` | ГГГГ-ММ-ДД | Период, как в отчёте |
| `userId, projectId, taskId` | string | Фильтры через запятую |
| `limit, cursor` |  | Постраничная выдача |

```bash
curl "https://klepps.ru/api/v1/time/entries?from=2026-10-01&to=2026-10-31&userId=u-p7d2x8q4" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "tl-a8s7d6f5",
      "taskId": "t-m4n8b2v6",
      "taskKey": "WEB-42",
      "projectId": "p-w1e8r5t2",
      "userId": "u-p7d2x8q4",
      "seconds": 5400,
      "date": "2026-10-09",
      "note": "Вёрстка и валидация"
    }
  ],
  "nextCursor": null,
  "total": 1
}
```

### Списать время

`POST /tasks/{ref}/time` — право ключа `time:write`

Время записывается на пользователя ключа.

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `minutes / seconds` (обязательно) | number | Сколько (от 1 минуты до 7 суток) |
| `date` | ГГГГ-ММ-ДД | День, по умолчанию сегодня (МСК) |
| `note` | string | Что делали |

```bash
curl -X POST "https://klepps.ru/api/v1/tasks/WEB-42/time" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "minutes": 90,
  "date": "2026-10-09",
  "note": "Вёрстка и валидация"
}'
```

Ответ:

```json
{
  "data": {
    "id": "tl-a8s7d6f5",
    "taskId": "t-m4n8b2v6",
    "taskKey": "WEB-42",
    "projectId": "p-w1e8r5t2",
    "userId": "u-p7d2x8q4",
    "seconds": 5400,
    "date": "2026-10-09",
    "note": "Вёрстка и валидация"
  }
}
```

## Документы

Видны только разделы, которые может читать пользователь ключа. Содержимое — HTML (content) и простой текст (text). При записи HTML очищается: скрипты, стили и чужие теги удаляются.

### Разделы

`GET /doc-spaces` — право ключа `docs:read`

```bash
curl "https://klepps.ru/api/v1/doc-spaces" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "ds-tech",
      "name": "Техническая документация",
      "description": "Архитектура, API, инфраструктура"
    }
  ]
}
```

### Список страниц

`GET /docs` — право ключа `docs:read`

Без содержимого, в порядке дерева.

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `spaceId` | string | Раздел |
| `parentId` | string | Дочерние страницы; none — верхнего уровня |
| `taskId` | string | Страницы, связанные с задачей |
| `q` | string | Поиск по названию и тексту |
| `updatedSince` | ISO 8601 \| мс | Изменённые после момента |
| `limit, cursor` |  | Постраничная выдача |

```bash
curl "https://klepps.ru/api/v1/docs?spaceId=ds-tech" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "d-feedback",
      "spaceId": "ds-tech",
      "parentId": null,
      "title": "Форма обратной связи",
      "taskIds": [
        "t-m4n8b2v6"
      ],
      "authorId": "u-k3f9a2m1",
      "createdAt": 1759900000000,
      "updatedAt": 1760080000000
    }
  ],
  "nextCursor": null,
  "total": 1
}
```

### Страница целиком

`GET /docs/{id}` — право ключа `docs:read`

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `format` | json \| markdown | markdown — страница простым Markdown-текстом (удобно для ИИ) |

```bash
curl "https://klepps.ru/api/v1/docs/d-feedback" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": {
    "id": "d-feedback",
    "spaceId": "ds-tech",
    "parentId": null,
    "title": "Форма обратной связи",
    "taskIds": [
      "t-m4n8b2v6"
    ],
    "authorId": "u-k3f9a2m1",
    "createdAt": 1759900000000,
    "updatedAt": 1760080000000,
    "content": "<h2>Поля</h2><ul><li>Имя</li><li>Контакт</li></ul>",
    "text": "Поля\nИмя\nКонтакт",
    "attachments": []
  }
}
```

### Создать страницу

`POST /docs` — право ключа `docs:write`

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `spaceId` (обязательно) | string | Раздел |
| `title` (обязательно) | string | Заголовок |
| `parentId` | string | Родительская страница |
| `content / text` | string | Содержимое в HTML или простым текстом |

```bash
curl -X POST "https://klepps.ru/api/v1/docs" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "spaceId": "ds-tech",
  "title": "Релиз 1.4.2",
  "text": "Что вошло:\n— форма обратной связи\n— тёмная тема"
}'
```

Ответ:

```json
{
  "data": {
    "id": "d-r3l3as",
    "spaceId": "ds-tech",
    "parentId": null,
    "title": "Релиз 1.4.2",
    "taskIds": [],
    "authorId": "u-k3f9a2m1",
    "createdAt": 1759900000000,
    "updatedAt": 1760080000000,
    "content": "<p>Что вошло:<br>— форма обратной связи<br>— тёмная тема</p>",
    "text": "Что вошло:\n— форма обратной связи\n— тёмная тема",
    "attachments": []
  }
}
```

### Изменить страницу

`PATCH /docs/{id}` — право ключа `docs:write`

Прежний текст сохраняется в истории версий (не чаще раза в час), изменение попадает в журнал документа.

Тело запроса (JSON):

| Имя | Тип | Описание |
|---|---|---|
| `title` | string | Заголовок |
| `content / text` | string | Новое содержимое целиком |

```bash
curl -X PATCH "https://klepps.ru/api/v1/docs/d-feedback" \
  -H "Authorization: Bearer $KLEPPS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "content": "<h2>Поля</h2><ul><li>Имя</li><li>Контакт</li><li>Сообщение</li></ul>"
}'
```

Ответ:

```json
{
  "data": {
    "id": "d-feedback",
    "spaceId": "ds-tech",
    "parentId": null,
    "title": "Форма обратной связи",
    "taskIds": [
      "t-m4n8b2v6"
    ],
    "authorId": "u-k3f9a2m1",
    "createdAt": 1759900000000,
    "updatedAt": 1760080000000,
    "content": "<h2>Поля</h2><ul><li>Имя</li><li>Контакт</li><li>Сообщение</li></ul>",
    "text": "Поля\nИмя\nКонтакт\nСообщение",
    "attachments": []
  }
}
```

## Транскрипты встреч

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

### Папки встреч

`GET /meeting-folders` — право ключа `meetings:read`

```bash
curl "https://klepps.ru/api/v1/meeting-folders" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "mf-dev",
      "name": "Разработка",
      "parentId": null,
      "teamIds": [
        "tm-frontend"
      ]
    }
  ]
}
```

### Список встреч

`GET /meetings` — право ключа `meetings:read`

Новые сверху.

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `folderId` | string | Папка; personal — личные |
| `projectId` | string | Проект встречи |
| `status` | string | recording, transcribing, done, failed… |
| `from, to` | ГГГГ-ММ-ДД | Дата встречи |
| `q` | string | Поиск по названию и саммари |
| `limit, cursor` |  | Постраничная выдача |

```bash
curl "https://klepps.ru/api/v1/meetings?from=2026-10-01" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": [
    {
      "id": "mt-h5j6k7",
      "title": "Планирование спринта",
      "url": "https://telemost.yandex.ru/j/12345678901234",
      "folderId": "mf-dev",
      "projectId": "p-w1e8r5t2",
      "createdBy": "u-k3f9a2m1",
      "startedAt": 1760010060000,
      "endedAt": 1760012700000,
      "status": "done",
      "participants": [
        "Анна Смирнова",
        "Иван Петров"
      ],
      "transcriptReady": true,
      "hasSummary": true
    }
  ],
  "nextCursor": null,
  "total": 1
}
```

### Встреча с саммари

`GET /meetings/{id}` — право ключа `meetings:read`

```bash
curl "https://klepps.ru/api/v1/meetings/mt-h5j6k7" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": {
    "id": "mt-h5j6k7",
    "title": "Планирование спринта",
    "url": "https://telemost.yandex.ru/j/12345678901234",
    "folderId": "mf-dev",
    "projectId": "p-w1e8r5t2",
    "createdBy": "u-k3f9a2m1",
    "startedAt": 1760010060000,
    "endedAt": 1760012700000,
    "status": "done",
    "participants": [
      "Анна Смирнова",
      "Иван Петров"
    ],
    "transcriptReady": true,
    "hasSummary": true,
    "summary": {
      "overview": "Спланировали спринт 14: форма обратной связи, тёмная тема, исправление оплаты.",
      "topics": [
        {
          "title": "Форма обратной связи",
          "points": [
            "Нужна капча",
            "Ответ — на e-mail или телефон"
          ]
        }
      ],
      "decisions": [
        "Релиз 1.4.2 — 20 октября"
      ],
      "actionItems": [
        {
          "text": "Сверстать форму",
          "owner": "Иван Петров",
          "due": "2026-10-15",
          "taskId": "t-m4n8b2v6"
        }
      ],
      "generatedAt": 1760013000000
    }
  }
}
```

### Транскрипт

`GET /meetings/{id}/transcript` — право ключа `meetings:read`

Реплики по порядку. С format=text — простой текст «[чч:мм:сс] Имя: реплика» построчно.

Параметры запроса:

| Имя | Тип | Описание |
|---|---|---|
| `format` | json \| text | По умолчанию json |

```bash
curl "https://klepps.ru/api/v1/meetings/mt-h5j6k7/transcript" \
  -H "Authorization: Bearer $KLEPPS_KEY"
```

Ответ:

```json
{
  "data": {
    "meetingId": "mt-h5j6k7",
    "replicas": [
      {
        "speaker": "Анна Смирнова",
        "start": "00:00:04",
        "end": "00:00:11",
        "text": "Коллеги, начнём. Сегодня планируем четырнадцатый спринт."
      },
      {
        "speaker": "Иван Петров",
        "start": "00:00:12",
        "end": "00:00:20",
        "text": "Предлагаю начать с формы обратной связи, макет уже готов."
      }
    ]
  }
}
```

## Примеры интеграций

### Табель за месяц в Excel (CSV)

```python
# Отчёт по времени за прошлый месяц: кто сколько часов потратил на какую задачу
import csv, datetime, os, requests

today = datetime.date.today()
last = today.replace(day=1) - datetime.timedelta(days=1)
res = requests.get(
    "https://klepps.ru/api/v1/time/report",
    params={"from": last.replace(day=1).isoformat(), "to": last.isoformat(), "groupBy": "user,task"},
    headers={"Authorization": f"Bearer {os.environ['KLEPPS_KEY']}"},
)
res.raise_for_status()
with open("time.csv", "w", newline="", encoding="utf-8-sig") as f:
    w = csv.writer(f, delimiter=";")
    w.writerow(["Сотрудник", "Задача", "Название", "Часы"])
    for row in res.json()["data"]:
        w.writerow([row["user"]["name"], row["task"]["key"], row["task"]["title"], str(row["hours"]).replace(".", ",")])
```

### Заявка с сайта или из CRM — задача

```javascript
// Заявка с сайта или из CRM → задача в Klepps
await fetch("https://klepps.ru/api/v1/tasks", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.KLEPPS_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    projectId: "p-w1e8r5t2",
    title: `Заявка: ${lead.company}`,
    descriptionText: `${lead.name}, ${lead.phone}\n\n${lead.message}`,
    labels: ["заявка"],
    priority: "high",
    dueDate: new Date(Date.now() + 86400000).toISOString().slice(0, 10),
  }),
});
```

### Синхронизация изменений

```javascript
// Забираем всё, что изменилось с прошлого запуска (постранично)
let since = loadCheckpoint();            // ISO-время прошлого запуска
const started = new Date().toISOString();
let cursor = null;
do {
  const url = new URL("https://klepps.ru/api/v1/tasks");
  url.searchParams.set("updatedSince", since);
  url.searchParams.set("archived", "all");
  url.searchParams.set("limit", "500");
  if (cursor) url.searchParams.set("cursor", cursor);
  const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.KLEPPS_KEY}` } });
  const page = await res.json();
  for (const task of page.data) await upsert(task);
  cursor = page.nextCursor;
} while (cursor);
saveCheckpoint(started);
```
