API наличия товаров в магазинах для Shopping Assistant

Если покупатель спрашивает, есть ли товар в конкретном магазине или в каких магазинах поблизости он доступен, Shopping Assistant нужны актуальные данные из системы клиента. Это особенно важно при большом числе магазинов и частом изменении остатков. Региональные варианты in_stock в товарном фиде через lng подходят для более стабильных зон обслуживания, но обновление фида не гарантирует наличие на момент вопроса в отдельной точке.

Для такого сценария передайте Gravity Field справочник магазинов и предоставьте серверный HTTPS API для актуальной проверки товара по SKU и магазину. Справочник проще сначала передать файлом; если магазины часто добавляются или меняются, его можно подключить через API. Gravity Field вызывает API остатков во время диалога и использует его ответ как источник сведений о наличии. Адреса ручек, авторизацию, лимиты и правила интерпретации данных согласуйте при подключении. Примеры ниже показывают ожидаемые возможности и формат обмена; сами по себе они не включают проверку остатков в Shopping Assistant.

Товарный фид продолжает передавать карточки и атрибуты товаров. sku во внешнем API должен точно совпадать с sku в фиде. Общее in_stock из фида не подтверждает наличие в конкретном магазине.

Какие данные нужны

Возможность Для чего нужна
Справочник магазинов Сопоставить название, адрес, город или район из сообщения покупателя со стабильным storeId; при нескольких совпадениях предложить уточнить точку.
Проверка по sku и storeId Ответить, доступен ли один или несколько товаров в выбранных магазинах сейчас.
Поиск магазинов с товаром Ответить на вопрос «где есть» в заданном городе или радиусе без перебора всего справочника магазинов.

Справочник магазинов

Справочник можно передать двумя способами. Рекомендуем начать с файла: это быстрее для первого запуска, а если магазины меняются редко, файла может быть достаточно и в дальнейшем. API справочника имеет смысл подключать, когда состав и данные точек меняются часто.

В обоих вариантах для каждой точки нужны стабильный storeId, название, полный адрес, город, координаты и признак действующего магазина. Название и адрес нужны для ответа покупателю, а storeId — для проверки наличия. Не используйте свободный текст адреса как идентификатор точки. Если найдено несколько подходящих магазинов, ассистент должен уточнить выбор до проверки конкретной точки.

Вариант 1. Файл справочника

Передайте полный CSV-файл в UTF-8 по согласованной ссылке, доступной для скачивания Gravity Field. Одна строка — один магазин; при обновлении публикуйте полный актуальный список с теми же storeId для существующих точек. Периодичность обновления согласуйте при подключении. Файл подходит и как первый этап, даже если позже справочник будет передаваться через API.

storeId,name,address,city,latitude,longitude,active
kzn-014,Магазин — Kazan Mall,"Казань, ул. Примерная, 1",Казань,55.767,49.137,true

Вариант 2. API справочника

Ручка поиска должна принимать текстовое описание магазина или географическое ограничение и возвращать подходящие точки. Если магазинов много, поддержите ограничение числа результатов и постраничную выдачу.

Для поиска по местоположению вместо query передавайте city либо latitude, longitude и radiusKm. Для следующей страницы повторите те же условия и передайте cursor из предыдущего nextCursor.

Пример адреса ручки: POST https://shop.example.com/api/assistant/stores/search.

{
  "requestId": "8f2b1c0a-6c1d-4a0e-9f3b-2d4e5a6b7c8d",
  "query": "Казань, ТЦ Kazan Mall",
  "limit": 10
}
{
  "requestId": "8f2b1c0a-6c1d-4a0e-9f3b-2d4e5a6b7c8d",
  "stores": [
    {
      "storeId": "kzn-014",
      "name": "Магазин — Kazan Mall",
      "address": "Казань, ул. Примерная, 1",
      "city": "Казань",
      "latitude": 55.767,
      "longitude": 49.137,
      "active": true
    }
  ],
  "nextCursor": null
}

Проверка остатков

Ручка должна принимать массив SKU и массив storeId в одном запросе. Верните результат для каждой запрошенной пары, чтобы отсутствие записи нельзя было принять за нулевой остаток. Размеры массивов и максимальное число пар в запросе согласуйте при подключении.

Пример адреса ручки: POST https://shop.example.com/api/assistant/stock/check.

{
  "requestId": "8f2b1c0a-6c1d-4a0e-9f3b-2d4e5a6b7c8d",
  "skus": ["1066109"],
  "storeIds": ["kzn-014", "kzn-027"]
}
{
  "requestId": "8f2b1c0a-6c1d-4a0e-9f3b-2d4e5a6b7c8d",
  "items": [
    {
      "sku": "1066109",
      "storeId": "kzn-014",
      "status": "available",
      "availableQuantity": 3,
      "pickupAvailable": true,
      "updatedAt": "2026-09-24T10:15:30Z"
    },
    {
      "sku": "1066109",
      "storeId": "kzn-027",
      "status": "out_of_stock",
      "availableQuantity": 0,
      "pickupAvailable": false,
      "updatedAt": "2026-09-24T10:15:30Z"
    }
  ]
}

status должен различать как минимум available (можно купить), out_of_stock (товар продаётся в точке, но сейчас недоступен), not_carried (точка не продаёт этот товар) и unknown (достоверных данных нет). availableQuantity передавайте, если доступен остаток к продаже, а не только физический остаток на складе. pickupAvailable — отдельный признак возможности самовывоза: наличие на полке само по себе не гарантирует оформление заказа. updatedAt показывает время актуальности данных по каждой паре.

Если SKU или storeId неизвестен, верните явный результат для пары со статусом unknown либо согласованную ошибку входных данных. Не превращайте неизвестное значение или технический сбой в out_of_stock.

Поиск магазинов, где товар доступен

Для вопроса «в каких магазинах есть товар» нужна серверная выборка по SKU и географической области: например, по коду города или по координатам и радиусу. Верните только действующие магазины с доступным товаром, их storeId, адрес, статус, признак самовывоза и updatedAt. Поддержите limit и nextCursor, чтобы число магазинов не определяло размер одного ответа. Если подходящих точек нет, верните пустой список с 200; если данные получить не удалось — ошибку. Географическое ограничение и максимальный радиус согласуйте при подключении.

Пример адреса ручки: POST https://shop.example.com/api/assistant/stock/find.

{
  "requestId": "8f2b1c0a-6c1d-4a0e-9f3b-2d4e5a6b7c8d",
  "sku": "1066109",
  "city": "Казань",
  "limit": 10
}

В ответе верните items[] со сведениями о магазине и наличии в том же формате, что при проверке по storeId, и nextCursor для следующей страницы. Для продолжения запроса передайте полученный курсор вместе с теми же sku и географическим ограничением.

{
  "requestId": "8f2b1c0a-6c1d-4a0e-9f3b-2d4e5a6b7c8d",
  "items": [
    {
      "sku": "1066109",
      "storeId": "kzn-014",
      "name": "Магазин — Kazan Mall",
      "address": "Казань, ул. Примерная, 1",
      "status": "available",
      "pickupAvailable": true,
      "updatedAt": "2026-09-24T10:15:30Z"
    }
  ],
  "nextCursor": null
}

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

  • Передавайте канонический storeId выбранного пользователем магазина в runtimeContext.ctx.attributes.storeId с каждым запросом /shopping/generate, если точка уже известна. Обработку этого поля согласуйте при подключении коннектора. ctx.lng описывает зону обслуживания для фида и поиска, а не заменяет актуальную проверку остатков в точке.
  • Если пользователь назвал магазин в сообщении, сопоставьте его со справочником. При конфликте с выбранной в интерфейсе точкой уточните, о каком магазине спрашивает пользователь. Для фразы «в этом магазине» используйте подтверждённый магазин из контекста диалога.
  • SKU берите из ctx.data на странице PRODUCT, из точного артикула в сообщении или из уже выбранной карточки. Если товар или вариант нельзя определить однозначно, уточните его до проверки.
  • В ответе указывайте конкретный магазин и опирайтесь на результат свежей проверки. Для статуса unknown, устаревших данных, тайм-аута или ошибки API сообщайте, что наличие подтвердить не удалось. Не выводите наличие в точке из общего in_stock фида.

Перед подключением согласуйте, что именно означает available: наличие к продаже, возможность резервирования или доступность самовывоза. Данные о сроках новой поставки и доставке требуют дополнительных полей или отдельных API — текущий остаток сам по себе не отвечает на эти вопросы.

Требования к подключению

  • Для API остатков и API справочника: HTTPS, метод POST и JSON; вызовы выполняются между серверами Gravity Field и клиента. Авторизацию, адреса ручек и допустимые IP-адреса согласуйте с командой Gravity Field.
  • Передавайте requestId в запросе и возвращайте его в ответе для диагностики. Ручки только читают данные; повторный вызов не должен менять остатки или резервировать товар.
  • Согласуйте тайм-аут, целевое время ответа, нагрузку и допустимый возраст данных. Проверка выполняется во время диалога и должна укладываться в бюджет ответа ассистента.
  • Разделяйте пустой достоверный результат (200), ошибку запроса (400), ошибку авторизации (401), временный сбой (5xx) и тайм-аут. При сбое ассистент не должен сообщать, что товара нет.
  • Проверьте сценарии с магазином из текста и из контекста, несколькими совпавшими магазинами, отсутствием товара, неизвестным SKU, пустой географической выдачей и ошибкой API через тестовые диалоги с trafficType: "test".

Связанные материалы

Shopping Assistant
/shopping_assistant/

Shopping Assistant API
/shopping_assistant/api_reference/

API поиска и получения товаров
/shopping_assistant/byoa_search_api/