如何使用 Shoply Merchant API
Shoply Merchant API 让商家能够在报告工具、支持工作流、定时导出和私有业务应用中,安全地使用自己的 Shoply 数据。
每个集成都使用在 Shoply Settings 中创建的、可撤销且限定在单个店铺范围内的凭证进行身份验证。您无需共享 Shopify Admin API 访问令牌,并且每个集成只能访问为其签发凭证的那个店铺。
我可以用 Merchant API 做什么?
您可以使用 Merchant API 来:
- 将每日、每周或每月的业绩结果导出到电子表格或数据仓库。
- 为会话、聊天、搜索、商品点击、加入购物车事件、购买和归因收入构建私有仪表板。
- 监控客户活动并发现互动中的异常变化。
- 查看聊天和搜索会话,用于支持、商品运营和回答质量相关工作。
- 在调查客户问题时,检索单个会话的完整时间线。
- 创建、更新、列出和删除 Shoply AI 使用的自定义知识。
- 将外部网页或上传的 PDF、文本或 Markdown 文件添加到知识库中。
- 将 UTC 事件数据与店铺的本地时区对齐。
本指南记录了七个端点。其中五个与 Shoply Admin → Analytics 使用的端点相同,另外两个用于管理知识库:
| API | 类别 | 返回内容 |
|---|---|---|
admin_store_analytics | 业绩 | 每日、每周或每月的业绩行数据和汇总 |
query_api_usage_count | 互动 | 按 UTC 分钟或日期分组的活动计数 |
query_sessionized_chat | 会话 | 聊天和搜索会话摘要 |
query_log_visualization | 会话 | 单个选定会话的完整事件时间线 |
admin_get_store_metadata | 店铺配置 | 用于正确显示 UTC 数据的店铺时区 |
admin_store_knowledge | 知识 | 自定义文本、外部页面、上传文件、删除和重新抓取 |
user_generated_file | 知识文件 | 在将 PDF、文本或 Markdown 文件注册为知识之前先进行上传 |
下面的响应体是示例。您的字段和值将反映为您的店铺记录的实际活动。
部署要求: 您调用的 API 服务器必须已部署店主密钥身份验证。如果有效密钥返回 HTTP
403且带有No access_token found,说明该服务器仍在运行仅支持旧版 access token 的身份验证代码。
如何创建 API 密钥?
- 打开您的 Shoply AI 管理后台。
- 前往 Settings → Store owner API secret。
- 创建一个密钥,并为其指定一个可标识该集成的名称,例如
Weekly reporting export。 - 在密钥显示时立即复制。Shoply 只会显示一次明文值。
每个密钥有效期为 90 天。一个店铺可以为不同集成分别创建不同密钥,您也可以撤销某一个密钥而不中断其他集成。
请将以下值保存为服务端环境变量:
export SHOPLY_STORE_KEY="your-store.myshopify.com"
export SHOPLY_STORE_OWNER_API_SECRETE="shoply_owner_key_example123.secret-value"对于 SHOPLY_STORE_KEY,请使用店铺永久的 myshopify.com 域名,即使顾客通常访问的是自定义域名。

身份验证是如何工作的?
每个 Merchant API 请求都会发送一个 Authorization 请求头,其值是一个 JSON 字符串:
{
"store_key": "your-store.myshopify.com",
"store_owner_api_secrete": "YOUR_STORE_OWNER_API_SECRET"
}store_owner_api_secrete 是确切的公开字段名,包括其历史拼写。这不是一个 Bearer token。请将完整的 JSON 字符串直接放入 Authorization 请求头中。
请仅在后端代码中保存该密钥。不要将其放入 URL、浏览器打包文件、公开代码仓库、分析事件或应用日志中。
有官方的 Python 和 Node.js 包吗?
有。Shoply 发布了两个服务端包,它们会自动添加所需的身份验证,并将 Merchant API 暴露为类型化函数。两个包都以开源形式发布在 shoplyai-public GitHub 组织下。
Python 包
shoply-merchant-api 包支持 Python 3.12,并使用 Pydantic v2 响应模型。请安装固定版本 2.1.3:
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install "git+https://github.com/shoplyai-public/shoply-merchant-api.git@v2.1.3"将最新的聊天和搜索会话作为类型化的 SessionSummary 模型进行获取:
import os
from shoply_merchant_api import ShoplyMerchantClient
with ShoplyMerchantClient(
store_key=os.environ["SHOPLY_STORE_KEY"],
api_secret=os.environ["SHOPLY_STORE_OWNER_API_SECRETE"],
) as shoply:
session_response = shoply.list_sessions(limit=40)
for conversation in session_response.data:
print(conversation.customer_id, conversation.user_questions)该包还提供用于分析、活动计数、完整会话时间线、店铺时区和知识管理的函数。请参阅其业务用例指南 和 API reference 。
Node.js 和 TypeScript 包
shoply-merchant-api-js 仓库提供了适用于 Node.js 20 或更高版本的 @shoplyai/merchant-api 包。它是一个 ESM 包,内置 TypeScript 声明且没有运行时依赖。请直接从 GitHub 安装固定版本 2.1.3:
npm install "github:shoplyai-public/shoply-merchant-api-js#v2.1.3"从 Node.js 服务器中检索相同的最新会话:
import { ShoplyMerchantClient } from "@shoplyai/merchant-api";
const storeKey = process.env.SHOPLY_STORE_KEY;
const apiSecret = process.env.SHOPLY_STORE_OWNER_API_SECRETE;
if (!storeKey || !apiSecret) {
throw new Error("SHOPLY_STORE_KEY and SHOPLY_STORE_OWNER_API_SECRETE are required");
}
const shoply = new ShoplyMerchantClient({
storeKey,
apiSecret,
});
const sessionResponse = await shoply.listSessions({ limit: 40 });
for (const conversation of sessionResponse.data) {
console.log(conversation.customer_id, conversation.user_questions);
}该 npm 包覆盖了与 Python 包相同的 Merchant API 端点。请参阅其业务用例指南 和 API reference 。
这两个包都适用于受信任的后端服务、定时任务和私有内部工具。不要将任一包导入店面代码中,也不要在浏览器打包文件中暴露 API 密钥。
不使用包也能调用 HTTP API 吗?
可以。Merchant API 仍然是标准的 HTTPS API。下面的底层 Python 示例使用 Requests,这样您可以看到完整的线上传输协议,或从其他语言进行集成。
如果您的环境中尚未安装 Requests,请先安装:
python -m pip install requests下面的辅助函数会为每个请求添加店铺 key 和身份验证请求头:
import json
import os
from typing import Any
import requests
BASE_URL = "https://api.shoplyai.ai"
STORE_KEY = os.environ["SHOPLY_STORE_KEY"]
STORE_OWNER_API_SECRETE = os.environ["SHOPLY_STORE_OWNER_API_SECRETE"]
session = requests.Session()
session.headers.update({
"Authorization": json.dumps({
"store_key": STORE_KEY,
"store_owner_api_secrete": STORE_OWNER_API_SECRETE,
})
})
def shoply_get(api_name: str, **params: Any) -> dict[str, Any]:
"""Call one store-scoped Shoply API and surface HTTP or API-level errors."""
response = session.get(
f"{BASE_URL}/{api_name}",
params={"store_key": STORE_KEY, **params},
timeout=30,
)
response.raise_for_status()
payload = response.json()
if payload.get("error") is not None or payload.get("statusCode") not in (None, 200):
raise RuntimeError(payload.get("error", "Shoply API request failed"))
return payload
def shoply_post(
api_name: str,
payload: dict[str, Any] | None = None,
**params: Any,
) -> dict[str, Any]:
"""Write store-scoped data and surface HTTP or API-level errors."""
response = session.post(
f"{BASE_URL}/{api_name}",
params={"store_key": STORE_KEY, **params},
json=payload,
timeout=60,
)
response.raise_for_status()
result = response.json()
if result.get("error") is not None or result.get("statusCode") not in (None, 200):
raise RuntimeError(result.get("error", "Shoply API request failed"))
return result下面的示例都会使用这个共享客户端。两个辅助函数都会自动添加已验证的店铺 key。
我可以通过 API 管理 Shoply AI 知识吗?
可以。admin_store_knowledge 使用 GET 检索知识,使用 POST 创建、更新、删除或重新抓取知识。使用现有知识 ID 的 POST 会更新该条目;使用新 ID 则会创建新条目。
在自动化更新之前,请结合我们的训练指南中的示例来规划有用的店铺知识。
知识写入可能会改变向顾客展示的回答。请为管理知识的系统使用专用密钥,在发送前验证内容,并且绝不要在店面 JavaScript 中暴露这个具有写权限的凭证。
列出现有知识
knowledge_payload = shoply_get(
"admin_store_knowledge",
knowledge_id_to_retrieve="_ALL_",
)
for knowledge_id, knowledge in knowledge_payload["data"].items():
print(knowledge_id, knowledge.get("title"))响应示例
{
"data": {
"knowledge::shipping-policy": {
"title": "Shipping policy",
"text": "Orders leave our warehouse within two business days.",
"epoch_edit": 1787211246
}
}
}创建或更新自定义文本知识
请选择一个稳定且唯一的知识 ID。更新该条目时请复用相同的 ID。
from time import time
knowledge_id = "knowledge::shipping-policy"
result = shoply_post(
"admin_store_knowledge",
{
knowledge_id: {
"title": "Shipping policy",
"text": (
"Orders leave our warehouse within two business days. "
"Standard delivery normally takes three to five business days."
),
"epoch_edit": int(time()),
}
},
)
print(result)响应示例
{
"statusCode": 200
}成功响应表示知识已保存。搜索索引可能需要几分钟,因此新答案不一定会立即出现。如果 API 报告内容已保存但索引延迟,请在重试写入前,先使用 GET 确认已存储的条目。
添加外部网页
请使用以 external_url:: 开头的 ID。将完整的 http:// 或 https:// URL 放入 text 中。
from time import time
result = shoply_post(
"admin_store_knowledge",
{
"external_url::returns-policy": {
"title": "Returns and exchanges",
"text": "https://www.example.com/policies/returns",
"epoch_edit": int(time()),
}
},
)上传并注册知识文件
知识文件必须是 PDF、TXT 或 Markdown 格式,且小于 5 MB。请先上传文件,然后将返回的私有 S3 位置保存为一个知识条目。
from pathlib import Path
from time import time
file_path = Path("shipping-policy.md")
with file_path.open("rb") as file_handle:
upload_response = session.post(
f"{BASE_URL}/user_generated_file",
params={"store_key": STORE_KEY, "folder": "knowledge_file"},
files={"file": (file_path.name, file_handle, "text/markdown")},
timeout=60,
)
upload_response.raise_for_status()
uploaded = upload_response.json()
if uploaded.get("statusCode") != 200:
raise RuntimeError(uploaded.get("error", "Knowledge file upload failed"))
shoply_post(
"admin_store_knowledge",
{
"knowledge_file::shipping-policy": {
"title": "Shipping policy document",
"text": uploaded["file_url"],
"epoch_edit": int(time()),
}
},
)上传响应示例
{
"message": "File uploaded successfully",
"statusCode": 200,
"file_url": "s3://shoplystores/your-store.myshopify.com/uploads/shipping-policy.md"
}请将 file_url 视为 Shoply 返回的不透明私有位置。不要自行构造或修改它。
删除知识
删除是永久性的。请先检索当前条目,并且只发送您打算移除的确切 ID。
result = shoply_post(
"admin_store_knowledge",
{
"knowledge_ids_to_delete": [
"knowledge::shipping-policy",
"external_url::returns-policy",
"knowledge_file::shipping-policy",
]
},
)请求重新抓取网站
当商家网站上的内容发生变化时,可使用重新抓取。在每次自定义文本更新后通常不需要这样做。
result = shoply_post(
"admin_store_knowledge",
re_crawl_ind="true",
)业务用例
- 从内部内容系统同步配送、退货、保修、尺码或商品护理指南。
- 无需手动复制到 Shoply Admin,即可发布临时活动或节假日信息。
- 作为部署工作流的一部分,将政策网页或已批准文档添加到知识库中。
- 在政策或促销结束后立即移除过时指导内容。
Merchant API 示例
1. 获取业绩分析数据
admin_store_analytics 为 Analytics → Summary 表格提供支持。它返回会话、聊天、搜索、点击、加入购物车事件、购买和归因收入。
端点
GET https://api.shoplyai.ai/admin_store_analytics查询参数
| 参数 | 必填 | 描述 |
|---|---|---|
store_key | 是 | 由共享客户端添加 |
report_type | 是 | daily、weekly 或 monthly |
start_date | 每日/每周 | 包含在内的 UTC 日期,格式为 YYYYMMDD |
end_date | 每日/每周 | 包含在内的 UTC 日期,格式为 YYYYMMDD |
月度报告使用 Shoply 存储的月度历史数据,不需要日期边界。
Python 示例
daily_report = shoply_get(
"admin_store_analytics",
report_type="daily",
start_date="20260801",
end_date="20260820",
)
for row in daily_report["data"]:
print(row["date"], row["sessions"], row["purchases"], row["revenue"])
print("Totals:", daily_report["totals"])
# Weekly rows use the Monday of each week as their date label.
weekly_report = shoply_get(
"admin_store_analytics",
report_type="weekly",
start_date="20260701",
end_date="20260820",
)
# Monthly requests do not need start_date or end_date.
monthly_report = shoply_get("admin_store_analytics", report_type="monthly")响应示例
{
"data": [
{
"date": "20260820",
"sessions": 42,
"chats": 18,
"searches": 24,
"clicks": 11,
"add_to_cart": 5,
"purchases": 2,
"revenue": "$168.00",
"revenue_usd": "$168.00"
}
],
"totals": {
"date": "totals",
"sessions": 42,
"chats": 18,
"searches": 24,
"clicks": 11,
"add_to_cart": 5,
"purchases": 2,
"revenue": "$168.00",
"revenue_usd": "$168.00"
},
"report_type": "daily"
}收入可能包含多种货币。请将 revenue 视为显示文本。如果您需要 Shoply 显示的标准化美元值,请使用 revenue_usd。
业务用例
- 向商家或电商团队发送每日销售影响摘要。
- 对比搜索、商品点击、加入购物车事件和购买情况,以发现漏斗流失环节。
- 无需抓取 Shoply Admin 页面,即可为每周或每月的商业智能仪表板提供数据。
- 跟踪归因收入的时间变化,并将其与商品运营或营销活动变化进行比较。
2. 获取店铺时区
admin_get_store_metadata 提供显示在 Analytics → Chat & Search History 中的时区标记。该页面使用它将 UTC 活动转换为店铺本地时间。
端点
GET https://api.shoplyai.ai/admin_get_store_metadata查询参数
| 参数 | 必填 | 描述 |
|---|---|---|
store_key | 是 | 由共享客户端添加 |
metadata_key | 是 | 使用字面值 time_zone |
Python 示例
timezone_payload = shoply_get(
"admin_get_store_metadata",
metadata_key="time_zone",
)
timezone = timezone_payload["data"]
print(timezone["ianaTimezone"], timezone["timezoneOffsetMinutes"])响应示例
{
"data": {
"ianaTimezone": "America/Los_Angeles",
"timezoneOffset": -7,
"timezoneOffsetMinutes": -420
},
"statusCode": 200
}业务用例
- 将 UTC 活动按商家在 Analytics 中看到的相同本地日历日期进行分组。
- 在店铺本地日期结束后安排每日导出。
- 使用明确无歧义的 IANA 时区标签(如
America/Los_Angeles)为报告添加标注。
由于夏令时规则,时区偏移量可能会变化。如果您的报告系统支持,请优先使用 ianaTimezone,而不是永久保存某一个数字偏移量。
3. 获取活动计数
query_api_usage_count 返回按 UTC 日期或原始 UTC 分钟分组的店铺活动。它也是 Analytics → Chat & Search History 中活动图表的数据来源。
端点
GET https://api.shoplyai.ai/query_api_usage_count查询参数
| 参数 | 必填 | 描述 |
|---|---|---|
start_dt_utc | 是 | UTC 开始时间,格式为 YYYY-MM-DD HH:mm:ss |
end_dt_utc | 是 | UTC 结束时间,格式为 YYYY-MM-DD HH:mm:ss |
groupby | 否 | utc_date 表示每日总计,utc_date_time 表示按分钟返回 |
Python 示例
activity = shoply_get(
"query_api_usage_count",
start_dt_utc="2026-08-01 00:00:00",
end_dt_utc="2026-08-20 23:59:59",
groupby="utc_date",
)
for row in activity["data"]:
print(row)响应示例
{
"data": [
{
"utc_date": "2026-08-20",
"QA": 18,
"CHAT": 18,
"SEARCH": 20,
"CACHED_SEARCH": 4,
"PRODUCT_SEARCH": 22,
"CLICK": 11,
"ADD_TO_CART": 5,
"CHECKOUT": 2
}
]
}返回行会包含该时间段内可用的活动计数器,例如聊天提问、搜索、点击、加入购物车事件和结账事件。没有活动的计数器可能会缺失,而不是被设置为零。
业务用例
- 构建类似于 Chat & Search History 中的按小时或按日活动图表。
- 检测异常流量高峰或客户互动的突然下降。
- 比较商品搜索量与点击、加入购物车事件和结账之间的关系。
- 估算支持和商品运营团队应何时审查最繁忙的时段。
4. 获取聊天和搜索会话摘要
query_sessionized_chat 为每个客户会话返回一条紧凑记录。它也为 Analytics → Chat & Search History 中的会话列表提供支持。
端点
GET https://api.shoplyai.ai/query_sessionized_chat查询参数
| 参数 | 必填 | 描述 |
|---|---|---|
start_dt_utc | 是 | UTC 开始时间,或字面值 undefined |
end_dt_utc | 是 | UTC 结束时间,或字面值 undefined |
num_sessions | 否 | 当任一边界为 undefined 时要选择的会话数量 |
ScanIndexForward | 否 | 使用 false 先选择最新会话 |
获取最新的 40 个会话
summary_payload = shoply_get(
"query_sessionized_chat",
start_dt_utc="undefined",
end_dt_utc="undefined",
num_sessions=40,
ScanIndexForward="false",
)
sessions = summary_payload["data"]
for conversation in sessions:
print(conversation["customer_id"], conversation.get("user_questions", ""))获取某个 UTC 范围内的会话
summary_payload = shoply_get(
"query_sessionized_chat",
start_dt_utc="2026-08-20 00:00:00",
end_dt_utc="2026-08-20 23:59:59",
ScanIndexForward="false",
)当两个时间边界都存在时,API 会返回完整范围内的会话;num_sessions 不会限制该有边界查询。
响应示例
{
"data": [
{
"customer_id": "customer-or-session-id",
"user_questions": "Do you have this in blue?\nWhen will it ship?",
"start_timestamp_ms": 1787184000000,
"end_timestamp_ms": 1787184065000,
"session_types": "product information, click",
"customer_email": null,
"customer_info": {},
"sentiment": "positive",
"num_questions": 2,
"num_searches": 1,
"num_clicks": 1
}
]
}可选字段会因会话而异。如果您计划获取完整时间线,请保留 customer_id、start_timestamp_ms 和 end_timestamp_ms。
业务用例
- 抽样查看近期会话,用于回答质量审查和支持培训。
- 找出重复出现的客户问题,以便影响商品文案或常见问题内容。
- 识别包含搜索、商品点击或其他购物行为的高意向会话。
- 在避免更大事件级负载的情况下,按每个会话导出一行数据用于趋势分析。
5. 获取单个完整会话
将选定的摘要传递给 query_log_visualization,以获取其客户、AI、搜索和商业事件。
端点
GET https://api.shoplyai.ai/query_log_visualization查询参数
| 参数 | 必填 | 描述 |
|---|---|---|
date_time_utc_start | 是 | 会话开始时间,格式为 UTC YYYY-MM-DD HH:mm:ss |
date_time_utc_end | 是 | 会话结束时间,格式为 UTC YYYY-MM-DD HH:mm:ss |
session_id | 否 | 摘要中的 customer_id,用于较旧的历史记录 |
start_timestamp_ms | 建议提供 | 摘要中的精确毫秒级开始时间戳 |
Python 示例
from datetime import datetime, timezone
def utc_from_milliseconds(timestamp_ms: int) -> str:
"""Format a Shoply millisecond timestamp for the history API."""
value = datetime.fromtimestamp(timestamp_ms / 1000, tz=timezone.utc)
return value.strftime("%Y-%m-%d %H:%M:%S")
selected = sessions[0]
timeline_payload = shoply_get(
"query_log_visualization",
date_time_utc_start=utc_from_milliseconds(selected["start_timestamp_ms"]),
date_time_utc_end=utc_from_milliseconds(selected["end_timestamp_ms"]),
session_id=selected["customer_id"],
start_timestamp_ms=selected["start_timestamp_ms"],
)
for event in timeline_payload["data"]:
print(event.get("server_timestamp_ms"), event.get("action_type"))响应示例
{
"data": [
{
"action_type": "QA",
"session_id": "customer-or-session-id",
"utc_date_time": "2026-08-20 00:00:00",
"start_timestamp_ms": 1787184000000,
"server_timestamp_ms": 1787184000123,
"Q": {
"question": "Do you have this in blue?",
"question_context": {}
},
"task_id": "task-id",
"list_tokens": [
{
"data_type": "LLMOutput",
"data": "Yes. These blue options are currently available."
}
],
"dict_search_results": {}
}
]
}时间线中可能包含客户问题、AI 回答、搜索结果、商品点击、加入购物车事件、结账事件以及人工客服参与。请使用 server_timestamp_ms 对混合事件类型进行排序。较旧的记录可能包含更少字段。
业务用例
- 在支持调查期间,精确审计客户问了什么以及 Shoply 给出了什么回答。
- 结合展示给顾客的搜索结果和商品,一起审查回答质量。
- 重建从提问到点击、加入购物车或结账的完整路径。
- 诊断客户报告的某个单独会话,而无需在无关历史中搜索。
我可以为所有 API 使用同一个密钥吗?
可以。有效的 store_owner_api_secrete 仅限于单个店铺,并可用于上述所有 Merchant API 端点。对于 SiteChat 账户,同一个密钥也可用于 catalog upload APIs 的身份验证。为了更安全的操作,建议为不同系统使用不同的已命名密钥——例如,一个用于夜间数据导出,另一个用于内部仪表板。
如果某个集成被停用或遭到泄露,只需在 Shoply Settings 中撤销该集成对应的密钥。其他集成将继续正常工作。
关于过期、隐私和错误,我需要了解什么?
另请查看 Shoply 数据来源和隐私,以了解哪些信息可用于客户回答。
- 店主 API 密钥会在 90 天 后过期。请在过期日期之前创建替代密钥并更新集成。
- Shoply 标准聊天和搜索历史保留期同样为 90 天。密钥过期和数据保留是两项独立政策。
- 历史响应可能包含个人数据,包括客户标识符、电子邮件地址、大致位置、问题和购物活动。请根据您的隐私政策和适用法律进行存储和处理。
- HTTP
403表示密钥缺失、无效、已过期、已撤销,或属于其他店铺。 - HTTP
422通常表示缺少必需的查询参数,或参数名称错误。 - HTTP
500或带有statusCode: 500的响应表示请求已到达 Shoply,但无法完成。对于临时故障,请使用退避机制重试;如果错误持续存在,请联系我们。 - 对于导出和周期性任务,请使用有边界的 UTC 时间范围,以保持响应规模可控。
商品搜索属于 Merchant API 的一部分吗?
Shoply 的公开商品搜索 API 具有不同的身份验证和请求协议。如果您想为面向顾客的体验获取商品搜索结果,而不是获取商家私有数据,请参阅如何通过 API 访问 Shoply AI Search。
SiteChat 商家可以上传商品目录吗?
可以。SiteChat 账户可以使用同一个店主 API 密钥上传结构化商品和商品图片。这些目录端点在如何为 SiteChat 上传您的目录中另行说明。Shopify 店铺仍通过 Shopify 同步商品,不使用这些上传路由。
如需集成帮助,请联系 Shoply AI。
