Pixora API Reference

API & Інтеграція

Повний довідник та документація для роботи з API платформою Pixora.

Поточне середовище

Усі приклади запитів нижче автоматично використовують цей базовий URL.

https://pixora-ashy-iota.vercel.app

Тестування у Postman

Завантажте готову колекцію зі всіма налаштованими маршрутами платформи.

Завантажити JSON Колекцію

Пам'ятка для інтеграції:

  • Єдиний API URL: Усі запити мають направлятись на https://pixora-ashy-iota.vercel.app або ваш локальний порт.
  • CORS політика: Браузер вимагає коректних origin заголовків. Для локальної розробки порт повинен бути дозволений у whitelist бекенду.
  • Авторизаційні Cookies (credentials): Для всіх захищених /api/admin/* роутів у клієнтському fetch обов'язково вказуйте credentials: 'include'.
  • Postman: Перед імпортом колекції вкажіть змінну середовища {{baseUrl}}.

Authentication & Profile

POST/api/auth/register
Public

Реєстрація нового фотографа

Request Body (JSON)
{
  "email": "user@example.com",
  "password": "securepassword",
  "name": "Іван Коваленко"
}
Response (200 OK)
{
  "id": "uuid",
  "email": "user@example.com",
  "name": "Іван Коваленко"
}
POST/api/auth/login
Public

Вхід та встановлення сесійної куки

Request Body (JSON)
{
  "email": "user@example.com",
  "password": "securepassword"
}
Response (200 OK)
{
  "id": "uuid",
  "email": "user@example.com"
}
POST/api/auth/logout
Session Cookie

Вихід та видалення сесійної куки

Response (200 OK)
{ "success": true }
GET/api/auth/me
Session Cookie

Отримання даних поточного користувача

Response (200 OK)
{
  "id": "uuid",
  "email": "user@example.com",
  "tier": "PRO"
}
GET/api/admin/profile
Session Cookie

Отримати профіль фотографа (налаштування бренду, нікнейм, контакти)

Response (200 OK)
{
  "name": "Іван Коваленко",
  "studioName": "Kovalenko Studio",
  "handle": "kovalenko",
  "bio": "Весільний фотограф",
  "phone": "+380501234567",
  "instagram": "@ivan_photo",
  "telegram": "@ivan_photo",
  "website": "https://kovalenko.com",
  "customFooter": "© 2026 Kovalenko Studio",
  "watermarkEnabled": true,
  "avatarUrl": "https://pub-xxx.r2.dev/branding/avatar.webp",
  "logoUrl": "https://pub-xxx.r2.dev/branding/logo.png",
  "subscriptionTier": "PRO"
}
PATCH/api/admin/profile
Session Cookie

Оновлення профілю та брендингу (нікнейм handle вимагає тариф PRO/STUDIO)

Request Body (JSON)
{
  "name": "Іван Коваленко",
  "studioName": "Kovalenko Studio",
  "handle": "kovalenko",
  "phone": "+380501234567",
  "instagram": "@ivan_photo",
  "telegram": "@ivan_photo",
  "website": "https://kovalenko.com",
  "customFooter": "© 2026 Kovalenko Studio",
  "watermarkEnabled": true
}
Response (200 OK)
{
  "success": true,
  "handle": "kovalenko"
}
GET/api/admin/profile/check-handle
Session Cookie

Миттєва перевірка доступності персонального нікнейму (?handle=xxx)

Response (200 OK)
{
  "available": true,
  "handle": "kovalenko"
}
POST/api/admin/upload-brand-asset
Session Cookie

Завантаження брендового ресурсу (аватар 512×512 WebP / логотип 800×400 PNG) з Magic Bytes валідацією та санітизацією Sharp

Request Body (JSON)
// Підтримує FormData або JSON Base64
const formData = new FormData();
formData.append("type", "avatar"); // або "logo"
formData.append("file", fileInput.files[0]);
Response (200 OK)
{
  "success": true,
  "publicUrl": "https://pub-xxx.r2.dev/branding/avatar-uuid.webp",
  "key": "branding/avatar-uuid.webp",
  "width": 512,
  "height": 512,
  "size": 42150,
  "format": "webp"
}
GET/api/admin/proxy-image
Session Cookie

Безпечний серверний проксі для кадрування/редактора (обхід CORS, захист від Canvas Tainting, пряме S3-читання)

Response (200 OK)
// Повертає чистий бінарний потік зображення з заголовками:
// Content-Type: image/webp
// Access-Control-Allow-Origin: *

Admin Galleries

GET/api/admin/galleries
Session Cookie

Список усіх галерей фотографа

Response (200 OK)
[
  {
    "id": "uuid",
    "title": "Весілля Анни",
    "status": "DRAFT",
    "coverUrl": "..."
  }
]
GET/api/admin/galleries/[id]/analytics
Session Cookie

Статистика переглядів та завантажень

Response (200 OK)
{
  "views": 142,
  "downloads": 5,
  "favorites": 12
}
GET/api/admin/galleries/[id]/download
Session Cookie

Завантажити повний архів усіх фото (генерація ZIP)

Response (200 OK)
{
  "downloadUrl": "https://s3.amazonaws.com/temp-zip-url.zip"
}
POST/api/admin/galleries/[id]/sections
Session Cookie

Керування розділами (наприклад: "Ранок нареченої", "Церемонія")

Request Body (JSON)
{
  "name": "Ранок нареченої"
}
Response (200 OK)
{
  "id": "section-uuid",
  "name": "Ранок нареченої"
}

Photos Management

POST/api/admin/galleries/[id]/photos
Session Cookie

Пряме завантаження фотографій у галерею

Request Body (JSON)
// Формат: multipart/form-data
// Поле "file": <Файл зображення (JPEG, PNG)>
// Поле "sectionId" (опціонально): <ID розділу>

const formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("sectionId", "uuid");
Response (200 OK)
{
  "id": "photo-uuid",
  "url": "https://...",
  "filename": "IMG_001.jpg"
}
POST/api/admin/galleries/[id]/photos/upload-url
Session Cookie

Генерація Presigned URL для прямого завантаження в S3 (для великих файлів)

Request Body (JSON)
{
  "filename": "IMG_001.jpg",
  "contentType": "image/jpeg",
  "size": 5242880
}
Response (200 OK)
{
  "uploadUrl": "https://s3...",
  "photoId": "uuid"
}
DELETE/api/admin/galleries/[id]/photos/[photoId]
Session Cookie

Видалити одне фото

Response (200 OK)
{ "success": true }
DELETE/api/admin/galleries/[id]/photos/batch
Session Cookie

Масове видалення фотографій

Request Body (JSON)
{
  "photoIds": ["uuid-1", "uuid-2"]
}
Response (200 OK)
{ "success": true, "deletedCount": 2 }
POST/api/admin/galleries/[id]/photos/process
Session Cookie

Запуск фонової обробки (водяні знаки, ресайз)

Request Body (JSON)
{
  "photoIds": ["uuid-1", "uuid-2"]
}
Response (200 OK)
{ "jobId": "job-uuid", "status": "processing" }

Client Access & Selections

GET/api/client/portfolio/[handle]
Public

Публічна персональна сторінка-портфоліо фотографа (PRO / STUDIO)

Response (200 OK)
{
  "photographer": {
    "name": "Іван Коваленко",
    "studioName": "Kovalenko Studio",
    "handle": "kovalenko",
    "avatarUrl": "https://pub-xxx.r2.dev/branding/avatar.webp",
    "subscriptionTier": "PRO"
  },
  "galleries": [
    {
      "id": "uuid",
      "title": "Summer Wedding",
      "slug": "summer-wedding",
      "photoCount": 120,
      "coverUrl": "https://..."
    }
  ],
  "totalGalleries": 1
}
GET/api/client/galleries/by-slug
Public

Отримання клієнтської галереї за красивим персональним посиланням (?handle=xxx&slug=yyy)

Response (200 OK)
{
  "gallery": {
    "id": "uuid",
    "title": "Summer Wedding",
    "clientName": "Anna & Michael",
    "photos": [...]
  }
}
POST/api/client/g/[accessToken]/lock
Token

Блокування або розблокування доступу клієнтом (пін-код або пароль)

Request Body (JSON)
{
  "pin": "1234"
}
PATCH/api/client/g/[accessToken]/photos/[photoId]
Token

Лайк / зняття лайка на фото (додавання до обраного)

Request Body (JSON)
{
  "favorite": true
}
POST/api/client/galleries/[id]/selections
Token

Відправка фінальної вибірки фото клієнтом фотографу

Request Body (JSON)
{
  "clientName": "Анна",
  "clientEmail": "anna@example.com",
  "photoIds": ["uuid-1", "uuid-2"],
  "comment": "Зробіть тепліші кольори"
}
Response (200 OK)
{ "success": true, "selectionId": "uuid" }
GET/api/client/galleries/[id]/download
Token

Завантаження архіву клієнтом (враховує налаштування скачування)

Response (200 OK)
{ "downloadUrl": "https://..." }
POST/api/client/galleries/[id]/download-token
Token

Генерація токена для безпечного скачування (Anti-hotlink)

Request Body (JSON)
{
  "email": "anna@example.com"
}
Response (200 OK)
{ "token": "abc123xyz" }
GET/api/client/galleries/[id]/photos/[photoId]/download
Token

Завантаження окремого фото клієнтом

GET/api/admin/galleries/[id]/selections
Session Cookie

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

Response (200 OK)
[
  {
    "clientName": "Анна",
    "photoCount": 42,
    "status": "PENDING"
  }
]
DELETE/api/admin/galleries/[id]/selections/[selectionId]
Session Cookie

Видалення клієнтської вибірки

Response (200 OK)
{ "success": true }
GET/api/admin/galleries/[id]/selections/[selectionId]/export
Session Cookie

Експорт відбору для Adobe Lightroom в 1 клік (?format=txt|csv|json, тариф PRO/STUDIO)

Response (200 OK)
// format=txt: повертає список імен для пошуку в Lightroom
// format=json:
[
  { "id": "uuid", "originalName": "IMG_001.CR3", "fileSize": 25000000 }
]

Billing & Subscription Tiers

POST/api/admin/billing/checkout
Session Cookie

Створити Stripe Checkout Session (Тарифи: PRO $19/mo, STUDIO $39/mo)

Request Body (JSON)
{
  "tier": "PRO",
  "interval": "month"
}
Response (200 OK)
{
  "url": "https://checkout.stripe.com/..."
}
POST/api/admin/billing/portal
Session Cookie

Генерація посилання на Stripe Portal для керування карткою та підпискою

Response (200 OK)
{
  "url": "https://billing.stripe.com/..."
}
GET/api/admin/billing/status
Session Cookie

Поточний статус підписки, ліміт сховища (5 ГБ / 250 ГБ / 1 ТБ) та активні галереї

Response (200 OK)
{
  "tier": "PRO",
  "active": true,
  "expiresAt": "2026-12-31T00:00:00Z",
  "usedBytes": 42949672960,
  "limitBytes": 268435456000,
  "activeGalleriesCount": 12
}
POST/api/admin/billing/sync-session
Session Cookie

Синхронізація сесії після успішного повернення зі Stripe

Response (200 OK)
{ "success": true }
POST/api/admin/billing/sync-storage
Session Cookie

Перерахунок та синхронізація використаного місця згідно тарифного ліміту

Response (200 OK)
{
  "usedBytes": 42949672960,
  "limitBytes": 268435456000,
  "percentage": 16.0
}
POST/api/webhooks/stripe
Public

Обробник подій Stripe (checkout, invoice, customer.subscription.*)