14 KiB
REST API (Swagger-Style)
Общая информация
- Базовый URL:
http://0.0.0.0:8080/api/v1 - Форматы: все конечные точки принимают и возвращают
application/json, если не указан инойContent-Type. - Часовой формат: даты/время сериализуются в
ISO_LOCAL_DATE_TIME, например2024-05-12T13:45:00. - JWT-аутентификация: приватные маршруты располагаются под
/api/v1/admin/**и требуют заголовокAuthorization: Bearer <token>изPOST /admin/login. - Ошибки: при валидационных/авторизационных ошибках сервер возвращает код
4xxс телом{"error": "описание"}.
Базовые схемы
| Схема | Описание |
|---|---|
| Page | Обёртка пагинации: items (список сущностей T), total (общее количество), limit (число элементов на странице), offset (смещение). |
| ServiceCategoryDTO | { id: number, name: string, slug: string }. |
| ServiceDTO | { id, title, slug, description, priceFrom: number|null, imageUrl: string|null, status: "PUBLISHED"|"DRAFT"|"ARCHIVED", category: ServiceCategoryDTO|null, createdAt, updatedAt }. |
| NewsDTO | { id, title, slug, summary, content, status: "draft"|"published"|"archived", imageUrl: string|null, publishedAt: string|null }. |
| LeadDTO | { id, fullName, email, phone: string|null, createdAt }. |
| AdminDTO | { id, username, createdAt }. |
Администраторы и аутентификация
| Метод | Путь | Требуется JWT | Описание |
|---|---|---|---|
| POST | /admin/login |
Нет | Получение JWT токена. |
| GET | /admin/password_hash |
Нет | Вспомогательный эндпойнт для генерации bcrypt-хэша. |
| GET | /admin |
Да | Получить профиль текущего администратора. |
| POST | /admin |
Да | Создать нового администратора. |
| PUT | /admin/{id}/password |
Да | Сменить пароль администратора. |
| DELETE | /admin/{id} |
Да | Удалить администратора. |
POST /api/v1/admin/login
Тело запроса
| Поле | Тип | Обязательно | Примечание |
|---|---|---|---|
username |
string | да | Мин. 3 символа ([A-Za-z0-9_.-]). |
password |
string | да | Мин. 8 символов. |
Ответ 200
| Поле | Тип | Примечание |
|---|---|---|
id |
number | Идентификатор администратора. |
username |
string | Введённое имя. |
token |
string | JWT access token. |
tokenType |
string | Всегда Bearer. |
expiresInMinutes |
number | Время жизни токена (минуты). |
Пример:
{
"id": 1,
"username": "admin",
"token": "eyJhbGciOi...",
"tokenType": "Bearer",
"expiresInMinutes": 60
}
GET /api/v1/admin/password_hash
Query-параметры
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
password |
string | нет | Исходный пароль. По умолчанию admin123. |
Ответ 200: { "pass": "<bcrypt-hash>" }.
GET /api/v1/admin
Возвращает AdminDTO текущего пользователя по subject токена.
POST /api/v1/admin
Тело запроса – AdminRegisterRequest:
| Поле | Тип | Обязательно | Примечание |
|---|---|---|---|
username |
string | да | Уникальное имя (регулярное выражение как при логине). |
password |
string | да | Мин. 8 символов. |
Ответ 201 – AdminRegisterResponse:
| Поле | Тип |
|---|---|
id |
number |
username |
string |
PUT /api/v1/admin/{id}/password
Параметры пути: id – numeric ID.
Тело запроса – ChangePasswordRequest:
| Поле | Тип | Обязательно | Примечание |
|---|---|---|---|
currentPassword |
string | да | Текущий пароль (проверяется через bcrypt). |
newPassword |
string | да | Новый пароль, минимум 8 символов. |
Ответ 200: { "updated": true }.
DELETE /api/v1/admin/{id}
Удаляет администратора. Ответ 200 OK: { "deleted": true }.
Лиды (заявки)
| Метод | Путь | JWT | Описание |
|---|---|---|---|
| POST | /leads |
Нет | Оставить заявку. |
| GET | /admin/leads |
Да | Список лидов с фильтром. |
| GET | /admin/leads/{id} |
Да | Получить лид по ID. |
| DELETE | /admin/leads/{id} |
Да | Удалить лид. |
POST /api/v1/leads
Тело запроса – LeadCreateRequest:
| Поле | Тип | Обязательно | Примечание |
|---|---|---|---|
fullName |
string | да | Имя клиента. |
email |
string | да | Проверяется регуляркой ^[\\w.+-]+@[\\w.-]+\\.[A-Za-z]{2,}$. |
phone |
string | нет | Любой формат, сохраняется как строка. |
Ответ 201: { "id": 42 }.
GET /api/v1/admin/leads
Query-параметры
| Имя | Тип | По умолчанию | Описание |
|---|---|---|---|
limit |
integer | 50 | Размер страницы. |
page |
integer | 1 | Должна быть ≥ 1, иначе 400. |
q |
string | null | Поиск по fullName, email, phone. |
Ответ 200: Page<LeadDTO>.
Пример элемента: { "id": 7, "fullName": "Иван Иванов", "email": "ivan@example.com", "phone": "+79001234567", "createdAt": "2024-05-05T10:34:00" }.
GET /api/v1/admin/leads/{id}
Параметр id (long). Ответ – LeadDTO.
DELETE /api/v1/admin/leads/{id}
Ответ { "deleted": true }.
Новости
| Метод | Путь | JWT | Описание |
|---|---|---|---|
| GET | /news |
Нет | Пагинированный список опубликованных новостей. |
| GET | /news/{slug} |
Нет | Получение новости по slug. |
| GET | /admin/news |
Да | Список всех новостей. |
| POST | /admin/news |
Да | Создать новость. |
| PUT | /admin/news/{slug} |
Да | Обновить новость. |
| POST | /admin/news/{slug}/publish |
Да | Публикация новости. |
| DELETE | /admin/news/{slug} |
Да | Удалить новость. |
GET /api/v1/news
Query-параметры: limit (default 20), page (default 1, ≥1).
Ответ: Page<NewsDTO>, где items отсортированы по publishedAt у опубликованных записей.
GET /api/v1/news/{slug}
Возвращает NewsDTO опубликованной новости (если slug неактивен — 404).
GET /api/v1/admin/news
Query-параметры: limit (50), page (1, ≥1).
Ответ: Page<NewsDTO> (включая черновики).
POST /api/v1/admin/news
Тело запроса – NewsCreate:
| Поле | Тип | Обязательно | Примечание |
|---|---|---|---|
title |
string | да | Заголовок. |
slug |
string | да | Уникальный slug (валидация – на уровне базы). |
summary |
string | да | Краткое описание. |
content |
string | да | Полный текст (HTML/Markdown). |
status |
string | нет | draft (по умолчанию) | published | archived. |
imageUrl |
string | нет | Ссылка на обложку. |
Ответ: { "id": <number> }.
PUT /api/v1/admin/news/{slug}
Тело запроса – NewsUpdateRequest (все поля опциональны, как в NewsCreate). Ответ { "updated": true }.
POST /api/v1/admin/news/{slug}/publish
Без тела. Устанавливает status = "published", publishedAt = now. Ответ { "published": true }.
DELETE /api/v1/admin/news/{slug}
Ответ { "deleted": true }.
Категории услуг
| Метод | Путь | JWT | Описание |
|---|---|---|---|
| GET | /service-categories |
Нет | Публичный список категорий. |
| GET | /service-categories/{slug} |
Нет | Получить категорию по slug. |
| GET | /admin/service-categories |
Да | Пагинация категорий. |
| POST | /admin/service-categories |
Да | Создать категорию. |
| PUT | /admin/service-categories/{id} |
Да | Обновить категорию. |
| DELETE | /admin/service-categories/{id} |
Да | Удалить категорию. |
GET /api/v1/service-categories
Возвращает массив ServiceCategoryDTO.
GET /api/v1/service-categories/{slug}
Ответ – ServiceCategoryDTO.
GET /api/v1/admin/service-categories
Query-параметры: limit (100), offset (0).
Ответ: список ServiceCategoryDTO (без обёртки).
POST /api/v1/admin/service-categories
Тело запроса – CategoryCreateRequest (name, slug – обязательные). Ответ { "id": <number> }.
PUT /api/v1/admin/service-categories/{id}
Тело – CategoryUpdateRequest (оба поля опциональны). Ответ { "updated": true }.
DELETE /api/v1/admin/service-categories/{id}
Ответ { "deleted": true }.
Услуги
| Метод | Путь | JWT | Описание |
|---|---|---|---|
| GET | /services |
Нет | Список опубликованных услуг с фильтрами. |
| GET | /services/{slug} |
Нет | Одна услуга по slug. |
| GET | /admin/services |
Да | Список всех услуг. |
| POST | /admin/services |
Да | Создать услугу. |
| PUT | /admin/services/{id} |
Да | Обновить услугу. |
| PUT | /admin/services/{id}/status |
Да | Изменить статус. |
| DELETE | /admin/services/{id} |
Да | Удалить услугу. |
GET /api/v1/services
Query-параметры
| Имя | Тип | По умолчанию | Описание |
|---|---|---|---|
limit |
integer | 20 | Размер страницы. |
page |
integer | 1 | ≥ 1. |
q |
string | null | Поиск по title и description (case-insensitive). |
category |
string | null | slug категории. |
minPrice |
number | null | Минимальная цена (decimal). |
maxPrice |
number | null | Максимальная цена (decimal). |
Ответ: Page<ServiceDTO>.
Пример элемента:
{
"id": 10,
"title": "Разработка мобильного приложения",
"slug": "mobile-dev",
"description": "Полный цикл разработки",
"priceFrom": 150000.0,
"imageUrl": "https://cdn.example/app.jpg",
"status": "PUBLISHED",
"category": { "id": 2, "name": "Разработка", "slug": "development" },
"createdAt": "2024-04-01T09:15:00",
"updatedAt": "2024-05-05T12:00:00"
}
GET /api/v1/services/{slug}
Ответ – ServiceDTO (включая category). Ошибка 404, если slug не найден или услуга скрыта.
GET /api/v1/admin/services
Query-параметры
| Имя | Тип | По умолчанию | Описание |
|---|---|---|---|
limit |
integer | 50 | Размер страницы. |
page |
integer | 1 | ≥ 1. |
q |
string | null | Фильтр по названию/описанию. |
status |
string | null | PUBLISHED | DRAFT | ARCHIVED. |
Ответ: Page<ServiceDTO> (включая черновики).
POST /api/v1/admin/services
Тело запроса – ServiceCreateRequest:
| Поле | Тип | Обязательно | Примечание |
|---|---|---|---|
title |
string | да | Название услуги. |
slug |
string | да | Уникальный slug (^[a-z0-9-]{3,}$). |
description |
string | да | Детальное описание. |
priceFrom |
string | нет | Десятичное число, например "1499.99". |
imageUrl |
string | нет | URL изображения. |
status |
string | нет | По умолчанию PUBLISHED. |
categoryId |
number | нет | ID существующей категории. |
Ответ 201: { "id": <number> }.
PUT /api/v1/admin/services/{id}
Тело – ServiceUpdateRequest (все поля опциональны, формат как в ServiceCreateRequest). Ответ { "updated": true }.
PUT /api/v1/admin/services/{id}/status
Тело запроса – StatusRequest с полем status (PUBLISHED|DRAFT|ARCHIVED). Ответ { "updated": true }.
DELETE /api/v1/admin/services/{id}
Ответ { "deleted": true }.
Пример структуры Page
{
"items": [ /* сущности */ ],
"total": 125,
"limit": 20,
"offset": 0
}