如何为 SiteChat 上传您的商品目录
如果您在自己的网站上使用 SiteChat(而不是 Shopify 商店),您可以将结构化的产品记录发送到 Shoply,以便购物者能在 SiteChat 聊天和产品搜索中找到它们。
这些端点与其余 Shoply Merchant API 使用相同的 Settings → Store owner API secret,并且 SiteChat 管理后台中的 Product Catalog 页面可以使用您已登录管理员的访问令牌来调用它们。Shopify 商店仍然通过 Shopify 同步商品目录数据;这些上传路由仅适用于尚未同步 Magento 商品目录的 SiteChat 账户。
在 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 | 部分更新一个产品(读取-合并-写入) |
/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_platform为 SiteChat)。 - Shopify 商店密钥(包括任何
*.myshopify.com域名)都会被拒绝。 - 身份验证必须使用有效的店主 API 密钥,或请求中对应确切
store_key的 SiteChat 管理员访问令牌。 - Shopify Admin API 令牌不能调用这些路由。
创建或轮换 owner secret 的方式与其他 Merchant API 集成相同: How to Use the Shoply Merchant API。在 SiteChat 管理控制台中,打开 Product Catalog 以管理产品、集合和库存,或导入 CSV 或 Excel 文件,而无需您自己管理该密钥。
身份验证如何工作?
从服务器连接器发起
通过受信任的后端使用 HTTPS 调用 API。在 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 页面会改为发送您已登录的管理员会话:
{
"store_key": "YOUR_SITECHAT_STORE_KEY",
"admin_auth_token": "YOUR_SITECHAT_ACCESS_TOKEN"
}access_token 可作为 admin_auth_token 的别名使用。
store_key 查询参数必须与请求头匹配。仅在服务器端环境变量中保存 owner secret——绝不要放在店面脚本、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。- 产品身份由 store、source 和 external ID 的组合确定。批量和单个
POSTupsert 都是完整替换,不是补丁:省略的可选字段会被清除。部分更新请使用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)。当前版本不支持智能/基于规则的集合。
成功响应示例
{
"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 字段中。公开的 S3 HTTPS URL 可以使用。原始 s3:// 路径和短时效签名 URL 不可以。
如果希望由 Shoply 托管该文件,请从您的后端上传原始图片字节:
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 且不超过 2000 万像素。不支持动态图像。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"。完成时间没有固定保证。
- 已发布产品会同时进入产品搜索和 SiteChat 聊天所使用的知识库。
- 草稿和已归档产品会在下一次重建时被排除。
- 如果未安排索引(
index_status: "request_failed"),请针对那些已成功存储的产品重试该批次请求。
我应该预期哪些错误?
| HTTP 状态码 | 含义 |
|---|---|
403 | 密钥缺失、无效、过期或已撤销;商店错误;或非 SiteChat 账户 |
404 | 请求的已导入产品不存在 |
413 | 请求或图片超出大小限制 |
415 | 图片上传使用了不受支持的 Content-Type |
422 | 字段无效、ID 重复、动态图像或超大图片,或超出模型限制 |
503 | 临时存储失败 |
密钥会在 90 天后过期。请在过期前于 Settings → Store owner API secret 中创建替代密钥,并撤销任何您不再需要的密钥。相同的密钥还可用于调用 Merchant API 指南 中记录的分析、会话和知识端点。
如需集成帮助,请联系 Shoply AI。
