邮件送达能力与运维
接收邮件送达事件,管理禁止发送名单,重放死信任务,并管理预热路由规则、回复模板和组织级外联设置。
本组接口覆盖发送相关的运维控制功能:向平台上报退信、垃圾邮件投诉、退订等送达信号,列出和重放死信任务,定义高级预热池路由偏好,管理回复模板,以及读取或更新组织整体的高级外联设置。所有路由均限定在组织范围内,调用者必须已选择当前组织;API 密钥始终绑定到一个组织。
错误采用共享的 {error, message, code, request_id} 封装。完整列表见错误码,权限范围与组织权限如何组合见身份验证。
获取外联设置
GET /outreach/settings
返回组织的高级外联设置,包括退信处理、任务可靠性、A/B 测试、回复意图、发送时间优化、发送前检查和邮件送达能力仪表板配置块。
身份验证:权限范围 WRITE_CAMPAIGNS · 组织权限 manage_settings
响应
直接返回 AdvancedOutreachSettings 对象,不额外封装。
{
"bounce_pipeline": {
"enabled": true,
"auto_suppress_on_bounce": true,
"auto_suppress_on_complaint": true,
"auto_suppress_on_unsubscribe": true,
"auto_pause_campaign_on_spike": true,
"pause_bounce_rate_threshold": 8,
"pause_complaint_rate_threshold": 1.5
},
"task_reliability": {
"enabled": true,
"dlq_enabled": true,
"max_attempts": 5,
"execution_window_seconds": 300
},
"ab_testing": {
"enabled": true,
"default_winning_rule": "reply_rate",
"auto_promote_winner": false,
"min_sample_size": 30
},
"reply_intent": {
"enabled": true,
"positive_keywords": ["interested", "demo", "pricing"],
"negative_keywords": ["not interested", "unsubscribe", "stop"],
"out_of_office_keywords": ["out of office", "ooo", "vacation", "abwesenheitsnotiz"],
"question_keywords": ["?", "how", "price"],
"auto_create_crm_task": true,
"crm_task_intents": ["positive", "question", "neutral", "negative"],
"auto_pause_on_negative": false,
"auto_suppress_on_unsubscribe_keyword": true,
"hold_on_out_of_office": true,
"out_of_office_hold_days": 7
},
"send_time_optimization": {
"enabled": false,
"use_contact_timezone": true,
"default_contact_timezone": "UTC",
"preferred_hours": [9, 10, 11, 14, 15, 16],
"weekend_weight_multiplier": 0.5
},
"preflight": {
"enabled": true,
"check_tracking_domain": true,
"check_unsubscribe_header": true,
"check_ab_variant_configured": false,
"check_daily_limit": true,
"check_schedule_window": true,
"check_content_score": true,
"min_content_score": 60
},
"dashboard": {
"enabled": true,
"show_suppression_log": true,
"show_intent_summary": true,
"show_dlq_stats": true
},
"unsubscribe": {
"mode": "text",
"text": "If this isn't relevant, just reply and let me know and I won't email you again.",
"link_intro": "Not the right person, or not interested?",
"link_text": "Unsubscribe"
},
"custom": {}
}unsubscribe 配置块是工作区默认退订设置,用于附加在每封营销活动邮件签名之后:mode 为 text(默认,提示通过回复退订)、link(包含收件人专属退订链接的说明)或 off;营销活动自身的 unsubscribe_mode(默认为 inherit)可覆盖此设置。文案字段为单行,最多 300 个字符,留空时回退到默认值。请参阅退订指南。
按回复意图创建跟进任务
reply_intent.auto_create_crm_task 会在收到已分类的回复时创建 CRM 任务,reply_intent.crm_task_intents 指定哪些意图值得创建任务。省略该字段或传入 null 时使用默认值:positive、question、neutral、negative,即全部人工回复意图,不包含自动回复意图。传入 ["positive"] 可缩小范围,传入 ["positive", "question", "neutral", "negative", "out_of_office", "automated"] 可包含自动回复和退信,传入 [] 则不创建任何任务,效果与关闭开关相同。超出该取值集合的意图会返回 400 并被拒绝。参阅任务。
内容评分下限会被限制在有效范围内
preflight.min_content_score 保存时会限制在 1 至 100 之间。超出范围的值会在写入时修正,而非拒绝,因此高于 100 的下限不会让所有营销活动永久被标记为有问题。将 preflight.check_content_score 设为 false 可关闭检查;无论如何,评分都不会阻止或延迟发送。请参阅内容检查。
默认启用外出自动回复暂停机制
reply_intent.hold_on_out_of_office 默认为 true。收件邮箱对营销活动步骤发出外出自动回复时,会暂停该联系人在此营销活动中的下一步,直到其返回:能从自动回复读取返回日期时,在该日期上加一个工作日;无法读取时,使用 out_of_office_hold_days,范围 1 至 90 天,默认 7。自动回复不会计为人工回复,因此不开启此功能时,即使联系人不在,跟进邮件也会按计划发出。out_of_office_keywords 用于回复意图记录,可由工作区编辑;检测逻辑自身具有多语言词表,不依赖此字段。请参阅外出回复与暂停单个潜在客户和暂停潜在客户。
默认关闭发送时间优化
send_time_optimization.enabled 默认为 false。设为 true 后,营销活动调度会将每次发送延迟到收件人当地时间达到 preferred_hours 中的某个小时。收件人时区依次从联系人的 timezone 自定义字段、邮箱域名的国家或地区代码后缀,以及 default_contact_timezone 解析。此功能只会延迟发送:营销活动时间窗口、邮箱发送配置、每日上限和营销活动结束日期仍全部生效。请参阅发送行为。
需要处理的邮件默认保留在收件箱
inbox_tagging.action_required_in_inbox 默认为 true。开启收件箱自动标记后,还会判断每封自动通知是否需要人工处理,例如支付失败、账户暂停、可疑登录、发送限制、服务即将过期。需要处理的通知会带有“需要处理”标签保留在收件箱,不移入“自动邮件”视图。inbox_tagging.questions 中带 automated: true 的问题也会用于判断通知。请参阅需要你处理的邮件。
更新外联设置
PATCH /outreach/settings
以提供的对象替换组织的高级外联设置。必须发送完整设置块;该值采用整体插入或更新,不进行深层合并。对象中省略的字段取默认值,而非旧值。成功时不返回响应体。
身份验证:权限范围 WRITE_CAMPAIGNS · 组织权限 manage_settings
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
settings | object | 是 | 完整的 AdvancedOutreachSettings 对象,结构与 GET 响应相同。 |
{
"settings": {
"bounce_pipeline": {
"enabled": true,
"auto_suppress_on_bounce": true,
"auto_suppress_on_complaint": true,
"auto_suppress_on_unsubscribe": true,
"auto_pause_campaign_on_spike": true,
"pause_bounce_rate_threshold": 8,
"pause_complaint_rate_threshold": 1.5
},
"task_reliability": {
"enabled": true,
"dlq_enabled": true,
"max_attempts": 5,
"execution_window_seconds": 300
},
"ab_testing": {
"enabled": true,
"default_winning_rule": "reply_rate",
"auto_promote_winner": false,
"min_sample_size": 30
}
}
}响应
204 No Content.
接收邮件送达事件
POST /deliverability/events
向平台提交单个送达信号,可为退信、垃圾邮件投诉、退订、打开、点击或回复。该端点可使用 API 密钥调用,方便下游处理流程,例如 SES 退信处理器,无需人工参与即可报告事件。根据组织的退信处理设置,退信、投诉或退订可能自动禁止向该收件人发送邮件。提供 idempotency_key 可安全重试。
身份验证:权限范围 WRITE_CAMPAIGNS · 组织权限 send_campaigns
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
event_type | string | 是 | 取值为 bounce、complaint、unsubscribe、open、click、reply 之一。 |
recipient_email | string | 是 | 事件涉及的收件地址。 |
campaign_id | uuid | 否 | 事件归属的营销活动。 |
task_id | uuid | 否 | 事件归属的发送任务。 |
contact_id | uuid | 否 | 事件归属的联系人。 |
provider | string | 否 | 来源服务商标签,例如 ses、postmark。 |
reason | string | 否 | 便于阅读的原因或诊断文字。 |
idempotency_key | string | 否 | 对重试的事件去重。 |
metadata | object | 否 | 附加到事件的自由格式 JSON。 |
{
"event_type": "bounce",
"recipient_email": "[email protected]",
"campaign_id": "8f1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"provider": "ses",
"reason": "550 5.1.1 mailbox does not exist",
"idempotency_key": "ses-bounce-01hzx9q",
"metadata": { "bounce_type": "Permanent" }
}响应
202 Accepted,无响应体。事件已进入处理队列。
列出禁止发送名单
GET /suppressions
分页返回工作区禁止发送名单,最新优先,包括无论因何原因加入、均不会接收营销活动邮件的所有地址和域名。expires_at 已过期的条目不会返回。
身份验证:权限范围 READ_CONTACTS · 组织权限 view_contacts
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
q | query | string | 按地址或域名进行子字符串筛选。 |
limit | query | integer | 每页数量,范围 1 至 200,默认 50。 |
cursor | query | string | 上一页 pagination.next_cursor 中的不透明游标。 |
响应
{
"data": [
{
"id": "5a0c...",
"organization_id": "9b1e...",
"email": "[email protected]",
"kind": "email",
"reason": "clicked the unsubscribe link",
"source": "unsubscribe",
"campaign_id": "c1...",
"metadata": { "via": "link" },
"created_at": "2026-09-01T10:12:00Z",
"updated_at": "2026-09-01T10:12:00Z"
},
{
"id": "7d2f...",
"organization_id": "9b1e...",
"email": "competitor.io",
"kind": "domain",
"reason": "Competitor",
"source": "manual",
"metadata": { "added_by": "4e5f..." },
"created_at": "2026-08-20T09:00:00Z",
"updated_at": "2026-08-20T09:00:00Z"
}
],
"pagination": { "next_cursor": null, "has_more": false }
}kind 为 email 或 domain;域名条目在 email 中保存纯主机名,并匹配该域下的所有地址。source 为 bounce、complaint、unsubscribe、manual(逐条添加)或 import(批量添加)。limit 或 cursor 无效时返回 400。
添加到禁止发送名单
POST /suppressions
添加地址和域名。包含 @ 的值视为邮件地址;不带或带前导 @ 的纯主机名视为域名。两者都不符合的值会列在 skipped 中,不会使整个请求失败。已存在的值会原地更新,因此可安全重复调用。每个请求最多 5000 个条目。
身份验证:权限范围 WRITE_CONTACTS · 组织权限 manage_contacts
请求
{
"entries": [
{ "value": "[email protected]", "reason": "Asked us by phone" },
{ "value": "acme.com" },
{ "value": "@partner.io" }
],
"reason": "Existing customers"
}请求级 reason 会应用到未单独指定原因的每个条目。添加地址还会关闭匹配联系人的 subscribed 标志。
响应
{ "added": 3, "skipped": [] }从禁止发送名单中移除
DELETE /suppressions/:id
解除一个条目,使营销活动可以再次向该地址或域名下的所有地址发送邮件。移除地址条目时,还会恢复匹配联系人的 subscribed 标志。移除操作会连同条目的值、类型和来源写入审计日志,因为撤销收件人主动退订,是合规审核需要关注的操作。
身份验证:权限范围 WRITE_CONTACTS · 组织权限 manage_contacts
成功返回 204;条目在此组织中不存在时返回 404。
列出死信任务
GET /tasks/dlq
列出已耗尽重试次数、进入死信队列的任务,包括发送失败、同步失败及其他有副作用的工作。应先通过此接口检查失败原因,再决定是否重放。
身份验证:权限范围 SEND_CAMPAIGNS · 组织权限 send_campaigns
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
status | query | string | 可选的状态筛选,例如 pending、replayed、resolved。 |
limit | query | integer | 最多返回的行数,范围 1 至 200,默认 100。 |
响应
通过 data 数组返回死信记录。此端点不使用游标分页,一次响应最多返回 limit 行。
发送死信只有在权威工作节点或运维人员确认的发送结果完成核对后,才会转为 resolved。恢复不会重新发送邮件:原始载荷、错误和尝试记录仍保留供检查。结果未知的任务保持待处理和暂停状态。缺少“已发送”文件夹副本、预留标记或执行器标记,都不能证明没有发送。
{
"data": [
{
"id": "1a2b3c4d-5e6f-7081-9293-a4b5c6d7e8f9",
"task_id": "9f8e7d6c-5b4a-3021-8f7e-6d5c4b3a2110",
"task_type": "send_campaign_email",
"payload": { "campaign_id": "8f1b2c3d-...", "email_account_id": "..." },
"last_error": "smtp: 421 too many connections",
"attempts": 5,
"max_attempts": 5,
"status": "pending",
"next_retry_at": null,
"replayed_at": null,
"created_at": "2026-06-11T14:02:09Z",
"updated_at": "2026-06-11T14:31:50Z"
}
]
}重放死信任务
POST /tasks/dlq/:id/replay
只允许重放具有明确、持久化唤醒意图的营销活动唤醒死信任务,并在营销活动锁内重新检查。一旦任务为发送绑定了联系人或邮件序列,即使其中任一记录之后被删除,其发送意图限制仍然保留。没有经验证唤醒意图的旧任务或导入任务,以及所有具备发送能力的任务,都会返回 409 Conflict 并保留死信证据。重试日期、JSON 载荷、为空的联系人或邮件序列、缺失的发送标记,都不能授予重放资格。此路由需要发送权限,仅有写入权限不足。
只要存在带发送意图的记录,或尚未解决且未经验证的死信记录,数据库降级就会拒绝丢弃这些来源证据。应保留数据库结构,并通过向前升级解决。
身份验证:权限范围 SEND_CAMPAIGNS · 组织权限 send_campaigns
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | 死信记录 ID,即死信队列列表中的 id 字段,不是 task_id。 |
响应
200 OK.
{ "status": "replayed" }列出预热路由规则
GET /warmup/routing
返回组织的全部预热路由规则,按 priority 升序排列,较小者先评估。规则用于表达高级预热池伙伴偏好,例如“归类为 Google 的发件邮箱只向 Gmail 收件人发送”。
身份验证:权限范围 WARMUP_ROUTING · 组织权限 manage_settings
响应
在 rules 键下返回规则,始终为数组,绝不为 null。
{
"rules": [
{
"id": "c1d2e3f4-5061-7283-94a5-b6c7d8e9f0a1",
"organization_id": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"name": "Gmail to Gmail only",
"priority": 10,
"sender_match_type": "provider",
"sender_match_value": "google",
"recipient_match_type": "provider",
"recipient_match_value": "google",
"weight": 1.0,
"enabled": true,
"created_at": "2026-06-01T09:00:00Z",
"updated_at": "2026-06-01T09:00:00Z"
}
]
}创建预热路由规则
POST /warmup/routing
为组织创建路由规则。发件方和收件方都会参与匹配,只有两侧都匹配时规则才生效。匹配值在写入时转为小写并去除首尾空格。
身份验证:权限范围 WARMUP_ROUTING · 组织权限 manage_settings
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 规则显示名称。 |
priority | integer | 否 | 评估顺序,升序。较小的值先执行。 |
sender_match_type | string | 是 | 取值为 any、domain、tld、provider 之一。 |
sender_match_value | string | 有条件必填 | 除非 sender_match_type 为 any,否则必填。可为域名(acme.com)、顶级域(com),或服务商分组(google、microsoft、yahoo、apple、proton、zoho、custom)。 |
recipient_match_type | string | 是 | 取值为 any、domain、tld、provider 之一。 |
recipient_match_value | string | 有条件必填 | 除非 recipient_match_type 为 any,否则必填。值的格式与发件方相同。 |
weight | number | 否 | 选择权重,必须 >= 0。高于 1 时优先选择该配对,低于 1 时降低优先级,恰好为 0 时完全排除:匹配的配对永远不会被选中,即使没有其他可选配对,也不会向其回复。 |
enabled | boolean | 否 | 规则是否启用。 |
{
"name": "Gmail to Gmail only",
"priority": 10,
"sender_match_type": "provider",
"sender_match_value": "google",
"recipient_match_type": "provider",
"recipient_match_value": "google",
"weight": 1.0,
"enabled": true
}响应
201 Created,包含完整规则对象,结构与列表项相同,并含服务端管理的 id、organization_id、created_at、updated_at。
{
"id": "c1d2e3f4-5061-7283-94a5-b6c7d8e9f0a1",
"organization_id": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"name": "Gmail to Gmail only",
"priority": 10,
"sender_match_type": "provider",
"sender_match_value": "google",
"recipient_match_type": "provider",
"recipient_match_value": "google",
"weight": 1.0,
"enabled": true,
"created_at": "2026-06-11T16:20:00Z",
"updated_at": "2026-06-11T16:20:00Z"
}更新预热路由规则
PATCH /warmup/routing/:id
按 ID 替换规则。请求体与创建时相同,必须提供完整载荷,所有字段都会应用,不进行深层合并;验证规则也相同。
身份验证:权限范围 WARMUP_ROUTING · 组织权限 manage_settings
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | 规则 ID。 |
请求体
字段与创建预热路由规则相同。
{
"name": "Gmail to Gmail only",
"priority": 5,
"sender_match_type": "provider",
"sender_match_value": "google",
"recipient_match_type": "provider",
"recipient_match_value": "google",
"weight": 2.0,
"enabled": true
}响应
200 OK,包含更新后的规则对象。
删除预热路由规则
DELETE /warmup/routing/:id
按 ID 移除路由规则。
身份验证:权限范围 WARMUP_ROUTING · 组织权限 manage_settings
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | 规则 ID。 |
响应
204 No Content.
列出回复模板
GET /templates
按位置顺序列出组织的回复模板。可选的 q 筛选会对名称和主题进行不区分大小写的匹配。
身份验证:权限范围 READ_TEMPLATES · 组织权限 view_campaigns
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
q | query | string | 可选。对名称和主题进行不区分大小写的搜索。 |
响应
在 data 键下返回模板,不使用游标分页。
{
"data": [
{
"id": "11111111-2222-3333-4444-555555555555",
"organization_id": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"user_id": "99999999-8888-7777-6666-555555555555",
"name": "Pricing follow-up",
"subject": "Re: pricing for {{.Company}}",
"body_html": "<p>Hi {{.FirstName}},</p>",
"body_plain": "Hi {{.FirstName}},",
"position": 1,
"created_at": "2026-05-20T10:00:00Z",
"updated_at": "2026-05-20T10:00:00Z"
}
]
}创建回复模板
POST /templates
创建归调用用户所有的回复模板,并追加到组织列表末尾。
身份验证:权限范围 WRITE_TEMPLATES · 组织权限 manage_campaigns
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 模板名称,最多 255 个字符。 |
subject | string | 否 | 邮件主题,可包含 {{.Key}} 占位符。 |
body_html | string | 否 | HTML 正文。 |
body_plain | string | 否 | 纯文本正文。 |
{
"name": "Pricing follow-up",
"subject": "Re: pricing for {{.Company}}",
"body_html": "<p>Hi {{.FirstName}},</p>",
"body_plain": "Hi {{.FirstName}},"
}响应
200 OK,包含创建的 ReplyTemplate。
{
"id": "11111111-2222-3333-4444-555555555555",
"organization_id": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"user_id": "99999999-8888-7777-6666-555555555555",
"name": "Pricing follow-up",
"subject": "Re: pricing for {{.Company}}",
"body_html": "<p>Hi {{.FirstName}},</p>",
"body_plain": "Hi {{.FirstName}},",
"position": 3,
"created_at": "2026-06-11T17:00:00Z",
"updated_at": "2026-06-11T17:00:00Z"
}调整回复模板顺序
PATCH /templates/reorder
按提供的 ID 顺序重新排列模板,位置从 1 开始。列表中未包含的 ID 保持不变。返回重新排序后的完整列表。
身份验证:权限范围 WRITE_TEMPLATES · 组织权限 manage_campaigns
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
ids | array of uuid | 是 | 按新顺序排列的模板 ID。 |
{
"ids": [
"33333333-3333-3333-3333-333333333333",
"11111111-2222-3333-4444-555555555555"
]
}响应
200 OK,在 data 下返回重新排序的列表,结构与列出回复模板相同。
获取回复模板
GET /templates/:id
按 ID 获取单个回复模板。
身份验证:权限范围 READ_TEMPLATES · 组织权限 view_campaigns
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | 模板 ID。 |
响应
200 OK,包含 ReplyTemplate 对象,结构与列表项相同。
更新回复模板
PATCH /templates/:id
更新回复模板。所有字段均可选,省略的字段保持不变。
身份验证:权限范围 WRITE_TEMPLATES · 组织权限 manage_campaigns
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | 模板 ID。 |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 否 | 新名称。 |
subject | string | 否 | 新主题。 |
body_html | string | 否 | 新 HTML 正文。 |
body_plain | string | 否 | 新纯文本正文。 |
{
"subject": "Re: updated pricing for {{.Company}}"
}响应
200 OK,包含更新后的 ReplyTemplate。
删除回复模板
DELETE /templates/:id
按 ID 删除回复模板。
身份验证:权限范围 WRITE_TEMPLATES · 组织权限 manage_campaigns
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | 模板 ID。 |
响应
204 No Content.
复制回复模板
POST /templates/:id/duplicate
克隆模板,在名称后附加 " (copy)",并将副本放在组织列表末尾。
身份验证:权限范围 WRITE_TEMPLATES · 组织权限 manage_campaigns
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | 源模板 ID。 |
响应
200 OK,包含新建的 ReplyTemplate,结构与创建响应相同。
渲染回复模板
POST /templates/:id/render
使用调用者提供的变量映射展开模板主题和正文中的 {{.Key}} 占位符,用于发送前预览回复。请求体可选;空映射会将所有占位符渲染为空。
身份验证:权限范围 READ_TEMPLATES · 组织权限 view_campaigns
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
id | path | uuid | 模板 ID。 |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
variables | object (string to string) | 否 | 用于替换 {{.Key}} 占位符的值。 |
{
"variables": {
"FirstName": "Dana",
"Company": "Acme"
}
}响应
200 OK,包含渲染后的主题和正文。
{
"subject": "Re: pricing for Acme",
"body_html": "<p>Hi Dana,</p>",
"body_plain": "Hi Dana,"
}为模板内容评分
POST /templates/score
根据主题和正文返回建议性的邮件送达内容评分,范围 0 至 100,越高越安全,并列出发现的问题。评分仅供参考,绝不会阻止发送。它不读取已保存的模板,只对请求体中的内容评分。
身份验证:权限范围 READ_TEMPLATES · 组织权限 view_campaigns
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
subject | string | 否 | 要评分的邮件主题。 |
body_html | string | 否 | HTML 正文,body_plain 为空时使用。 |
body_plain | string | 否 | 纯文本正文,提供时优先于 HTML。 |
{
"subject": "Quick question about {{.Company}}",
"body_plain": "Hi Dana, are you the right person to talk to about outreach?"
}响应
200 OK,包含评分和建议性问题。
每个问题都有位置。field 在问题仅位于一处时为 subject 或 body;跨越两处,或描述整封发送邮件的问题,例如附件数量时,省略此字段。spans 引用触发问题的精确片段,并提供该字段内从 1 开始的行号及整行上下文。suggestion 用一句话说明修正方式。
{
"score": 84,
"issues": [
{
"severity": "warn",
"code": "spam_trigger_terms",
"message": "2 spam-trigger term(s): free, limited time.",
"field": "body",
"spans": [
{
"field": "body",
"text": "free",
"line": 3,
"excerpt": "Here is a free look at what we do."
},
{
"field": "body",
"text": "limited time",
"line": 5,
"excerpt": "This is a limited time offer."
}
],
"suggestion": "Rewrite those words in plain language, or cut the sentence they sit in."
}
]
}spans 列表最多八项。用于扣分的数量在截取上限前计算,因此即使只显示部分片段,提示中出现十四个链接时,评分按十四个链接扣分也是一致的。
使用 AI 分析模板内容
POST /templates/analyze
对相同的主题和正文调用部署所配置的 AI 服务提供方,返回应修改的内容:从文案中引用具体词语或句子、所在位置是主题还是正文、问题原因,以及建议替换内容。同一请求还会运行规则检查,并通过 rules 返回,因此两部分都基于同一次读取的文案评分。
与 /templates/score 完全相同,此功能仅提供建议,不会阻止或延迟发送。
身份验证:权限范围 WRITE_TEMPLATES · 组织权限 view_campaigns 和 use_ai
此端点不写入模板,但会消耗工作区 AI 积分,因此需要写入权限范围:只读密钥不能具有花费资金的能力。已登录成员仍只需 view_campaigns 加 use_ai。
此端点消耗 AI 积分,参阅 AI 积分;如果部署运行不计量模型,即 AI_PROVIDER=ollama,或任意服务提供方设置了 AI_FREE=true,则返回的 credits_charged 为 0。发送 Idempotency-Key 请求头可安全重试,相同键绝不会重复扣费。
请求体
与 /templates/score 相同。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
subject | string | 否 | 要分析的邮件主题。 |
body_html | string | 否 | HTML 正文,body_plain 为空时使用。 |
body_plain | string | 否 | 纯文本正文,提供时优先于 HTML。 |
三个字段至少一个必须有内容,合计上限为 60,000 字节。
响应
200 OK,包含分析结果。
{
"score": 62,
"verdict": "This reads like a promotion rather than a note from a person.",
"findings": [
{
"severity": "high",
"field": "subject",
"text": "FREE bonus inside",
"line": 1,
"excerpt": "Your FREE bonus inside",
"issue": "Capitalised offer wording in the subject is one of the strongest promotional signals a filter reads.",
"suggestion": "Name the thing you noticed about them instead, in lower case.",
"category": "trigger_word"
}
],
"suggested_subject": "quick question about your onboarding",
"improvements": [
"Cut the closing paragraph. One ask lands better than three."
],
"rules": {
"score": 84,
"issues": []
},
"model": "gpt-6-luna",
"tokens_used": 812,
"credits_remaining": 248,
"credits_charged": 2
}| 字段 | 说明 |
|---|---|
score | 整体邮件送达评分,0 至 100,越高越安全。以 rules 为依据,绝不与其结论相矛盾。 |
verdict | 用一句话说明邮件的预计送达表现。 |
findings | 已定位的问题,按严重程度从高到低排列。severity 为 high、warn 或 info;field 为 subject 或 body,只有模型未标明位置且问题内容无法定位到原文时才省略;category 为 trigger_word、tone、formatting、links、structure、authenticity 之一,模型给出集合之外的类别时省略。 |
findings[].text | 从你的文案中引用的片段。问题涉及整封邮件时省略。 |
suggested_subject | 改写后的主题;当前主题无问题时省略。 |
improvements | 针对整体文案的建议,没有单个可引用片段。 |
rules | 同一内容的 /templates/score 结果。 |
引用内容会经过核验,而非直接采信
每个 text 返回前都会与提交的主题和正文核对。原文中不存在的片段会被丢弃,该问题只保留 issue 和 suggestion,因此响应不会引用你未提交的句子。如果引用实际出现在另一部分,会修正该问题的 field。
分析使用固定温度,因此对未修改文案重新分析会返回相同评分。评分变化表示文案发生变化,这也是编辑后重新检查的意义所在。
错误
| 状态 | 发生条件 |
|---|---|
400 | 没有可分析的内容,或模板超过大小上限。 |
402 | 工作区 AI 积分已用尽。不扣费,也不调用服务提供方。 |
403 | 套餐或试用不包含 AI,或成员缺少 use_ai。 |
503 | 此部署未配置 AI 服务提供方,code 为 ai_not_configured,对该部署属于持续性配置问题;或服务提供方失败,code 为 service_unavailable,已预留的积分会退回。 |