如何为 SiteChat 上传您的商品目录

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

如果您在自己的网站上使用 SiteChat(而不是 Shopify 商店),您可以将结构化的商品记录发送到 Shoply,以便购物者能够在 SiteChat 聊天和商品搜索中找到它们。

这些端点与其余 Shoply Merchant API 使用相同的 设置 → 店主 API 密钥,并且 SiteChat 管理后台中的 Product Catalog 页面可以使用您已登录的管理员访问令牌来调用它们。Shopify 商店会继续通过 Shopify 同步商品目录数据;这些上传路由仅适用于尚未同步 Magento 商品目录的 SiteChat 账户。

在 SiteChat 管理后台中,Product Catalog 会打开一个类似 Shopify 的区域,其中包含 Products、Collections 和 Inventory。您可以添加或编辑产品、导入 CSV/Excel、将产品分组到手动集合中,并调整库存数量。

有哪些 API 可用?

API方法作用
/merchant/products/batchPOST在一次请求中创建或完全替换最多 50 个产品
/merchant/productsPOST创建或完全替换一个产品
/merchant/productsGET通过 source 和 external_id 读取一个已导入的产品
/merchant/productsPATCH部分更新一个产品;替换变体或 metafields 需要使用来自 GET 的版本
/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 为 SiteChat)。
  • Shopify 商店密钥(包括任何 *.myshopify.com 域名)会被拒绝。
  • 身份验证必须使用有效的店主 API 密钥,或用于请求中确切 store_key 的 SiteChat 管理员访问令牌。
  • Shopify Admin API 令牌不能调用这些路由。

像其他 Merchant API 集成一样创建或轮换 owner secret: 如何使用 Shoply Merchant API。在 SiteChat 管理控制台中,打开 Product Catalog 即可管理产品、集合和库存——或导入 CSV 或 Excel 文件——而无需您自己管理密钥。

身份验证如何工作?

从服务器连接器发起

通过 HTTPS 从受信任的后端调用 API。在 Authorization 请求头中放入一个 JSON 字符串:

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 查询参数必须与请求头匹配。仅在服务器端环境变量中保存 owner secret——绝不要放在店面脚本、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。
  • 产品身份由 store、source 和 external ID 的组合确定。批量和单个 POST upsert 都是完全替换,而不是补丁:省略的可选字段会被清除。部分更新请使用 PATCH。
  • 每个批次包含 1–50 个产品,请求最大为 2,000,000 字节。每个产品经验证后的 JSON 限制为 128,000 字节,且最多 250 个变体。
  • 价格建议使用十进制字符串。货币必须是三个字母的大写代码。
  • 产品和图片 URL 必须为 HTTP(S)。导入操作不会替您抓取这些 URL。
  • 对于可搜索的产品规格,请使用公开的 metafields(SiteChat 中对应 Shopify 产品 metafields 的概念)。值必须是普通字符串。旧版 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"])

我如何安全地更新变体或 Metafields?

对于包含 variants、metafields 或旧版 attributes 字段的 PATCH,请先使用 GET 读取产品。基于该响应构建编辑内容,并将其顶层 updated_at 值作为 expected_updated_at 包含在 PATCH 请求体中。清空变体或 metafields 时也同样适用。

python
current_response = requests.get( "https://api.shoplyai.ai/merchant/products", params={"store_key": store_key, "source": "woocommerce-main", "external_id": "123"}, headers=headers, timeout=30, ) current_response.raise_for_status() current = current_response.json() updated_metafields = {**current["product"].get("metafields", {}), "material": "Leather"} response = requests.patch( "https://api.shoplyai.ai/merchant/products", params={"store_key": store_key}, headers=headers, json={ "source": "woocommerce-main", "external_id": "123", "expected_updated_at": current["updated_at"], "metafields": updated_metafields, }, timeout=30, ) response.raise_for_status()

HTTP 409 表示版本缺失,或另一次更新已更改该产品。请读取最新产品,再次合并您计划的更改后重试。不要将新版本附加到旧的变体列表上:那样可能会覆盖较新的库存值。

现有集成中,如果在没有版本的情况下对这些字段执行 PATCH,则必须更新。仅标量字段的 PATCH 请求、专用库存调整以及通过 POST 或批量导入进行的完全替换都不需要此字段。完全替换仍然会替换整个产品。

我可以上传产品图片吗?

可以。如果图片已经可通过持久公开的 HTTPS URL 访问,请将该 URL 放入产品的 images 列表或变体的 image 字段中。公开的 S3 HTTPS URL 可以使用。原始 s3:// 路径和短期有效的签名 URL 不可以。

如果希望由 Shoply 托管该文件,请从您的后端上传原始图片字节:

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

请发送原始文件字节,不要发送 JSON、base64 或 multipart 表单数据。支持 JPEG、PNG 和 WebP,最大 10 MiB,且不超过 2000 万像素。不支持动态图像。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"。完成时间没有固定保证。

  • 已发布产品会同时进入产品搜索和 SiteChat 聊天所使用的知识库。
  • Draft 和 archived 产品会在下一次重建时被排除。
  • 如果索引未被安排(index_status: "request_failed"),请针对那些已经成功存储的产品重试该批次。

我应当预期哪些错误?

HTTP status含义
403密钥缺失、无效、已过期或已撤销;商店错误;或账户不是 SiteChat
404请求的已导入产品不存在
413请求或图片超过大小限制
415图片上传使用了不受支持的 Content-Type
422字段无效、ID 重复、图片为动态或尺寸过大,或超出模型限制
503临时存储故障

密钥会在 90 天 后过期。请在过期前于 设置 → 店主 API 密钥 中创建替代密钥,并撤销任何不再需要的密钥。同一个密钥还可调用 Merchant API 指南 中记录的分析、会话和知识端点。

如果您需要集成帮助,请联系 Shoply AI。