如何使用 Shoply Merchant API

A secure merchant key unlocks an API connector carrying storefront chat, analytics, and knowledge into backend code

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 密钥?

  1. 打开您的 Shoply AI 管理后台。
  2. 前往 Settings → Store owner API secret。
  3. 创建一个密钥,并为其指定一个可标识该集成的名称,例如 Weekly reporting export。
  4. 在密钥显示时立即复制。Shoply 只会显示一次明文值。
Shoply Settings showing the Store owner API secret panel, Create API secret button, expiry date, and revoke control

每个密钥有效期为 90 天。一个店铺可以为不同集成分别创建不同密钥,您也可以撤销某一个密钥而不中断其他集成。

请将以下值保存为服务端环境变量:

bash
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 域名,即使顾客通常访问的是自定义域名。

Settings → Store owner API secret contains the Create API secret control. Keep generated secrets private.
Settings → Store owner API secret contains the Create API secret control. Keep generated secrets private. Click the screenshot to view it at full size.

身份验证是如何工作的?

每个 Merchant API 请求都会发送一个 Authorization 请求头,其值是一个 JSON 字符串:

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:

bash
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 模型进行获取:

python
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:

bash
npm install "github:shoplyai-public/shoply-merchant-api-js#v2.1.3"

从 Node.js 服务器中检索相同的最新会话:

typescript
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,请先安装:

bash
python -m pip install requests

下面的辅助函数会为每个请求添加店铺 key 和身份验证请求头:

python
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 中暴露这个具有写权限的凭证。

列出现有知识

python
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"))

响应示例

json
{ "data": { "knowledge::shipping-policy": { "title": "Shipping policy", "text": "Orders leave our warehouse within two business days.", "epoch_edit": 1787211246 } } }

创建或更新自定义文本知识

请选择一个稳定且唯一的知识 ID。更新该条目时请复用相同的 ID。

python
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)

响应示例

json
{ "statusCode": 200 }

成功响应表示知识已保存。搜索索引可能需要几分钟,因此新答案不一定会立即出现。如果 API 报告内容已保存但索引延迟,请在重试写入前,先使用 GET 确认已存储的条目。

添加外部网页

请使用以 external_url:: 开头的 ID。将完整的 http:// 或 https:// URL 放入 text 中。

python
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 位置保存为一个知识条目。

python
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()), } }, )

上传响应示例

json
{ "message": "File uploaded successfully", "statusCode": 200, "file_url": "s3://shoplystores/your-store.myshopify.com/uploads/shipping-policy.md" }

请将 file_url 视为 Shoply 返回的不透明私有位置。不要自行构造或修改它。

删除知识

删除是永久性的。请先检索当前条目,并且只发送您打算移除的确切 ID。

python
result = shoply_post( "admin_store_knowledge", { "knowledge_ids_to_delete": [ "knowledge::shipping-policy", "external_url::returns-policy", "knowledge_file::shipping-policy", ] }, )

请求重新抓取网站

当商家网站上的内容发生变化时,可使用重新抓取。在每次自定义文本更新后通常不需要这样做。

python
result = shoply_post( "admin_store_knowledge", re_crawl_ind="true", )

业务用例

  • 从内部内容系统同步配送、退货、保修、尺码或商品护理指南。
  • 无需手动复制到 Shoply Admin,即可发布临时活动或节假日信息。
  • 作为部署工作流的一部分,将政策网页或已批准文档添加到知识库中。
  • 在政策或促销结束后立即移除过时指导内容。

Merchant API 示例

1. 获取业绩分析数据

admin_store_analytics 为 Analytics → Summary 表格提供支持。它返回会话、聊天、搜索、点击、加入购物车事件、购买和归因收入。

端点

text
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 示例

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")

响应示例

json
{ "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 活动转换为店铺本地时间。

端点

text
GET https://api.shoplyai.ai/admin_get_store_metadata

查询参数

参数必填描述
store_key是由共享客户端添加
metadata_key是使用字面值 time_zone

Python 示例

python
timezone_payload = shoply_get( "admin_get_store_metadata", metadata_key="time_zone", ) timezone = timezone_payload["data"] print(timezone["ianaTimezone"], timezone["timezoneOffsetMinutes"])

响应示例

json
{ "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 中活动图表的数据来源。

端点

text
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 示例

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)

响应示例

json
{ "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 中的会话列表提供支持。

端点

text
GET https://api.shoplyai.ai/query_sessionized_chat

查询参数

参数必填描述
start_dt_utc是UTC 开始时间,或字面值 undefined
end_dt_utc是UTC 结束时间,或字面值 undefined
num_sessions否当任一边界为 undefined 时要选择的会话数量
ScanIndexForward否使用 false 先选择最新会话

获取最新的 40 个会话

python
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 范围内的会话

python
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 不会限制该有边界查询。

响应示例

json
{ "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、搜索和商业事件。

端点

text
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 示例

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"))

响应示例

json
{ "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。