如何为 SiteChat 上传您的商品目录
如果您在自己的网站上使用 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/batch | POST | 在一次请求中创建或完全替换最多 50 个产品 |
/merchant/products | POST | 创建或完全替换一个产品 |
/merchant/products | GET | 通过 source 和 external_id 读取一个已导入的产品 |
/merchant/products | PATCH | 部分更新一个产品;替换变体或 metafields 需要使用来自 GET 的版本 |
/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 令牌不能调用这些路由。
像其他 Merchant API 集成一样创建或轮换 owner secret: 如何使用 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"])我如何安全地更新变体或 Metafields?
对于包含 variants、metafields 或旧版 attributes 字段的 PATCH,请先使用 GET 读取产品。基于该响应构建编辑内容,并将其顶层 updated_at 值作为 expected_updated_at 包含在 PATCH 请求体中。清空变体或 metafields 时也同样适用。
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 托管该文件,请从您的后端上传原始图片字节:
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 并移除嵌入的元数据。
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。
