Инструкция для фронтендеров

Этот документ описывает, как фронтенд-приложение взаимодействует с API TASKFLOW CRM: аутентификация, форматы запросов и ответов, ошибки, пагинация, типовые сценарии. Swagger-документация доступна на работающем приложении по адресу /docs/swagger.


1. Базовые сведения

Ниже в примерах базовый URL опущен: /project означает GET https://api.taskflow.thescript.agency/project.


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

Аутентификация — через внешний сервис Passport (SSO, OAuth2). Фронтенд сам не хранит пароли.

2.1. Начало входа (SSO redirect)

Клик по «Войти» на фронтенде (или прямое открытие):

GET /auth/login

Ответ: HTML-страница с мета-редиректом (через ~3 секунды) на https://passport.../auth/authorize?.... После входа на Passport пользователь возвращается на:

GET /auth/callback?code=...&state=...

API меняет code на токены и выставляет httpOnly-куки:

КукаНазначение
taskflow_access_tokenAccess-токен (JWT RS256), TTL по умолчанию 3600 c
taskflow_refresh_tokenRefresh-токен, TTL по умолчанию 2592000 c (~30 дней)
taskflow_oauth_stateЗащита CSRF на время SSO-потока (10 минут)

Затем редирект на FRONTEND_URL (куки выставляются на домен API).

Фронтенд не должен читать эти куки из JS (они httpOnly). Достаточно браузера: куки автоматически отправляются с запросами к API.

2.2. Авторизация запросов

Два способа (поддерживаются оба):

  1. Куки (рекомендуется для браузерных SPA): куки taskflow_access_token / taskflow_refresh_token уходят автоматически с каждым запросом (нужно настроить credentials: 'include' в fetch/axios).
  2. Заголовок (для мобильных/серверных клиентов):
Authorization: Bearer <access_token>

2.3. Обновление токена (refresh)

Если access-токен истёк — API сам попытается обновить его через refresh-токен из куки (или заголовка Cookie), выставит новые куки и продолжит обработку запроса. Клиент обычно не получает 401 из-за истечения токена, если refresh-кука жива.

2.4. Выход

GET /auth/logout

API проксирует запрос в Passport, удаляет куки токенов и возвращает результат Passport (статус и заголовки Set-Cookie).

2.5. Публичные маршруты

Не требуют аутентификации (и не блокируются RBAC):


3. Форматы ответов

3.1. Один объект — обёртка item

{
  "item": {
    "id": 1,
    "name": "Проект клиента",
    "type": "agency",
    "settings": {}
  }
}

3.2. Список — обёртка items + _meta

{
  "items": [
    { "id": 1, "name": "Проект A" },
    { "id": 2, "name": "Проект B" }
  ],
  "_meta": {
    "total": 2,
    "page": 1,
    "limit": 20,
    "pages": 1
  }
}

3.3. Успех без тела

{ "message": "Project deleted" }

3.4. Ошибка — обёртка error

{
  "error": {
    "code": 422,
    "message": "Validation failed",
    "details": {
      "errors": {
        "name": ["Необходимо заполнить «name»."]
      }
    }
  }
}

details появляется, только если есть; структура details:


4. Пагинация

Все списковые эндпоинты (…/index, …/list и т.п.) поддерживают:

ПараметрТипПо умолчаниюОграничения
pageint1≥ 1
limitint201–1000

Пример: GET /task?page=2&limit=50.

Ответ содержит _meta (см. выше). Страниц: ceil(total / limit).


5. Коды ответов

КодЗначение
200Успех (включая создание/обновление/удаление)
302Редирект (SSO login/callback)
400Некорректный запрос
401Не аутентифицирован (нет/просрочен токен)
403Доступ запрещён (RBAC / права внутри проекта)
404Не найдено
405Метод не поддерживается
409Конфликт (например, сущность уже существует)
410Gone (ресурс удалён)
422Ошибка валидации
500Внутренняя ошибка

Точная карта «исключение → код» — в core/exceptions.md.


6. CORS

API отвечает на OPTIONS (preflight) без аутентификации. Фронтенд на другом домене должен слать OPTIONS-запросы с нужными заголовками; API поддерживает это через маршрут OPTIONS <any:.*>.


7. Типовые сценарии (примеры запросов)

7.1. Список проектов пользователя

GET /project
Cookie: taskflow_access_token=...
{ "items": [ { "id": 3, "name": "Личный проект пользователя #12", "type": "personal", "settings": {} } ], "_meta": { "total": 1, "page": 1, "limit": 20, "pages": 1 } }

7.2. Создать проект

POST /project
Content-Type: application/json

{ "name": "Проект клиента", "type": "agency", "settings": {} }

7.3. Доски проекта

GET /project/3/board
GET /project/3/board       # после создания доски:

7.4. Колонки доски

GET  /board/5/column
POST /board/5/column                # {"title": "В работе"}
PUT  /board/column/12               # {"title": "In Progress"}
POST /board/5/column/reorder        # {"columnIds": [12, 13, 11]}
DELETE /board/column/14

7.5. Задачи

GET  /task?limit=50&page=1
POST /task                          # создать
PUT  /task/100                      # обновить
POST /task/100/move-to-column       # {"columnId": 12}
POST /task/100/assign               # {"assigneeId": 7}
POST /task/100/restore              # восстановить из удалённых
DELETE /task/100                    # мягкое удаление
DELETE /task/100/hard               # жёсткое удаление (только с правами)

7.6. Тайм-трекинг

POST /time-interval/start           # {"taskId": 100}
POST /time-interval/stop            # {"taskId": 100}
POST /time-interval                 # ручной интервал: {"taskId":100,"startedAt":"...","endedAt":"...","duration":...}
GET  /time-interval?taskId=100
GET  /time-interval/daily-summary?date=2026-03-01
GET  /task/100/time-summary

7.7. Комментарии к задаче

GET  /task/100/comment
POST /task/100/comment              # {"text": "..."}
PUT  /comment/55
DELETE /comment/55

7.8. Стикеры

GET  /sticker
POST /sticker                       # создать стикер
GET  /task/100/sticker              # стикеры задачи
POST /task/100/sticker              # {"stickerId": 3}
DELETE /task/100/sticker/3

7.9. Участники и приглашения

GET    /project/3/member
POST   /project/3/member            # {"userId": 7, "role": "member"}
PUT    /project/3/member/7/role     # {"role": "manager"}
DELETE /project/3/member/7
POST   /project/3/invite            # {"email": "...", "role": "member"}
POST   /invitation/accept           # {"token": "..."} (см. модуль projects)
DELETE /project/3/invitation

7.10. RBAC (роли/разрешения — обычно админка)

GET    /roles
GET    /users
GET    /users/7
POST   /user-roles                  # {"userId": 7, "roleId": 2}
DELETE /user-roles/15
GET    /rbac/permissions
POST   /rbac/roles/2/permissions/5  # выдать разрешение роли
DELETE /rbac/roles/2/permissions/5

7.11. Обратная связь

POST /feedback/rating               # {"speed":5,"functionality":4,"design":5,"usability":4}
POST /feedback/idea                 # {"type":"feature","title":"...","description":"..."}
GET  /feedback/idea
GET  /feedback/stats

8. Обработка ошибок на фронтенде

  1. Проверять response.ok / HTTP-статус.
  2. При 401 — если есть refresh-кука, повторить запрос один раз (API сам обновил токен, если это возможно); иначе показать «Войдите в систему» и редирект на /auth/login.
  3. При 422 — показать поля из error.details.errors у соответствующих полей формы.
  4. При 403 — показать сообщение «Недостаточно прав» (проверить, что пользователь действительно участник/владелец).
  5. При 404 — «Не найдено» (ресурс удалён или нет доступа).
  6. При 5xx — общее сообщение, в dev можно показать error.details.trace.

Идемпотентность: POST-операции не идемпотентны (создают новые сущности); PUT/DELETE — идемпотентны.


9. Советы и ограничения


10. Где взять полный контракт