<!-- Canonical: https://docs.shopstory.live/docs/guide/architecture -->

# Формат запросов и ответов

## Базовый адрес и версии

Публичные эндпоинты только для чтения доступны на `https://app.shopstory.live`.

Версия в URL зависит от семейства ресурсов:

- `/v3/streams` и `/v3/translation/quick-state` — каталог и состояние трансляций;
- `/v2/mini-player/*` — выбор live или записи для товара.

Не заменяйте `/v2` на `/v3` механически.

## JSON-конверт

Ответ API обычно имеет три верхнеуровневых поля:

```json
{
  "status": 200,
  "serverTime": "2025-01-15T10:15:30.000Z",
  "body": {}
}
```

| Поле | Назначение |
| --- | --- |
| `status` | Результат операции внутри ShopStory API |
| `serverTime` | Серверное время в UTC, ISO 8601 |
| `body` | Данные, пустое состояние или описание ошибки |

## Два уровня результата

Проверяйте HTTP-код и `status` в JSON независимо. У некоторых `/v3/*` валидационная ошибка передаётся с HTTP `200` и `status: 400` внутри конверта.

validation-error.json

```json
{
  "status": 400,
  "body": {
    "error": "invalid",
    "message": "invalid applicationId"
  },
  "serverTime": "2025-01-15T10:15:30.000Z"
}
```

Если для товара нет подходящего видео, mini-player возвращает пустое состояние: HTTP `200`, `body.status: "no_active_stream"`, `body.stream: null`.

**HTTP, конверт и содержимое ответа**К следующей проверке переходите только после успеха предыдущей.

1. **1. HTTP**

  **Ответ не получен или HTTP с ошибкой**

  Обработайте сетевую или HTTP-ошибку.

  **Успешный HTTP-код**

  Ответ получен. Теперь проверьте JSON и результат операции.

  При успешном HTTP
2. **2. JSON-конверт**

  **Невалидный ответ или ошибка API**

  Например, HTTP `200` и `payload.status: 400` — ошибка API.

  **JSON валиден, `status` успешен**

  Проверьте `body` по схеме конкретного endpoint.

  При успешном результате в конверте
3. **3. Данные конкретного ресурса**

  **`stream-state`: `body.status`**

  `active` — есть данные для открытия плеера.

  `no_active_stream` и `stream: null` — штатно скрыть точку входа в видео.

  **Каталог: коллекции в `body`**

  Пустые массивы допустимы. Отсутствующая обязательная коллекция — невалидный ответ.

Структура `body` зависит от endpoint. `active` подтверждает наличие данных для открытия, а первый кадр и продолжение воспроизведения проверяются отдельно.

Обрабатывайте ответ в таком порядке:

unwrap-shopstory-response.js

```javascript
async function readShopStoryResponse(response) {
  if (!response.ok) {
    throw new Error(`ShopStory HTTP ${response.status}`);
  }

  const payload = await response.json();

  if (!Number.isInteger(payload.status)) {
    throw new Error('Invalid ShopStory response envelope');
  }

  if (payload.status < 200 || payload.status >= 300) {
    throw new Error(payload.body?.message || `ShopStory status ${payload.status}`);
  }

  return payload.body;
}
```

После распаковки отдельно проверяйте состояние ресурса, например `body.status` у mini-player.

## Идентификаторы

`applicationId`, `streamId`, `id`, `feedProductId`, `feedProductGroupId` и `vendorCode` обрабатывайте как строки:

- не приводите их к JavaScript `Number`;
- не удаляйте ведущие нули;
- не извлекайте бизнес-смысл из формата;
- используйте значение из согласованного товарного контракта без преобразований.

`applicationId` выбирает проект и его конфигурацию. Он передаётся в браузерных запросах и сам по себе не авторизует запрос. Браузерный доступ работает только для origins, зарегистрированных ShopStory.

## Совместимость клиента

- Игнорируйте незнакомые необязательные поля.
- Не считайте порядок полей частью контракта.
- Различайте отсутствующее поле, `null`, пустой массив и пустую строку.
- Устанавливайте собственный тайм-аут и обрабатывайте сетевой сбой отдельно от ответа API.
- Не подтверждайте изменение корзины по одному HTTP `200` или визуальному состоянию плеера: проверяйте результат в commerce-системе ритейлера.

Полные схемы и обязательные поля находятся в [OpenAPI](<https://docs.shopstory.live/docs/reference/openapi>). Рабочий запрос: [Quickstart](<https://docs.shopstory.live/docs/guide/quickstart>).
