开发者
公开 API Beta
使用安全、限定权限的 API 密钥和稳定的版本化 JSON 约定构建工作区集成。
打开交互式 API 参考快速入门
- 01
打开 API 密钥
打开设置,选择开发者,找到 API 密钥,然后选择创建密钥。所有者和管理员可以创建密钥。
- 02
创建 API 密钥
填写名称,选择有效天数,将渠道访问权限设为全部渠道或指定渠道,并在权限范围下选择集成所需的最少权限。只有当密钥具备端点所要求的确切资源操作时,请求才会成功。选择创建密钥。
- 03
保存你的 API 密钥
完整密钥只显示一次。把它复制到你的密钥管理工具中,然后选择我已保存。
- 04
发送密钥
使用 Bearer 令牌,或在
x-api-key中发送相同的值。切勿把密钥放在查询字符串或浏览器代码中。
cURL
curl https://www.usesonny.com/api/v1/contacts?limit=25 \
--header "Authorization: Bearer sonny_your_key"密钥始终安全
- 密钥安全
- 密钥使用
sonny_前缀和 64 个随机字符,存储时经过单向哈希,有效期可配置,每个密钥每分钟限 600 次请求。一个密钥只绑定一个工作区。 - 要撤销某个密钥,选择它旁边的删除按钮。在撤销 API 密钥?中选择删除确认。密钥会立即停用。
- 每次调用都进行授权
- Sonny 会校验哈希和权限范围,然后重新检查创建者当前的工作区成员身份、角色和账单状态。移除或停用该用户会立即禁用其所有密钥。
- 每次 REST API 和 MCP 调用都会强制执行所选渠道限制。联系人、属性、标签和 Webhook 管理端点需要全部渠道的访问权限。从表单创建对话时,可在指定渠道上使用 contacts:write 配合 conversations:write;独立的联系人端点仍作用于整个工作区。
权限范围
contacts:readcontacts:writetags:readtags:writeconversations:readconversations:writemessages:readmessages:writemessages:sendwebhooks:readwebhooks:writekb:readkb:writecsat:readattachments:writemembers:readcontact-memory:readcontact-memory:writereporting:read
资源
- 联系人
- 管理联系人、带类型的属性、精确值筛选和客户记忆。可以归档联系人,或在处理数据保护请求时将其连同所有对话永久删除。
- 来源
- 查看已配置的来源,以及每个来源支持聊天、邮件还是两者皆可。
- 对话
- 从表单创建咨询、筛选待处理对话、分配客服或团队、延后、打标签和批量更新。
- 同步
- 使用保存的游标重放持久的工作区变更和删除记录。
- 成员与团队
- 查看可分配的同事、在线状态和实际的渠道访问权限。
- 报表
- 读取客服、团队、AI、知识库、潜在客户和在线时长报表。
- 消息
- 读取消息历史和附件提取内容,上传私有文件,添加内部备注,以及发送或编辑给客户的回复。
- Webhook
- 管理端点、订阅、测试、投递和重试。
- 知识库
- 按来源创建、读取、更新和删除帮助中心文章与分类。
- 客户满意度
- 读取工作区、各渠道和各对话的满意度得分,并按评分值、评论、负责人或时间范围筛选列出单条评分。
从 AI 工具中使用 Sonny
Sonny MCP 将每一项公开 API 操作都作为工具提供。客户端通过 OAuth 2.1 登录(或使用限定权限的 API 密钥)进行连接,每次调用都遵循同样的权限范围、工作区边界和业务规则。
阅读 Sonny MCP 指南响应与错误
集合类响应使用 data,并在适用时包含分页信息。每个响应都包含 x-request-id;你也可以提供一个安全的请求 ID,Sonny 会原样返回。错误会返回安全的提示信息,不会暴露敏感的实现细节。
{
"error": {
"type": "validation_error",
"message": "Invalid email address",
"requestId": "req_01J..."
}
}400- 输入、JSON、查询参数或游标无效。
401- API 密钥缺失、无效、已过期或缺少权限范围。
402- 工作区的账单状态阻止了此请求。
403- 密钥创建者在工作区中的角色无权执行此操作。
404- 该资源在密钥所属的工作区中不存在。
409- 请求与现有资源冲突。
410- 同步游标已过期。请重新获取当前状态,并从新游标开始重放。
413- 上传内容超出允许的大小。
422- 该来源没有邮件渠道,或提交的字段值无效。
429- 超出了单个密钥的请求频率限制。
500- 发生意外错误。请携带请求 ID 重试。
503- Webhook 投递积压已满,请稍后重试。
请求频率限制
每个 API 密钥每分钟最多可发起 600 次请求。每个响应都会通过标准的 RateLimit-Limit、RateLimit-Remaining 和 RateLimit-Reset 响应头报告当前时间窗口,客户端可以据此自行限流,而不必猜测。超出限制时,API 返回 429 和 Retry-After 响应头——请等待相应的秒数后再重试。
版本与弃用
API 通过 URL 路径进行版本控制(/api/v1)。同一版本内只做增量变更——新增端点、新增可选字段、新增枚举值。破坏性变更会以新版本发布;任何 v1 端点下线前,我们都会提前至少六个月通知:在本页面公告、通过邮件通知拥有有效 API 密钥的工作区所有者,并在受影响的端点上返回 Deprecation 和 Sunset 响应头。
编辑已发送的回复
- 为你的 API 密钥或 MCP 连接授予
messages:read和messages:send权限范围,以及该回复所在渠道的访问权限。 - 读取对话的消息,并复制你发送的一条人工回复的 ID。API 密钥以其创建者的身份操作;OAuth 以已连接的同事身份操作。
- 使用下面的请求发送替换文本,或在 MCP 中调用
edit_message,并传入conversationId、messageId和body。 - 检查返回的消息。它的 ID、附件、已读回执和原始发送时间都保持不变。
curl --request PATCH \
https://www.usesonny.com/api/v1/conversations/conversation_1/messages/message_1 \
--header "Authorization: Bearer sonny_your_key" \
--header "Content-Type: application/json" \
--data '{"body":"The corrected reply"}'编辑会更正对话记录和已连接的聊天客户端。它不会再次发送邮件或通知,已送达的邮件也保持不变。只能编辑你自己发给客户的人工回复;收到的消息、机器人回复、内部备注和其他同事的回复都无法编辑。请等待待发送的邮件投递完成后再编辑。替换文本必须包含 1–50,000 个字符;之前的 HTML 和链接预览会被清除。集成会收到 message.updated Webhook 和同步事件。只轮询更新的消息 ID 无法发现编辑;请使用持久同步流。
从表单创建对话
将表单提交发送到 POST /api/v1/conversations。Sonny 会按邮箱查找或创建联系人,保存表单答案,并在你所选来源的邮件渠道上打开一个收到的对话。该渠道的团队、分配规则和通知都会生效。客服通过邮件回复。
- 创建一个具有
conversations:write和contacts:write的密钥。你可以将其限制在客户的指定渠道。通过GET /api/v1/sources查找来源 ID,这还需要conversations:read。 - 在 n8n 中添加一个 HTTP Request 节点:方法 POST,URL
https://www.usesonny.com/api/v1/conversations。将密钥保存在 Header Auth 凭据中:Authorization,值为Bearer sonny_your_key。 - 启用 Send Body,选择 JSON 和 Using JSON,然后把整个 JSON 字段切换为 Expression 并粘贴此示例。替换来源 ID,并把输入字段映射到你的表单。请使用表单稳定且唯一的提交 ID,这样重试时会使用相同的值。
{{ {
sourceId: "YOUR_CLIENT_SOURCE_ID",
contact: { email: $json.email, name: $json.name },
subject: "Website enquiry",
message: $json.message,
fields: {
Company: String($json.company ?? ""),
Budget: String($json.budget ?? ""),
Service: String($json.service ?? "")
},
externalId: "website-form-" + $json.submissionId
} }}更多节点选项请参阅 n8n HTTP Request 指南。对应的 MCP 工具是 create_conversation,负载和权限相同。
新的字段名会成为文本属性。已有的数字、URL、日期和选项字段必须收到有效的字符串值;值无效时会返回 422 并指出字段名,且不会保存任何内容。日期接受 ISO 日期或时间戳;选项值必须与某个选项匹配。最多接受 50 个字段,字段名最长 100 个字符,值最长 5,000 个字符。属性会显示在联系人和对话侧边栏中。即使你提供了可选的 htmlMessage,两种消息正文中也都会保留一份答案副本。
可选的 tags 最多接受 20 个现有的工作区标签 ID。响应包含 conversation、contact 摘要、message 和 deduplicated。新提交返回 201。在同一来源上重复使用 externalId 会返回 200、原有 ID 以及 deduplicated: true;变更的内容会被忽略。不提供外部 ID 时,每次调用都会创建新对话。创建时不支持附件和 AI 自动回复。
智能体工作流
分拣、处理,并保持同步
REST 和 MCP 共用相同的权限和工作流。凭据只能缩小你当前的渠道访问范围;从你的成员身份中移除某个渠道,也会把它从你的集成中移除。
找出需要处理的对话
可按 awaitingReply、unread、unassigned、assigneeId、agentGroupId、snoozed、priority 或 tagIds 筛选。等待回复会忽略内部备注;未读针对的是已认证的同事本人。未分配表示没有个人负责人,即使已分配给某个团队。标签匹配所提供的任意 ID。
GET /api/v1/conversations?status=open&awaitingReply=true&compact=true&sort=waitingSince&direction=asc可按 waitingSince、lastMessageAt、createdAt 或业务优先级排序,方向为 asc 或 desc,ID 用于决定并列顺序。省略筛选条件时保持 compact=false 和 snoozed=any。REST 的 tagIds 接受逗号分隔的 ID;MCP 还接受数组。waitingSince 从上次回复之后的第一条收到的消息开始计算;后续消息和内部备注不会重置它。即使没有收到 Webhook,也请定期运行这种等待队列扫描,让旧会话重新浮现。
无需重读收件箱即可追上进度
使用 GET /api/v1/sync 并授予 conversations:read。持久变更流包含对话变更、标签、消息、联系人属性、记忆和删除记录。每种负载还需要各自的读取权限:消息正文需要 messages:read,记忆需要 contact-memory:read。受限的凭据只会收到其被允许的渠道。
- 不带游标开始,沿着 nextCursor 一直读取到 hasMore 为 false,然后保存该游标。
- 读取当前的对话和联系人列表,以及初始状态所需的任何历史记录。
- 从保存的游标开始重放,捕获读取期间发生的变更。处理完每一页后,保存 nextCursor。
按事件 id 去重:重放至少投递一次,因此下游操作需要自己的防重复机制。不带游标的请求只覆盖最近一小时,并非完整快照。事件保留 30 天;HTTP 410 resync_required 表示需要重新初始化。扩大权限范围或渠道访问后也需要重新初始化。limit 最大为 100,maxBodyChars 最大为 10,000(默认 500)。设置 compact=true 可获得上限为 200 个字符的消息 textPreview/textTruncated 字段,而不是 body/bodyTruncated。Webhook 可以唤醒智能体;即使没有 Webhook 订阅或 Webhook 投递积压,变更流依然可用。
检查只做一次,结果共享
在重复调查之前,先读取 list_conversation_checks(GET /api/v1/conversations/{conversationId}/checks)。使用 record_conversation_check(PUT 到同一路径)保存结果,提供 key、result、checkedBy,以及可选的 reference(卡片 ID 或 URL)。例如:key=product-version、result=Shopstar Go verified、checkedBy=Engineer、reference=card-X。Sonny 会记录已认证的 actorId 和 checkedAt 时间戳。重复使用某个 key 只会替换该项检查;这是当前状态,而不是历史日志。读取需要 conversations:read,写入需要 conversations:write,二者都限定在对话所属的渠道。这些调用不会发送回复,也不会把卖家标记为已回复。
批量分配和更新工作
通过 GET /api/v1/members and /teams(members:read)查看活跃的、可分配的同事和团队。响应包含在线状态和实际的渠道访问权限,但不含邮箱地址。使用 conversations:write 更改 status、priority、assigneeId、agentGroupId、snoozedUntil、snoozedUntilReply、addTagIds 或 removeTagIds。
POST /api/v1/conversations/batch
{
"conversationIds": ["conversation_1", "conversation_2"],
"updates": { "agentGroupId": "team_1", "assignment": "round_robin" }
}轮流分配会选择一位在线、且能访问该对话渠道的团队成员。没有符合条件的成员时,单个更新返回 409,批量中的对应项失败。每个批量最多接受 100 个不重复的 ID,并对每个对话原子地应用一次补丁。请检查每一个 { id, ok, error? } 结果;部分项可能会失败。批量操作按当前基于请求的频率限制计算,不按项目数量加权计费。
与 Sonny AI 共享客户信息
使用 contact-memory:read/write 列出、保存和删除联系人记忆。需同时提供 contactId 和一个可访问的 sourceId;该联系人必须在此来源上有对话。保存的事实与应用内使用相同的校验、去重处理和限制,并记录为手动记忆。
在 /api/v1/properties 读取属性定义,在 /api/v1/contacts/{contactId}/properties 读取或设置属性值。MCP 提供 list_properties、get_contact_properties 和 set_contact_property。这些操作需要 contacts:read/write 以及全部渠道的访问权限。只设置 propertyId 或 propertyName 其中之一,值为字符串,或用 null 清除。文本、数字、URL、日期和选项值都会根据字段定义进行校验。
PUT /api/v1/contacts/contact_1/properties
{ "propertyName": "Plan", "value": "Pro" }
GET /api/v1/contacts?property[Plan]=Pro属性筛选匹配精确存储的字符串;多个属性必须全部匹配。通过 API 写入的值会在 Co-Pilot 和自动回复中标注为 API 数据。现有的已验证客户和来源规则依然适用。普通的手动内部字段值仍不会纳入此 AI 上下文。
读取与团队相同的报表
授予 reporting:read 后调用 GET /api/v1/reporting/{kind}。报表类型有 overview、volume、response-times、agents、sources、tags、csat、ai、knowledge、leads 和 online-hours。overview 综合了数量、响应时间和满意度。筛选条件包括 period(1–365 天,默认 30)、成对的 from/to 日期(to 不包含在内)、granularity(day/month)、source、assigneeId 和 tagId。source 接受 all、all-chat、all-email、website:{id} 或 email:{id}。
报表使用与仪表板相同的查询和当前的访问检查。knowledge 报表按日期和被允许的渠道统计,不受所选来源、负责人或标签影响。online-hours 衡量可访问同事在工作区中的在线时长;其中的对话数量仍按渠道限定。现有的 /csat 端点保留单独的 csat:read 权限范围,统计对象可能不同。
在回复或内部备注中发送文件
授予 attachments:write,并为某个对话上传最大 25 MB 的文件。POST /api/v1/attachments 接受 multipart 格式的 file 和 conversationId 字段。响应包含 id 和 expiresAt。在一小时内,最多可将 10 个 attachmentIds 传给一条回复或备注。每次上传都绑定到你的用户和该对话,且只能使用一次。未使用的上传会在过期后清理。
POST /api/v1/conversations/conversation_1/reply
{ "attachmentIds": ["upload_1"] }回复需要 messages:send;内部备注需要 messages:write,且永远不会发给客户。支持只含附件的消息。邮件回复会在邮件大小限制内附上文件,其余文件则提供下载链接;离线聊天邮件会包含文件链接。只要附件还在,邮件中的链接就一直可用,收件人可以稍后打开。转发邮件会共享这些文件的访问权限。请检查 emailDeliveryStatus 了解投递失败情况。
经授权的消息读取包含 downloadUrl、downloadExpiresAt、aiStatus、aiDescription 和 aiExtractedText,链接视频(Loom、Vimeo 等)还包含 videoTranscripts。下载链接有效期为 15 分钟;需要新链接时请重新读取消息。新的 API/MCP 上传使用私有存储。较早的附件仍为公开,并标记为 access=legacy_public:其原始 URL 不会过期。当工作区开通了 Sonny AI 时,读取消息会触发读取其中的图片。图片识别和视频文字稿会在消息到达后不久完成:若仍有任务在运行,响应会以 readsInProgress 开头,其中的 nextStep 给出了应调用的确切操作。传入 waitSeconds(最多 30)可在一次请求中等待它们完成。面向客户的聊天组件和实时消息永远不会包含提取内容或文字稿。
知识库
从外部来源同步
使用稳定的外部 ID 同步文章和分类,导入 Markdown 或 HTML,上传图片,设置排序,并管理读者受众。重复执行 upsert 会更新已有内容。
- 选择你渠道的 sourceId,并授予 kb:read 和 kb:write。将 API 密钥保存在你的服务器上,并限制其渠道访问权限。
- 先创建分类,再将文章作为草稿同步。发布前检查其格式和访问权限。
- 配置帮助中心访问权限、发布,并测试读者视图。之后的更新请使用分页和稳定的外部 ID。
管理客户受众
根据已验证的客户特征创建群组,并应用到帮助中心、分类或文章。所有继承的限制都必须满足。API 和 MCP 凭据在其权限范围内以员工身份操作;请预览并测试真实的客户会话,以检查读者访问权限。
设置并测试帮助中心受众