REST API 参考指南

所有路径均以 https://shopify.workflow-transactional-email.app 为基准。除索引外,每个端点都需要添加 Authorization: Bearer fak_... - - 参见 身份验证和 API 密钥。

响应结果为 JSON 格式。错误信息在整个过程中采用统一的结构:

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 页脚文字是营销布局使用的,而非“设置”中全站通用的文本:

json
{
  "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。执行预算被刻意设定得较为严格:一个不断向支付服务商发送实时请求的失控循环,其造成的故障远比脚本运行缓慢更为严重。

预算是以密钥为单位计算的,而非按商店计算,因此一个集成不会耗尽另一个集成的配额。