http://localhost:8080/api/v1http://192.168.88.128/api/v1Authorization: Bearer <token>refresh_tokensuperadmin, moderator, landlord, executor, customer{
"error": "описание ошибки"
}
HTTP статусы: 400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), 404 (Not Found), 409 (Conflict), 422 (Validation Error), 500 (Internal Server Error)
// Запрос
{
"email": "user@example.com",
"password": "securePass123",
"role": "customer", // customer | landlord | executor
"name": "Иван Иванов"
}
// Ответ 201
{
"user": { "id": "uuid", "email": "...", "role": "customer", "created_at": "..." },
"access_token": "eyJ...",
"refresh_token": "eyJ..."
}
// Запрос
{
"email": "user@example.com",
"password": "securePass123"
}
// Ответ 200
{
"user": { ... },
"access_token": "eyJ...",
"refresh_token": "eyJ..."
}
refresh_token (httpOnly, устанавливается при login/register/refresh)Authorization: Bearer <access_token>Параметры запроса:
type: place | studio (по умолчанию оба)tags: ID тегов (можно несколько, напр. ?tags=portrait&tags=nature)min_rating: число 0-5features: ID характеристик (можно несколько)price_min, price_max: для студийbounds: sw_lat,sw_lng,ne_lat,ne_lng (область карты)limit: 1-100 (по умолчанию 20)sort: rating | created_at | distance (требует user_lat,user_lng)Ответ 200 (cursor-based pagination):
{
"data": [
{
"id": "uuid",
"type": "place",
"owner_id": "uuid",
"title": "Красивый парк",
"description": null,
"address": "Москва, Парковая 1",
"lat": 55.75,
"lng": 37.61,
"cover_image": "https://cdn.../uuid.jpg",
"access_info": null,
"status": "published",
"rating": 4.5,
"reviews_count": 12,
"hourly_rate": null,
"currency": "RUB",
"min_hours": 0,
"tags": [{ "id": "portrait", "name": "Портрет", "sort_order": 1 }],
"features": [{ "id": "parking", "name": "Парковка", "sort_order": 1 }],
"created_at": "2024-01-15T10:30:00Z"
}
],
"next_cursor": "base64encodedcursorstring",
"has_more": true
}
Ответ 200: Полная карточка PlaceCard / StudioCard
{
"id": "uuid",
"type": "studio",
"title": "Студия 'Свет'",
"description": "Профессиональная фотостудия...",
"address": "Москва, ул. Ленина 10, офис 5",
"lat": 55.75,
"lng": 37.61,
"cover_image": "https://cdn.../cover.jpg",
"access_info": "Метро 'Площадь Революции', 5 мин пешком. Парковка во дворе.",
"tags": [{ "id": "portrait", "name": "Портрет" }],
"features": [{ "id": "flash", "name": "Импульсные источники" }],
"hourly_rate": 1500,
"currency": "RUB",
"min_hours": 2,
"rating": 4.8,
"reviews_count": 24,
"status": "published",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-20T14:22:00Z"
}
Роли: customer (type=place), landlord (type=studio)
// Запрос
{
"type": "studio",
"title": "Новая студия",
"description": "Описание...",
"address": "Москва, ул. Новая 5",
"lat": 55.76,
"lng": 37.62,
"access_info": "Как добраться...",
"tags": ["portrait", "fashion"],
"features": ["flash", "cyclorama"],
"hourly_rate": 2000,
"currency": "RUB",
"min_hours": 3
}
// Ответ 201 — полный объект Place в статусе pending_moderation
Роли: Владелец, moderator, superadmin
pending_moderationРоли: Владелец (свои места), moderator, superadmin
owner_id == текущий пользователь || moderator || superadmindeleted_at)Роли: moderator, superadmin
// Запрос
{ "action": "approve", "comment": "Всё хорошо" }
// action: approve | reject | request_changes
Параметры: tags, min_rating, price_min, price_max, limit
Ответ 200: { "data": [ Service ] }
Ответ 200: Полный объект Service (с тегами)
Роль: executor
{
"title": "Портретная съемка в студии",
"description": "Профессиональная портретная съемка...",
"price": 5000,
"currency": "RUB",
"duration_minutes": 120,
"tags": ["portrait", "studio"]
}
publishedРоль: Владелец (свои услуги), moderator, superadmin
executor_id == текущий пользователь || moderator || superadminРоль: Владелец (свои услуги), moderator, superadmin
executor_id == текущий пользователь || moderator || superadminПубличный профиль
Обновление своего профиля
{
"name": "Новое имя",
"phone": "+79991234567",
"bio": "Фотограф с 10-летним стажем",
"avatar_url": "https://cdn.../avatar.jpg",
"country": "RU"
}
Роли: moderator, superadmin
Параметры: role, status, limit
Роли: superadmin (все), moderator (кроме superadmin/moderator)
{ "role": "customer", "status": "active" }
// status: active | banned | pending_verification
Роль: Любой авторизованный пользователь
{
"place_id": "uuid",
"start_time": "2024-02-01T10:00:00Z",
"end_time": "2024-02-01T14:00:00Z",
"comment": "Нужна циклорама"
}
hourly_rateСписок своих бронирований
Роль: Владелец брони
user_id == текущий пользователь// Параметры запроса
// ?target_type=place&target_id=uuid
// Ответ 200
{
"data": [
{
"id": "uuid",
"user_id": "uuid",
"target_type": "place",
"target_id": "uuid",
"rating": 5,
"text": "Отличное место",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"user": { "name": "Иван", "avatar_url": "https://cdn.../avatar.jpg" }
}
]
}
Роль: Любой авторизованный пользователь
{
"target_type": "place",
"target_id": "uuid",
"rating": 5,
"text": "Отличное место"
}
rating: 1-5text: опционально{ "user_id": "...", "lat": 55.75, "lng": 37.61 }Сервер рассылает всем подключённым клиентам список всех активных точек:
{ "visitors": [{ "user_id": "...", "lat": 55.75, "lng": 37.61 }] }
Ответ: Список тегов стилей съёмки
[{ "id": "portrait", "name": "Портрет", "category": "style" }, ...]
Ответ: Список характеристик мест
[{ "id": "flash", "name": "Импульсный свет", "category": "equipment" }, ...]
// Запрос
{ "content_type": "image/jpeg", "max_size_mb": 10 }
// Ответ
{ "upload_url": "https://s3...", "file_url": "https://cdn...", "fields": { "key": "...", "policy": "...", "signature": "..." } }
Планируется интеграция с CloudPayments (POST /webhooks/cloudpayments), но пока не реализована.