Как загрузить ваш каталог для SiteChat
Если вы используете 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/batch | POST | Создаёт или полностью заменяет до 50 товаров в одном запросе |
/merchant/products | POST | Создаёт или полностью заменяет один товар |
/merchant/products | GET | Считывает один импортированный товар по source и external_id |
/merchant/products | PATCH | Частично обновляет один товар (read-merge-write) |
/merchant/products | DELETE | Мягко архивирует товар (status=archived) |
/merchant/products/list | GET | Постранично выводит импортированные товары для таблиц в админке |
/merchant/products/images | POST | Загружает изображение товара и возвращает публичный HTTPS URL |
/merchant/collections | GET / POST | Выводит список или создаёт ручные коллекции |
/merchant/collections/{id} | GET / PUT / DELETE | Считывает, заменяет или архивирует одну коллекцию |
/merchant/inventory | GET | Выводит список строк остатков (количества товаров и вариантов) |
/merchant/inventory/adjust | POST | Устанавливает отслеживаемое количество для товара или варианта |
Успешное сохранение товаров просит Shoply пересобрать индекс магазина. Пока эта пересборка не завершится, ответы будут показывать index_status: "pending". Затем опубликованные товары появятся как в индексе товаров, так и в данных знаний, используемых в чате SiteChat.
Кто может использовать эти API?
- Ваш магазин должен быть аккаунтом SiteChat (
app_platformis 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:
{
"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 вместо этого отправляет вашу активную админскую сессию:
{
"store_key": "YOUR_SITECHAT_STORE_KEY",
"admin_auth_token": "YOUR_SITECHAT_ACCESS_TOKEN"
}access_token принимается как псевдоним для admin_auth_token.
Параметр запроса store_key должен совпадать с заголовком. Храните секреты владельца только в переменных окружения на стороне сервера — никогда не в скрипте витрины, URL или публичном репозитории.
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
{
"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 символов. Товары, созданные через формы в админке, по умолчанию получают sourceadmin.- Идентичность товара — это комбинация магазина, source и внешнего ID. Batch- и одиночные
POSTupsert-запросы — это полные замены, а не патчи: пропущенные необязательные поля очищаются. Для частичных обновлений используйтеPATCH. - Пакеты содержат 1–50 товаров и максимум 2,000,000 байт в запросе. Проверенный JSON каждого товара ограничен 128,000 байтами, максимум с 250 вариантами.
- Для цен предпочтительно использовать десятичные строки. Валюта — это трёхбуквенный код в верхнем регистре.
- URL товаров и изображений должны быть HTTP(S). Импорт не загружает эти URL за вас.
- Используйте публичные
metafieldsдля поисковых характеристик товара (аналог метаполей товаров Shopify в SiteChat). Значения должны быть простыми строками. Устаревшийattributesпринимается как псевдоним. Приватныеmetadataтовара больше не поддерживаются. - Товары со статусом
draftиarchivedне включаются в следующий опубликованный индекс. Распроданные опубликованные товары остаются в индексе с прикреплённой информацией о наличии. - Ручные коллекции хранят название, описание, статус и список вхождений товаров (
source+external_id). Умные/основанные на правилах коллекции в этом релизе не поддерживаются.
Пример успешного ответа
{
"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
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), чтобы исключить товар из следующего опубликованного индекса; жёсткое удаление в этом релизе отсутствует.
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:
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 и удаляет встроенные метаданные.
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.
