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

# Каталог эфиров — `GET /v3/streams`

Эндпоинт возвращает запланированные, текущие и завершённые эфиры вместе с товарами, ведущими и категориями, которые нужны для их отображения.

## Запрос

```http
GET https://app.shopstory.live/v3/streams?applicationId=<application-id>&limit=20&offset=0
Accept: application/json
```

| Параметр | Обязательно | Описание |
| --- | --- | --- |
| `applicationId` | Да | Выданный ShopStory идентификатор приложения. Он выбирает область данных и не авторизует запрос. |
| `feedProductId` | Нет | Стабильный строковый идентификатор товара из согласованного фида. Ведущие нули значимы. |
| `categoryId` | Нет | Числовой идентификатор категории эфира. |
| `status` | Нет | `planned`, `online` или `finished`. |
| `limit` | Нет | Размер страницы. `0` отключает пагинацию; значения выше `100` сервер обрабатывает как `100`. |
| `offset` | Нет | Смещение от начала набора. Передавайте вместе с положительным `limit`. |

Все переданные фильтры объединяются по логике `AND`.

## Конверт ответа

Успешный ответ:

```json
{
  "status": 200,
  "serverTime": "2025-01-15T10:00:00.000Z",
  "body": {
    "plannedStreams": [],
    "availableStreams": [],
    "products": [],
    "streamers": [],
    "categories": [],
    "total": 0
  }
}
```

`plannedStreams` содержит эфиры со статусом `planned` по возрастанию `plannedDate`. `availableStreams` сначала содержит эфиры `online`, затем записи `finished`; внутри каждой группы элементы отсортированы по `startDate` от новых к старым.

### Пагинация и `total`

- Без `status` пагинация применяется только к `availableStreams`; `plannedStreams` возвращается полностью.
- При `status=planned` пагинация применяется к `plannedStreams`, а `availableStreams` пуст.
- При `status=online` или `status=finished` пагинация применяется к соответствующей части `availableStreams`, а `plannedStreams` пуст.
- `total` — размер выбранного набора до применения `limit` и `offset`.
- `total` присутствует, если передан хотя бы один фильтр либо параметр пагинации. В запросе без фильтров, `limit` и `offset` поле может отсутствовать.

Offset pagination не создаёт snapshot. Новый эфир или смена статуса между запросами может сдвинуть элементы на следующих страницах. Для длительно открытого каталога периодически загружайте первую страницу заново и объединяйте элементы по строковому `id`; не используйте `offset` как механизм инкрементальной синхронизации.

## Модель эфира

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` | string | Идентификатор эфира. |
| `application` | string | Идентификатор приложения. |
| `name`, `description` | string | Название и описание эфира. |
| `streamer` | string | Идентификатор ведущего из `streamers`. |
| `status` | string | `planned`, `online` или `finished`. |
| `plannedDate`, `startDate`, `endDate` | string \| null | Временные метки ISO 8601. Отсутствующая дата передаётся как `null`. |
| `previewImages` | array | Изображения эфира. |
| `products` | string[] | Внутренние идентификаторы товаров из `products`. |
| `productFeedIds` | string[] | Идентификаторы этих товаров из фида. Поле может отсутствовать, если сопоставлений нет. |
| `categories` | integer[] | Идентификаторы категорий. |

## Модель товара

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` | string | Внутренний идентификатор ShopStory. |
| `application` | string | Идентификатор приложения. |
| `name` | string | Название товара. |
| `feedProductAvailable` | boolean | Доступность из последней успешно обработанной версии товарного фида. |
| `feedProductId` | string | Идентификатор из фида; может отсутствовать для ранее загруженных данных. |
| `vendorCode` | string | Артикул продавца; может отсутствовать. |
| `feedProductGroupId` | string | Идентификатор группы или варианта; может отсутствовать. |
| `url` | string | URL карточки товара. |
| `previewImages` | array | Изображения товара. |

Идентификаторы товаров являются строками. Не преобразуйте их в числовой тип: это может удалить ведущие нули или снизить точность.

Доступность из фида

`feedProductAvailable` — снимок, полученный при синхронизации фида. Поле не подтверждает остаток в конкретном магазине, и отдельного endpoint проверки остатков в Public API нет.

Остаток выбранного магазина в Web SDK приходит от обработчика наличия на стороне сайта ритейлера. При интеграции через Public API эту проверку выполняет интерфейс клиента: [Наличие товара и остатки](<https://docs.shopstory.live/docs/guide/product-availability>).

`streamers` содержит `id`, `application` и профиль ведущего. `categories` содержит `id`, `application` и `name`. Полная машинно-читаемая схема опубликована в [OpenAPI](<https://docs.shopstory.live/docs/reference/openapi>).

## Ошибки

Для `/v3/streams` валидационные и внутренние ошибки передаются в общем конверте при транспортном HTTP `200`. Проверяйте оба уровня: сначала возможность прочитать HTTP-ответ, затем верхнеуровневое поле `status`.

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

Не привязывайте обработку к точному тексту `message`. Для ветвления используйте `status` и `body.error`. Сетевой шлюз может вернуть собственный HTTP `4xx` или `5xx`, поэтому транспортные ошибки обрабатывайте отдельно.

## Карточка каталога и воспроизведение

**Ответ API → карточка каталога → полный плеер**Каталог рисует сайт, плеер открывает основной Web SDK. Интерфейс и контент в примере условные.

**`GET /v3/streams`**

`availableStreams` — live и записи.
`plannedStreams` — анонсы.

Данные карточки

Запись**Обзор косметики**Открыть плеер

**Карточка вашего сайта**

Название — `stream.name`, состояние — `stream.status`.

Клик «Открыть плеер»
`stream.id` → `streamId`

**Полный плеер ShopStory**

`showPlayer()` получает `streamId` и `clientId` — тот же `applicationId` проекта.

**Товар связывается отдельно от эфира**

`stream.products[]` → совпадающий `body.products[].id` → `product.feedProductId` в каталоге магазина.

Для перехода на PDP используйте `product.url`. Товарные ID сохраняйте строками, включая ведущие нули.

Анонсы можно показать в каталоге. В starter кнопка плеера доступна для `online` и `finished` на реальных данных; в fixture видео нет.

В [API starter](<https://docs.shopstory.live/downloads/shopstory-api-starter.zip>) есть `catalog.html` — запускаемый пример Public API + основного Web SDK. После распаковки выполните из папки starter:

```bash
python3 -m http.server 8080 --bind 127.0.0.1
```

Откройте `http://127.0.0.1:8080/catalog.html` и нажмите «Открыть fixture». Появятся карточка `Тестовая запись`, статус `finished` и товар `0001001`. Видео в fixture нет; кнопка player отключена и SDK не загружается.

Пример связывает данные так:

| Данные ответа | Использование |
| --- | --- |
| `availableStreams` и `plannedStreams` | Карточки эфиров и записей |
| `stream.products[]` → `body.products[].id` | Список товаров выбранного эфира |
| `product.feedProductId` | Строковый ID клиента, без преобразования в число |
| `product.url` | Переход к товару; пример допускает только HTTPS-ссылку |
| `stream.id` | Аргумент `streamId` для `ShopStorySDK.showPlayer()` |

Для реального прогона разместите starter на зарегистрированном test origin, введите выданный `applicationId` и нажмите «Запросить API». Выберите `online` или `finished` и нажмите «Открыть плеер». SDK получает `clientId` этого же проекта и `streamId` карточки; playback URL не собирается из отдельных полей.

Убедитесь, что появился первый кадр и видео продолжает воспроизводиться. Promise `showPlayer()` подтверждает только внутреннюю инициализацию. Этот метод не принимает cart handlers из `show()`; [контракт и ограничения](<https://docs.shopstory.live/docs/guide/web-sdk-reference#showplayerparams>) описаны отдельно.

До сетевого прогона подтвердите [consent-сценарий](<https://docs.shopstory.live/docs/guide/analytics#consent-%D0%B8-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5>). Для production примените CSP проекта к коду примера. При пустом ответе или ошибке страница показывает соответствующее состояние, не подменяя его fixture.

## Связанные разделы

- [Требования к товарному фиду](<https://docs.shopstory.live/docs/guide/feed-requirements>)
- [Mini-player](<https://docs.shopstory.live/docs/guide/mini-player>)
- [OpenAPI и Postman](<https://docs.shopstory.live/docs/reference/openapi>)
