REST API 参考指南
所有路径均以 https://shopify.workflow-transactional-email.app 为基准。除索引外,每个端点都需要添加 Authorization: Bearer fak_... - - 参见 身份验证和 API 密钥。
响应结果为 JSON 格式。错误信息在整个过程中采用统一的结构:
{ "error": "Invalid or missing API key" }索引与恒等式
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1 |
无 | API 索引。确认 API 正常运行,并报告当前版本信息 |
| GET | /api/v1/me |
阅读 | 检查密钥是否有效,并查看其访问级别 |
该索引无需键,因此将其作为监控对象进行健康检查是安全的。
电子邮件版式
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1/email-templates |
阅读 | 列出电子邮件模板。q 可按名称、主题和描述进行搜索;category=transactional 或 category=marketing 可列出某一种类型的电子邮件 |
| POST | /api/v1/email-templates |
写 | 创建版面 |
| GET | /api/v1/email-templates/:id |
阅读 | 一个版式,包含其设计或附件、页脚文本及其语言列表 |
| PUT / PATCH | /api/v1/email-templates/:id |
写 | 更改布局。只有您发送的字段会发生变化 |
| DELETE | /api/v1/email-templates/:id |
写 | 删除一个布局及其翻译和版本 |
| GET | /api/v1/layout-schema |
阅读 | 如何编写布局:设计格式、各模块的默认设置、可用的 Liquid 代码、限制及示例 |
该列表支持以下参数:page(默认值为 1)、limit(默认值为 25,最大值为 100)以及 q,后者用于搜索名称、主题和描述。API 不支持按类型过滤;请参阅 category 以了解各布局的具体实现。
一个版面包含以下字段:
| 字段 | 注释 |
|---|---|
name, description |
名称为必填项,最多200个字符;描述最多2000个字符 |
bodyType |
visual (默认)或 text。创建后即固定 |
defaultLocale |
布局自身内容的语言,若未设置,则默认为en |
category |
transactional (默认)或 marketing。详见下文 |
subject, previewText |
允许携带液体。必选科目 |
bodyDesign |
视觉布局:{ blocks, global?, header?, footer?, testVariables? }。修改时请发送完整的设计稿;HTML body 就是根据该设计渲染生成的 |
body |
文本布局:HTML 的 body 标签 |
attachments |
文本布局:[{ filename, fileKey, sendAsLink? }](用于上传的文件,参见下方的文件)或 [{ filename, url }](用于在发送电子邮件时通过 https 获取的文件) |
marketingTexts |
营销版面的页脚文本,或称null。详见下文 |
主题、预览文本、正文以及每个块状文本中的 Liquid 代码都必须经过解析,且每个 fileKey 必须属于您的店铺,否则写入操作将被拒绝,并返回一个 400 错误,该错误会指明具体字段。在编写视觉设计之前,请阅读 GET /api/v1/layout-schema:该设计由构建器自动生成,因此不会发生偏差。
通过此 API 进行的每次写入操作都会保存在布局的版本历史记录中,这与在应用中保存操作完全一样。
交易型和营销型版面
category 说明了布局的用途。交易类布局会原样发送给每位收件人。 营销版式会跳过已退订的收件人(此步骤中“To”字段中的所有收件人均已退订,该邮件不会被发送,并在历史记录中显示为 SKIPPED),以每名“To”收件人一封邮件的形式发送,每封邮件均包含独立的退订链接(每步最多 20 个),并在邮件末尾附上退订声明及贵公司信息。{{ unsubscribe_url }} 以及 {{ unsubscribe_link }} 需由您自行放置链接;在交易类布局中,这两个字段均为空。相关商家说明请参见 营销邮件与退订。
marketingTexts 页脚文字是营销布局使用的,而非“设置”中全站通用的文本:
{
"marketingTexts": {
"unsubscribeText": "You get this because you shop with us. {{ unsubscribe_link }}",
"unsubscribeLinkLabel": "Unsubscribe",
"companyDetails": "Example GmbH, Musterstrasse 1, 10115 Berlin"
}
}所有字段均为可选。设置了特定字段时,该字段将替换其对应的“设置”文本;其余字段保持原样。null(默认值)表示邮件语言对应的“设置”文本。限制:unsubscribeText 和 companyDetails 各限2000个字符,unsubscribeLinkLabel 限100个字符。 unsubscribeText 字段必须包含 {{ unsubscribe_link }} 或 {{ unsubscribe_url }},否则写入操作将被拒绝。该字段在任何布局中都会被存储,但仅随营销邮件发送。
删除布局绝不会被阻止。如果Shopify Flow步骤仍指向该布局,响应中会包含一个warning字段,用于说明具体数量;这些步骤将持续失败,直到它们改用另一个布局为止。
译文
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1/email-templates/:id/translations |
阅读 | 布局中的每种语言及其内容 |
| GET | /api/v1/email-templates/:id/translations/:locale |
阅读 | 一种语言 |
| PUT | /api/v1/email-templates/:id/translations/:locale |
写 | 创建或替换一种语言 |
| DELETE | /api/v1/email-templates/:id/translations/:locale |
写 | 删除一种语言。发送时将回退到该布局 |
| POST | /api/v1/email-templates/:id/translations/:locale/promote |
写 | 将该语言设为版式的主要语言 |
:locale 是一个语言代码,例如 de、fr 或 pt-br;大小写和分隔符均不影响识别。每个版面最多支持 30 种语言。在Shopify Flow步骤中,“语言”字段会在发送时进行选择:优先选择精确的区域设置,其次是基础语言,再其次是区域变体,否则直接采用该版面本身。
PUT 需要包含完整的翻译内容:subject(必填)、previewText,以及 bodyDesign(视觉)或 body(文本)。请保持 Liquid 标签和 URL 不变。以下两个字段专用于翻译:
| 字段 | 文本布局 | 含义 |
|---|---|---|
attachments |
是 | 一个列表(与布局的形状相同)= 该语言自身的附件,[] = 该语言无附件。null = 发送布局的附件。省略 = 保留当前选择;新语言使用布局的附件。可视化布局将其附件作为各语言中 bodyDesign 中的块进行携带,并拒绝此字段 |
marketingTexts |
任何 | 该语言的页脚文本将逐字段覆盖在布局的页脚文本之上。null= 采用布局的页脚文本。Omitted = 保留当前选择 |
返回的翻译包含相同的两个字段:attachments 的值是 null(同时采用了布局的值),而 marketingTexts 的值是 null(同时采用了布局的值)。
promote 交换布局和翻译:布局采用翻译的内容和区域设置,而它原本的内容则成为其原先所属语言的翻译。 附件和页脚文本也会互换位置,因此每种语言仍会发送其原先发送的内容。响应中会返回 promoted、previousMainLanguage 以及布局。由于这仅是一个版本,因此可以撤销该操作。
版本
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1/email-templates/:id/versions |
阅读 | 已保存的版本,按时间倒序排列。该应用会保留最新的25个版本 |
| GET | /api/v1/email-templates/:id/versions/:version |
阅读 | 某个版本的完整快照:布局及所有翻译内容 |
| POST | /api/v1/email-templates/:id/versions/:version/restore |
写 | 把那个版本放回去。已作为新版本录制 |
| GET | /api/v1/email-templates/:id/versions/github?page= |
阅读 | 连接的 GitHub 仓库中保存的每个版本,每页显示 20 个 |
| GET | /api/v1/email-templates/:id/versions/github/:sha |
阅读 | 某个提交时的布局情况 |
| POST | /api/v1/email-templates/:id/versions/github/:sha/restore |
写 | 将 GitHub 版本回滚,就像保存一样 |
在“开发者”页面上未连接任何仓库时,GitHub 端点返回 409 错误。请参阅 版式版本历史 和 在 GitHub 上保留无限的布局历史记录。
电子邮件发件人
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1/smtp-configs |
阅读 | 列出 SMTP 发件人 |
| GET | /api/v1/senders |
阅读 | 列出已连接的邮箱(Microsoft 365、Google) |
SMTP 发件人会报告 hasUsername 和 hasPassword 这样的地址,而非凭据本身 - - 这两部分均被隐藏,因为用户名与密码同为凭据的一部分。发件人仍可通过其名称、主机和发件人地址被识别。已连接的邮箱会报告部分遮蔽的地址(例如 so***@example.com),绝不会透露其登录令牌。
只读。在应用中连接并编辑发件人。
秘密
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1/secrets |
阅读 | 列出秘密名称和描述 |
返回 hasValue,绝不返回该值。不存在用于读取密钥的端点。请在应用中创建和更新密钥。
已上传的文件
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1/files |
阅读 | 已上传的徽标、图片和附件列表 |
| DELETE | /api/v1/files |
写 | 删除其中一个,作者:key(正文中) |
该列表支持通过 page、limit(最多 100 个)和 q 按文件名进行搜索。
添加 ?usage=true,每个文件还会报告 inUse,以及一个 usedBy 数组,其中列出了引用该文件的布局和预设。这就是如何通过单次请求找到所有可以安全清除的内容。该功能会扫描您的布局和预设,因此需要手动启用,而非默认启用。
此处不提供上传功能 - - 请通过应用中的媒体选择器添加文件。
HTTP 请求
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1/http-requests |
阅读 | 列出 HTTP 请求 |
| POST | /api/v1/http-requests |
写 | 创建一个 |
| GET | /api/v1/http-requests/:id |
阅读 | 买一个 |
| PUT / PATCH | /api/v1/http-requests/:id |
写 | 更新一 |
| DELETE | /api/v1/http-requests/:id |
写 | 删除一个 |
| POST | /api/v1/http-requests/:id/test |
执行 | 将其应用于实际目标 |
List 支持与电子邮件布局相同的 page、limit 和 q 参数。
目标 url 必须是 http:// 或 https://。保存时,其他方案将被拒绝。
写入请求头或请求正文中的明文凭证在每次响应中都会被掩码处理。以 {{ secrets.KEY }} 形式引用的值将按原样返回,因为该引用本身并不敏感。
历史与统计数据
同时涵盖电子邮件发送和HTTP请求。
| 方法 | 路径 | 级别 | 目的 |
|---|---|---|---|
| GET | /api/v1/history |
阅读 | 列表执行 |
| GET | /api/v1/history/:id |
阅读 | 获取包含请求和响应数据的一次执行 |
| GET | /api/v1/stats |
阅读 | 总数和成功率 |
History 支持 page、limit(最多 100 个)、actionType、status(PENDING、SUCCESS、FAILED、SKIPPED)以及 actionConfigId,用于筛选出单个布局或请求。
SKIPPED 这是一封营销邮件,其所有收件人都已取消订阅:既未发送任何内容,也未占用配额,且不计入成功率。
actionType 必须是EMAIL或HTTP_REQUEST中的任意一种。未识别的值会被忽略而非被拒绝,因此打字错误时会返回所有结果,而不是报错。
Stats 支持 days(默认值为 30,最大值为 365)。
状态码
| 代码 | 含义 |
|---|---|
| 200 | 成功 |
| 201 | 创建 |
| 400 | 请求格式错误或验证失败。error 指定了字段名称,例如 subject: required |
| 401 | API 密钥缺失、格式错误或已被撤销 |
| 403 | 该密钥有效,但其安全级别对于此端点而言过低 |
| 404 | 未找到,或属于另一家店铺 |
| 405 | 此路径的方法不正确 |
| 409 | 因记录仍在使用中(文件删除)或未连接 GitHub(GitHub 版本)而被拒绝 |
| 429 | 速率受限 - - 详见下文 |
| 502 | 请求已执行,但第三方目标执行失败 |
属于另一家商店的记录返回的是 404 而不是 403,因此 API 无法确认该 ID 在其他地方是否存在。
速率限制
两个独立的预算,均为按键计费:
- 所有端点每60秒的请求总数不得超过300次。
- 此外,每小时还要执行60次调用,涉及
POST /api/v1/http-requests/:id/test。
若任一项超限,系统将返回状态码 429 及说明信息error。执行预算被刻意设定得较为严格:一个不断向支付服务商发送实时请求的失控循环,其造成的故障远比脚本运行缓慢更为严重。
预算是以密钥为单位计算的,而非按商店计算,因此一个集成不会耗尽另一个集成的配额。

