4. API-контракт

API — источник данных для тем и для внешних (headless) клиентов. Объекты в ответах совпадают с объектной моделью.

Модель авторизации

Три типа секретов, три уровня доверия:

Секрет Кто держит Куда ходит
🔑 X-Api-Key (приватный) сервер (рантайм витрины / BFF) в ядро; браузер его НЕ видит
🎫 публичный токен браузер (встройка виджета/бот) только в BFF, не в ядро
🍪 cookie покупатель (браузер) сессия покупателя в рантайме

Тема НЕ ходит в ядро напрямую и не знает ключа. Тема (её JS) дергает same-origin эндпоинты своего рантайма → рантайм добавляет X-Api-Key и идёт в ядро. То есть для автора темы API — это /api/... на своём же домене, без ключей.

браузер (тема) ──/api/... (same-origin, без ключа)──► рантайм витрины ──X-Api-Key──► ядро

⚠️ сейчас: часть read-данных отдаётся как проксируемый HTML, часть — как JSON (/api/shop/...). Цель — весь read как чистый JSON/SSR-data, чтобы тема и headless-клиент били по одному контракту.

Read — чтение (для рендера)

Базовый префикс со стороны темы — same-origin /api/shop/… (рантайм подставляет slug тенанта; в примерах ниже {slug} со стороны ядра).

Метод Путь Отдаёт
GET /api/shop/{slug} shop (брендинг, флаги, категории, доставка, оплата)
GET /api/shop/{slug}/catalog?type=&categoryId=&q=&page=&pageSize= список product (карточные поля) + пагинация; варианты схлопнуты
GET /api/shop/{slug}/item/{id} полный product (галерея, варианты, состав)
GET /api/shop/{slug}/collections подборки (collection[])
GET /api/shop/{slug}/availability?serviceId=&staffId=&date= availability (слоты) ⚠️ сейчас через виджет

Пагинация: page (1..), pageSize. Поиск: q (по имени/артикулу). Фильтр: type=product|service, categoryId.

Write — действия

Метод Путь Действие
GET /api/shop/{slug}/cart текущая корзина (cart)
POST /api/shop/{slug}/cart/add {itemId, quantity} → добавить
PUT /api/shop/{slug}/cart/item {itemId, quantity} → изменить (0 = убрать)
POST /api/shop/{slug}/cart/clear очистить
POST /api/shop/{slug}/order оформить заказ {contact, delivery, payment, comment}{orderNumber, token, statusUrl, confirmationUrl?}
GET /api/shop/{slug}/order/{token} статус заказа (order)
POST /api/shop/{slug}/order/{token}/pay (пере)оплатить онлайн
POST /api/shop/{slug}/hold удержать слот ⚠️
POST /api/shop/{slug}/book оформить запись {serviceId, staffId, slot, contact, place} ⚠️

Аккаунт покупателя (OTP, единый на все магазины): /api/account/… — вход по коду (SMS/email), история заказов/записей.

Соглашения

Референс

Машинный контракт — OpenAPI/Swagger ядра (/swagger). Он остаётся источником истины по формам; этот документ — нарратив и «как задумано».

Что дальше