Довідник REST API

DocPlatform надає RESTful JSON API за адресою /api/v1/. Усі ендпоінти вимагають автентифікації, якщо не вказано інше.

Базова URL

http://localhost:3000/api/v1

Автентифікація

Більшість ендпоінтів вимагають JWT токен доступу в заголовку Authorization:

Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Отримайте токени через ендпоінти login або OIDC.

Життєвий цикл токенів

Токен Час життя Призначення
Токен доступу 15 хвилин Автентифікація API
Токен оновлення 30 днів Отримання нових токенів доступу

Ендпоінти автентифікації

Реєстрація

POST /api/v1/auth/register

Створення нового облікового запису. Перший користувач стає Super Admin.

Запит:

{
  "name": "Jane Smith",
  "email": "[email protected]",
  "password": "secure-password-here"
}

Відповідь: 201 Created

{
  "user": {
    "id": "01HJK...",
    "name": "Jane Smith",
    "email": "[email protected]",
    "role": "superadmin"
  },
  "access_token": "eyJhbG...",
  "refresh_token": "eyJhbG...",
  "expires_in": 900
}

Вхід

POST /api/v1/auth/login

Автентифікація за допомогою email та пароля.

Запит:

{
  "email": "[email protected]",
  "password": "secure-password-here"
}

Відповідь: 200 OK

{
  "access_token": "eyJhbG...",
  "refresh_token": "eyJhbG...",
  "expires_in": 900
}

Помилки:

Код Опис
401 Невірні облікові дані
429 Забагато спроб входу (обмеження частоти)

Оновлення токена

POST /api/v1/auth/refresh

Обмін токена оновлення на новий токен доступу. Токен оновлення ротується (старий інвалідується).

Запит:

{
  "refresh_token": "eyJhbG..."
}

Відповідь: 200 OK

{
  "access_token": "eyJhbG...",
  "refresh_token": "eyJhbG...",
  "expires_in": 900
}

Запит на скидання пароля

POST /api/v1/auth/password-reset

Запит токена скидання пароля. З налаштованим SMTP надсилається email. Без SMTP токен виводиться в stdout.

Запит:

{
  "email": "[email protected]"
}

Відповідь: 200 OK (завжди, незалежно від існування email — запобігає перерахуванню)

Підтвердження скидання пароля

POST /api/v1/auth/password-reset/confirm

Встановлення нового пароля за допомогою токена скидання.

Запит:

{
  "token": "reset-token-here",
  "new_password": "new-secure-password"
}

Відповідь: 200 OK


Ендпоінти контенту

Усі ендпоінти контенту прив’язані до робочого простору.

Список сторінок

GET /api/v1/workspaces/{workspace_id}/pages

Повертає всі сторінки, які поточний користувач має право переглядати.

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

Параметр Тип Опис
parent_id string Фільтр за батьківською сторінкою (для деревоподібної навігації)
tag string Фільтр за тегом
published boolean Фільтр за статусом публікації
limit int Максимум результатів (за замовчуванням: 100)
offset int Зсув для пагінації

Відповідь: 200 OK

{
  "pages": [
    {
      "id": "01HJK...",
      "title": "Getting Started",
      "slug": "getting-started",
      "description": "Install and configure DocPlatform.",
      "path": "getting-started.md",
      "tags": ["guide"],
      "published": true,
      "access": "public",
      "created_at": "2026-03-08T10:00:00Z",
      "updated_at": "2025-01-16T14:30:00Z",
      "author_id": "01HJK..."
    }
  ],
  "total": 42,
  "limit": 100,
  "offset": 0
}

Отримання сторінки

GET /api/v1/workspaces/{workspace_id}/pages/{page_id}

Відповідь: 200 OK

{
  "id": "01HJK...",
  "title": "Getting Started",
  "slug": "getting-started",
  "description": "Install and configure DocPlatform.",
  "path": "getting-started.md",
  "content": "# Getting Started\n\nThis guide walks you through...",
  "content_hash": "sha256:abc123...",
  "tags": ["guide"],
  "published": true,
  "access": "public",
  "parent_id": null,
  "created_at": "2026-03-08T10:00:00Z",
  "updated_at": "2025-01-16T14:30:00Z",
  "author_id": "01HJK..."
}

Помилки:

Код Опис
403 Недостатньо прав
404 Сторінку не знайдено

Створення сторінки

POST /api/v1/workspaces/{workspace_id}/pages

Запит:

{
  "title": "New Page",
  "slug": "new-page",
  "content": "# New Page\n\nContent here...",
  "description": "Description for search and SEO.",
  "tags": ["guide"],
  "published": false,
  "parent_id": null
}

Відповідь: 201 Created — повертає повний об’єкт сторінки.

Оновлення сторінки

PUT /api/v1/workspaces/{workspace_id}/pages/{page_id}

Запит:

{
  "title": "Updated Title",
  "content": "# Updated Title\n\nUpdated content...",
  "content_hash": "sha256:abc123..."
}

Поле content_hash забезпечує оптимістичне управління паралельністю. Якщо хеш не збігається з поточною версією, сервер повертає 409 Conflict.

Відповідь: 200 OK — повертає оновлений об’єкт сторінки.

Помилки:

Код Опис
409 Невідповідність хешу контенту (виявлено одночасне редагування)

Видалення сторінки

DELETE /api/v1/workspaces/{workspace_id}/pages/{page_id}

Відповідь: 204 No Content


Ендпоінти робочих просторів

Список робочих просторів

GET /api/v1/workspaces

Повертає робочі простори, учасником яких є поточний користувач.

Створення робочого простору

POST /api/v1/workspaces

Потребує роль Super Admin.

Запит:

{
  "name": "API Docs",
  "slug": "api-docs",
  "git_remote": "[email protected]:org/api-docs.git",
  "git_branch": "main"
}

Учасники робочого простору

GET /api/v1/workspaces/{workspace_id}/members
POST /api/v1/workspaces/{workspace_id}/invitations
DELETE /api/v1/workspaces/{workspace_id}/members/{user_id}
PUT /api/v1/workspaces/{workspace_id}/members/{user_id}/role

Пошук

GET /api/v1/workspaces/{workspace_id}/search?q={query}

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

Параметр Тип Опис
q string Пошуковий запит (обов’язковий)
tag string Фільтр за тегом
limit int Максимум результатів (за замовчуванням: 20)

Відповідь: 200 OK

{
  "results": [
    {
      "page_id": "01HJK...",
      "title": "Git Integration",
      "description": "Bidirectional git sync...",
      "path": "guides/git-integration.md",
      "score": 0.95,
      "highlights": [
        "...bidirectional <mark>git sync</mark> lets your team..."
      ]
    }
  ],
  "total": 5,
  "query": "git sync",
  "took_ms": 12
}

Результати фільтруються за правами доступу — користувачі бачать лише сторінки, до яких мають доступ.


Синхронізація Git

Запуск синхронізації

POST /api/v1/workspaces/{workspace_id}/sync

Ручний запуск git pull + реконсиляції. Потребує роль Admin.

Відповідь: 200 OK

{
  "status": "completed",
  "changes": {
    "added": 2,
    "updated": 1,
    "deleted": 0
  }
}

Ендпоінти webhook

POST /api/v1/webhooks/github
POST /api/v1/webhooks/gitlab
POST /api/v1/webhooks/bitbucket

Ці ендпоінти отримують payload push подій від провайдерів git хостингу. Заголовок автентифікації не потрібен — вони перевіряються за допомогою спільного секрету GIT_WEBHOOK_SECRET.


Стан

Ці ендпоінти не вимагають автентифікації.

GET /health    → 200 OK { "status": "ok" }
GET /ready     → 200 OK { "status": "ready", "db": "ok", "search": "ok" }

Формат помилок

Усі відповіді з помилками використовують єдиний формат:

{
  "error": {
    "code": "CONFLICT",
    "message": "Content hash mismatch. The page was modified by another user.",
    "details": {
      "current_hash": "sha256:def456...",
      "provided_hash": "sha256:abc123..."
    }
  }
}

Поширені коди помилок

HTTP Код Опис
400 BAD_REQUEST Невірне тіло запиту або параметри
401 UNAUTHORIZED Відсутня або невірна автентифікація
403 FORBIDDEN Недостатньо прав
404 NOT_FOUND Ресурс не знайдено
409 CONFLICT Виявлено одночасну модифікацію
429 RATE_LIMITED Забагато запитів
500 INTERNAL_ERROR Помилка сервера (перевірте логи)

Пагінація

Ендпоінти списків контенту використовують пагінацію на основі курсора з ULID для стабільних результатів навіть при додаванні або видаленні контенту.

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

Параметр Тип За замовчуванням Опис
cursor string ULID останнього елемента з попередньої сторінки. Опустіть для першої сторінки.
limit int 20 Кількість результатів на сторінку (максимум: 100)

Метадані відповіді:

{
  "data": [...],
  "next_cursor": "01HJK...",
  "has_more": true
}

Передайте next_cursor як параметр cursor у наступному запиті. Коли has_more дорівнює false, ви досягли кінця.


Завантаження ресурсів

POST /api/v1/workspaces/{workspace_id}/assets

Завантаження зображень та файлів у робочий простір. Ресурси зберігаються в директорії assets/ робочого простору та фіксуються в git, якщо синхронізація увімкнена.

Запит: multipart/form-data з полем file.

Обмеження:

Обмеження Значення
Максимальний розмір файлу 10 МБ
Прийнятні типи PNG, JPG, GIF, SVG, WebP, PDF

Відповідь: 201 Created

{
  "path": "assets/screenshot-2025-01-15.png",
  "url": "/api/v1/workspaces/{workspace_id}/assets/screenshot-2025-01-15.png",
  "size": 245760,
  "content_type": "image/png"
}

Вирішення конфліктів

Список конфліктів

GET /api/v1/workspaces/{workspace_id}/conflicts

Відповідь: 200 OK

{
  "workspace_id": "01HJK...",
  "sync_status": "conflict",
  "conflicts": [
    {
      "path": "guides/editor.md",
      "ours_hash": "abc123...",
      "theirs_hash": "def456...",
      "page_id": "01HJK...",
      "timestamp": "20250115T103045Z"
    }
  ]
}

Завантаження версії конфлікту

GET /api/v1/conflicts/{page_id}/{timestamp}/{version}

Параметр version — це або ours (локальна), або theirs (віддалена).

Відповідь: 200 OK з Content-Type: text/markdown — необроблений вміст файлу.

Вирішення конфлікту

POST /api/v1/conflicts/{page_id}/{timestamp}/resolve

Видаляє артефакти конфлікту після ручного вирішення.

Відповідь: 200 OK

{
  "message": "Conflict resolved",
  "page_id": "01HJK..."
}

WebSocket

Отримання ticket для підключення

POST /api/v1/auth/ws-ticket

WebSocket з’єднання використовують шаблон одноразового ticket, щоб уникнути розкриття JWT токенів у URL.

Відповідь: 200 OK

{
  "ticket": "random-ticket-value",
  "expires_in": 30
}

Ticket дійсний 30 секунд та може бути використаний лише один раз. Підключення через:

ws://localhost:3000/ws?ticket={ticket}

Серверні події

Тип події Payload Коли
page-created {workspace_id, path, actor} Створено нову сторінку
page-updated {workspace_id, path, actor} Сторінку змінено
page-deleted {workspace_id, path, actor} Сторінку видалено
presence-join {workspace_id, user_id} Користувач підключився
presence-leave {workspace_id, user_id} Користувач відключився (таймаут 90 с)
sync-status {workspace_id, status} Зміна статусу синхронізації git
conflict-detected {workspace_id, path} Виявлено конфлікт злиття git
bulk-sync {workspace_id, changed_count, paths[]} Синхронізовано кілька файлів (>20 файлів)

Клієнтські повідомлення

{"type": "subscribe", "workspace_id": "01HJK..."}
{"type": "unsubscribe", "workspace_id": "01HJK..."}

Заголовки безпеки

DocPlatform встановлює наступні заголовки на всі відповіді:

Заголовок Значення
X-Content-Type-Options nosniff
X-Frame-Options DENY
Content-Security-Policy default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
X-Request-ID ULID (унікальний для кожного запиту, включається у відповіді з помилками та логи)

Опублікована документація додатково встановлює:

Заголовок Значення
Cache-Control public, max-age=300
ETag Хеш контенту відрендереної сторінки

Обмеження частоти

Категорія ендпоінтів Community Edition
Операції читання 100 / хвилину на користувача
Операції запису 20 / хвилину на користувача
Пошук 30 / хвилину на користувача
Автентифікація (login, register, reset) 5 / хвилину на IP
Git webhook 10 / хвилину на робочий простір
Опублікована документація (публічна) 1 000 / хвилину на IP

Відповіді з обмеженням частоти включають заголовки Retry-After (секунди) та X-RateLimit-Reset (Unix timestamp).