Как загрузить ваш каталог для SiteChat

A secure merchant key unlocks catalog upload APIs that send products and images into SiteChat search and chat

Если вы используете SiteChat на собственном сайте (не в магазине Shopify), вы можете отправлять структурированные записи о товарах в Shoply, чтобы покупатели могли находить их в чате SiteChat и в поиске товаров.

Эти эндпоинты используют тот же Settings → Store owner API secret, что и остальная часть Shoply Merchant API, а страница Product Catalog в админке SiteChat может вызывать их с вашим токеном доступа администратора, если вы вошли в систему. Магазины Shopify продолжают синхронизировать данные каталога через Shopify; эти маршруты загрузки доступны только для аккаунтов SiteChat, которые ещё не синхронизируют каталог Magento.

В админке SiteChat раздел Product Catalog открывает область в стиле Shopify с разделами Products, Collections и Inventory. Вы можете добавлять или редактировать товары, импортировать CSV/Excel, группировать товары в ручные коллекции и корректировать остатки на складе.

Какие API доступны?

APIМетодЧто делает
/merchant/products/batchPOSTСоздаёт или полностью заменяет до 50 товаров в одном запросе
/merchant/productsPOSTСоздаёт или полностью заменяет один товар
/merchant/productsGETСчитывает один импортированный товар по source и external_id
/merchant/productsPATCHЧастично обновляет один товар (read-merge-write)
/merchant/productsDELETEМягко архивирует товар (status=archived)
/merchant/products/listGETПостранично выводит импортированные товары для таблиц в админке
/merchant/products/imagesPOSTЗагружает изображение товара и возвращает публичный HTTPS URL
/merchant/collectionsGET / POSTВыводит список или создаёт ручные коллекции
/merchant/collections/{id}GET / PUT / DELETEСчитывает, заменяет или архивирует одну коллекцию
/merchant/inventoryGETВыводит список строк остатков (количества товаров и вариантов)
/merchant/inventory/adjustPOSTУстанавливает отслеживаемое количество для товара или варианта

Успешное сохранение товаров просит Shoply пересобрать индекс магазина. Пока эта пересборка не завершится, ответы будут показывать index_status: "pending". Затем опубликованные товары появятся как в индексе товаров, так и в данных знаний, используемых в чате SiteChat.

Кто может использовать эти API?

  • Ваш магазин должен быть аккаунтом SiteChat (app_platform is SiteChat).
  • Ключи магазина Shopify (включая любой домен *.myshopify.com) отклоняются.
  • Аутентификация должна использовать либо действительный секретный API-ключ владельца магазина, либо токен доступа администратора SiteChat для точного store_key в запросе.
  • Токены Shopify Admin API не могут вызывать эти маршруты.

Создавайте или ротируйте секрет владельца так же, как и для других интеграций Merchant API: How to Use the Shoply Merchant API. В админ-консоли SiteChat откройте Product Catalog, чтобы управлять товарами, коллекциями и остатками — или импортировать файл CSV или Excel — без необходимости самостоятельно управлять секретом.

Как работает аутентификация?

Из серверного коннектора

Вызывайте API из доверенного backend-сервиса по HTTPS. Поместите JSON-строку в заголовок Authorization:

json
{ "store_key": "YOUR_SITECHAT_STORE_KEY", "store_owner_api_secrete": "YOUR_STORE_OWNER_API_SECRET" }

store_owner_api_secrete — это публичное имя поля, включая историческое написание. store_owner_api_secret также принимается. Это не токен Bearer.

Из админки SiteChat

Страница Product Catalog вместо этого отправляет вашу активную админскую сессию:

json
{ "store_key": "YOUR_SITECHAT_STORE_KEY", "admin_auth_token": "YOUR_SITECHAT_ACCESS_TOKEN" }

access_token принимается как псевдоним для admin_auth_token.

Параметр запроса store_key должен совпадать с заголовком. Храните секреты владельца только в переменных окружения на стороне сервера — никогда не в скрипте витрины, URL или публичном репозитории.

bash
export SHOPLY_STORE_KEY="your-sitechat-store-key" export SHOPLY_STORE_OWNER_API_SECRETE="shoply_owner_key_example123.secret-value"

Как загрузить товары?

POST https://api.shoplyai.ai/merchant/products/batch?store_key=YOUR_SITECHAT_STORE_KEY

json
{ "source": "woocommerce-main", "products": [ { "external_id": "123", "title": "Trail shoes", "description": "Water-resistant hiking shoes.", "url": "https://example.com/products/trail-shoes", "currency": "USD", "price": "49.95", "original_price": "59.95", "available": true, "status": "published", "images": ["https://example.com/images/trail-shoes.jpg"], "categories": ["Footwear"], "metafields": {"material": "Leather"}, "variants": [ { "external_id": "124", "title": "Brown / 42", "sku": "TRAIL-BR-42", "price": "49.95", "available": true, "metafields": {"color": "Brown", "size": "42"} } ] } ] }

Обязательные поля и правила

  • Обязательные поля товара: external_id, title, url, currency, price и available. Значение status по умолчанию — published.
  • Необязательные данные об остатках: установите tracks_inventory в true и неотрицательное quantity у товара или варианта. После этого Shoply определяет наличие по остатку (quantity > 0) и сохраняет total_inventory для списков в админке.
  • source задаёт имя подключения каталога (не обязательно платформу). Используйте стабильное имя, например woocommerce-main. Допустимые символы: строчные буквы, цифры, подчёркивания и дефисы; до 64 символов. Товары, созданные через формы в админке, по умолчанию получают source admin.
  • Идентичность товара — это комбинация магазина, source и внешнего ID. Batch- и одиночные POST upsert-запросы — это полные замены, а не патчи: пропущенные необязательные поля очищаются. Для частичных обновлений используйте PATCH.
  • Пакеты содержат 1–50 товаров и максимум 2,000,000 байт в запросе. Проверенный JSON каждого товара ограничен 128,000 байтами, максимум с 250 вариантами.
  • Для цен предпочтительно использовать десятичные строки. Валюта — это трёхбуквенный код в верхнем регистре.
  • URL товаров и изображений должны быть HTTP(S). Импорт не загружает эти URL за вас.
  • Используйте публичные metafields для поисковых характеристик товара (аналог метаполей товаров Shopify в SiteChat). Значения должны быть простыми строками. Устаревший attributes принимается как псевдоним. Приватные metadata товара больше не поддерживаются.
  • Товары со статусом draft и archived не включаются в следующий опубликованный индекс. Распроданные опубликованные товары остаются в индексе с прикреплённой информацией о наличии.
  • Ручные коллекции хранят название, описание, статус и список вхождений товаров (source + external_id). Умные/основанные на правилах коллекции в этом релизе не поддерживаются.

Пример успешного ответа

json
{ "results": [ { "external_id": "123", "product_id": "sitechat_product::woocommerce-main::<sha256-of-external-id>", "status": "stored" } ], "index_status": "pending", "index_revision": 1 }

Shoply проверяет весь запрос целиком перед записью. HTTP 200 всё равно может содержать некоторые результаты в failed с error: "storage_error". Проверяйте каждый результат и повторяйте попытку для неудавшихся товаров. Если index_status имеет значение request_failed, сохранение прошло успешно, но индексация не была запланирована — повторите попытку и для уже сохранённых товаров.

Пример на Python

python
import json import os import requests store_key = os.environ["SHOPLY_STORE_KEY"] headers = { "Authorization": json.dumps({ "store_key": store_key, "store_owner_api_secrete": os.environ["SHOPLY_STORE_OWNER_API_SECRETE"], }) } response = requests.post( "https://api.shoplyai.ai/merchant/products/batch", params={"store_key": store_key}, headers=headers, json={ "source": "custom", "products": [{ "external_id": "123", "title": "Trail shoes", "url": "https://example.com/products/trail-shoes", "currency": "USD", "price": "49.95", "available": True, }], }, timeout=60, ) response.raise_for_status() result = response.json() failed = [item["external_id"] for item in result["results"] if item["status"] != "stored"] if failed: raise RuntimeError(f"Products need retry: {failed}") if result["index_status"] == "request_failed": raise RuntimeError("Products saved, but retry the batch to request indexing")

Как проверить импортированный товар?

GET https://api.shoplyai.ai/merchant/products?store_key=YOUR_SITECHAT_STORE_KEY&source=woocommerce-main&external_id=123

Используйте тот же заголовок Authorization. Ответ включает schema_version, updated_at, index_status и нормализованный product. Отсутствующие записи возвращают HTTP 404.

После того как фоновый индексатор опубликует пересборку, статус обратного чтения для каждого товара станет indexed, excluded (для товаров в статусе draft или archived) или limit_exceeded. Используйте GET /merchant/products/list для отображения списка в админке. Выполняйте мягкую архивацию через DELETE /merchant/products (или установите status в archived / draft), чтобы исключить товар из следующего опубликованного индекса; жёсткое удаление в этом релизе отсутствует.

python
record = requests.get( "https://api.shoplyai.ai/merchant/products", params={ "store_key": store_key, "source": "woocommerce-main", "external_id": "123", }, headers=headers, timeout=30, ) record.raise_for_status() print(record.json()["index_status"], record.json()["product"]["title"])

Можно ли загружать изображения товаров?

Да. Если изображение уже доступно по постоянному публичному HTTPS URL, укажите этот URL в списке images товара или в поле image варианта. Публичные HTTPS URL S3 работают. Сырые пути s3:// и краткоживущие подписанные URL — нет.

Чтобы Shoply размещал файл у себя, загрузите сырые байты изображения из вашего backend:

text
POST https://api.shoplyai.ai/merchant/products/images?store_key=YOUR_SITECHAT_STORE_KEY Content-Type: image/png

Отправляйте сырые байты файла, а не JSON, base64 или multipart form data. Поддерживаются JPEG, PNG и WebP, размером до 10 MiB и 20 миллионов пикселей. Анимированные изображения не поддерживаются. Shoply преобразует изображение в WebP и удаляет встроенные метаданные.

python
with open("trail-shoes.png", "rb") as image_file: response = requests.post( "https://api.shoplyai.ai/merchant/products/images", params={"store_key": store_key}, headers={**headers, "Content-Type": "image/png"}, data=image_file, timeout=60, ) response.raise_for_status() image_url = response.json()["url"]

HTTP 201 возвращает url, content_type, size_bytes, width и height. Загрузка одного только изображения не привязывает его к товару и не запрашивает индексацию. Включите возвращённый URL в полный объект товара и повторно отправьте его через /merchant/products/batch.

Если то же изображение загружается повторно для того же аккаунта, его URL используется повторно. Изменённое изображение получает новый URL. Эндпоинта для удаления изображений в этом релизе нет.

Когда товары появляются в чате и поиске?

После успешного сохранения пакета Shoply запрашивает фоновую пересборку индекса. Ответы показывают index_status: "pending", пока worker не опубликует новый индекс. Фиксированной гарантии по времени завершения нет.

  • Опубликованные товары попадают и в поиск товаров, и в данные знаний, используемые в чате SiteChat.
  • Товары в статусах draft и archived исключаются при следующей пересборке.
  • Если индексация не была запланирована (index_status: "request_failed"), повторите пакет для товаров, которые уже были успешно сохранены.

Какие ошибки можно ожидать?

HTTP statusЗначение
403Отсутствующий, недействительный, истёкший или отозванный секрет; неправильный магазин; или аккаунт не SiteChat
404Запрошенный импортированный товар не существует
413Запрос или изображение превышает ограничение по размеру
415При загрузке изображения использовался неподдерживаемый Content-Type
422Недопустимые поля, дублирующиеся ID, анимированные или слишком большие изображения, либо превышены ограничения модели
503Временная ошибка хранилища

Срок действия секретов истекает через 90 дней. Создайте замену в Settings → Store owner API secret до истечения срока и отзовите все секреты, которые вам больше не нужны. Тот же секрет также может вызывать эндпоинты аналитики, диалогов и базы знаний, описанные в руководстве по Merchant API.

Если вам нужна помощь с интеграцией, свяжитесь с Shoply AI.