消息API对接指南:REST、SMPP与Webhook
面向开发者的消息API对接指南:详解REST、SMPP与Webhook的区别,覆盖鉴权、幂等键、送达回执(DLR)、失败重试、限流处理与沙箱测试,帮助出海团队稳定接入WhatsApp、短信和邮件等渠道,帮助团队少走弯路、更快完成上线并稳定运行。
作者: OmniChannels.ai Editorial Team · 审阅: BroadNet Messaging Solutions Team
集成
简短回答
应用程序发送消息用REST API;只有在已经具备电信级基础设施的高并发短信场景才选SMPP;接收送达回执和用户回复则用Webhook。每次调用都要鉴权,每次发送都带上幂等键,避免重试造成重复发送;把送达状态视为异步结果;遇到HTTP 429和5xx时退避重试;上线前先在沙箱中测试各种失败路径。
本页内容
要点速览
- REST适合大多数应用集成;SMPP是为消息系统之间的短信吞吐量设计的持久二进制协议。
- 发送请求被接受,只代表消息已进入队列,并不代表已送达;最终状态稍后通过Webhook或SMPP送达回执返回。
- HTTP 429 Too Many Requests 在RFC 6585中定义;客户端应放慢速度,并遵守Retry-After响应头。
- 幂等键可以让您在发送超时后安全重试,而不会让客户收到两条相同的消息。
- Meta会对WhatsApp Cloud API的Webhook签名,接收方因此可以验证事件确实来自Meta。
本指南面向需要把应用接入WhatsApp、短信或邮件消息服务商的后端开发者、解决方案架构师和CTO。文中说明应选用哪种接口,以及如何处理鉴权、幂等性、送达回执、重试、限流和测试,并附有请求与响应的示意结构。如果您想把会话同步到CRM,请参阅配套文章:用Webhook连接CRM。
该选REST、SMPP还是Webhook?
发送用REST,接收用Webhook;SMPP只用于您已经在运行SMPP的高并发短信场景。三者是互补而不是竞争关系:大多数集成都是出站用REST调用、回传用Webhook。
| 对比项 | REST API | SMPP | Webhook |
|---|---|---|---|
| 方向 | 您的应用 → 服务商 | 单一会话内双向 | 服务商 → 您的应用 |
| 传输方式 | HTTPS请求/响应 | 持久TCP会话,二进制PDU | 向您的端点发起HTTPS POST |
| 支持渠道 | WhatsApp、短信、邮件等 | 仅短信 | 所有渠道的事件 |
| 典型用途 | 发送消息、管理模板、查询状态 | 消息系统之间的批量短信 | 送达状态、用户回复 |
| 优势 | 简单、对防火墙友好、载荷丰富 | 吞吐量高、有窗口机制、电信行业标准 | 实时、无需轮询 |
| 注意事项 | 限流、超时 | 会话管理、bind、保活 | 重试、重复、安全性 |
SMPP(Short Message Peer-to-Peer)会话以bind开始(transmitter、receiver或transceiver),用submit_sm发送消息,通过deliver_sm接收送达回执和上行短信,并用enquire_link保持连接。它效率高,但运维成本比HTTPS更重。
应该如何鉴权?
使用服务商提供的最强方式,不要把密钥写进代码,并且双向都要鉴权。
- **出站调用:**通过TLS,在
Authorization头中发送API密钥或OAuth 2.0 bearer token。把它们存放在密钥管理器中,定期轮换,人员变动后也要轮换。 - **SMPP:**bind时使用system ID和密码,通常限制为白名单IP,如服务商支持,再叠加TLS。
- **入站Webhook:**对每个事件都验证签名。Meta使用您的应用密钥,对WhatsApp Cloud API的Webhook载荷计算HMAC-SHA256签名,放在
X-Hub-Signature-256头中;其他服务商通常也有类似机制。请在解析之前,基于原始请求体计算签名。
每个环境使用独立的凭证,这样泄露的测试密钥就无法发送生产流量。
如何安全地发送一条消息?
通过队列发送,带上幂等键,并把响应理解为“已接受”而不是“已送达”。
发送请求示例
下面的结构是用于说明的伪JSON,并非某家服务商的真实API。
POST /v1/messages
Authorization: Bearer <token>
Idempotency-Key: 7f3c9a2e-order-55821-shipped
{
"channel": "whatsapp",
"to": "+9715XXXXXXXX",
"template": {
"name": "order_shipped",
"language": "ar",
"variables": ["Layla", "55821", "15 March"]
},
"client_reference": "order-55821",
"callback_url": "https://api.example.com/webhooks/messaging"
}
响应示例
202 Accepted
{
"message_id": "msg_01HZX...",
"status": "accepted",
"client_reference": "order-55821",
"created_at": "2026-10-09T12:00:00Z"
}
请立即把message_id与您自己的业务引用一并保存。此后发生的一切都会异步返回。
为什么幂等性很重要?
因为网络超时往往发生在服务端已经处理请求之后。如果发送请求超时而您盲目重试,客户可能收到两条验证码或两条发货通知。幂等键能让服务端识别出这是一次重试,并返回第一次的结果。
行之有效的规则:
- 幂等键应由业务事件生成(例如订单ID加事件类型),而不是每次尝试都生成随机值。
- 同一次发送的每次重试都使用同一个键。
- 键的保留时间要覆盖您的重试窗口。
- 如果服务商不支持幂等键,请在发送之前自行去重。
IETF的Idempotency-Key头草案把这一模式标准化到了HTTP API中;各服务商的实现并不相同,请阅读其文档。
送达回执是如何工作的?
送达状态会以事件形式稍后返回:WhatsApp和大多数REST API通过Webhook,SMPP则通过deliver_sm回执。各状态的含义因渠道而异;我们的消息送达状态指南对此逐一说明。
状态Webhook示例
POST /webhooks/messaging
X-Signature: sha256=<hmac>
{
"event_id": "evt_9c1...",
"type": "message.status",
"message_id": "msg_01HZX...",
"client_reference": "order-55821",
"status": "delivered",
"timestamp": "2026-10-09T12:00:04Z",
"error": null
}
请以防御性的方式处理状态事件:
- **去重:**按
event_id,或按消息ID加状态去重。 - **不要回退:**事件乱序到达时,不要把消息从已读退回已送达。
- 快速返回2xx,再从队列中异步处理。
- **记录错误码:**对失败的消息,判断哪些错误可以重试。
- **允许缺失:**部分短信线路只返回有限的回执,已读状态则取决于渠道和用户设置。
如何处理重试和限流?
只重试有可能成功的请求,采用带抖动的指数退避,并遵从服务端发出的信号。
| 响应 | 含义 | 处理方式 |
|---|---|---|
| 2xx | 已接受 | 保存ID,等待状态 |
| 400 / 422 | 请求无效(号码、模板、变量) | 不要重试,修正数据 |
| 401 / 403 | 鉴权或权限问题 | 不要重试,触发告警 |
| 409 | 冲突,常见于重复的幂等键 | 获取第一次的结果 |
| 429 | 请求过多(RFC 6585) | 等待Retry-After时间或退避 |
| 5xx / 超时 | 服务端或网络错误 | 使用同一幂等键并退避重试 |
RFC 9110定义了Retry-After头,其值可以是秒数或日期。请在发送前加一层客户端限流器,使发送速率始终低于服务商公布的限制,而不是靠错误响应来摸索限制。WhatsApp在Meta侧还限制了您能触达的独立客户数量,详见消息限额与质量评级。
上线前应该如何测试?
不仅要测顺利路径,更要测失败路径。
上线前检查清单
- 用真实长度的变量值发送每个模板,包括阿拉伯语文本。
- 人为制造超时,确认重试不会造成重复发送。
- 向无效号码发送,确认错误被处理且不会重试。
- 把同一个Webhook重放两次并打乱顺序,确认最终只有一个状态。
- 发送一个签名错误的Webhook,确认被拒绝。
- 如果允许,对沙箱做压测以触发429。
- 轮换一次API密钥,确认没有停机。
- 检查日志里有消息ID,但没有完整的消息正文或验证码。
- 在每个渠道上用内部号码做小规模生产试点。
沙箱很难完全还原运营商和Meta的行为,所以上线后的最初几周请持续监控。
实战示例:验证码与订单通知服务
“Qafilah Logistics”(虚构)是沙特阿拉伯的一家包裹物流公司,通过WhatsApp发送订单更新、以短信作为备用,并发送身份验证验证码。
- **架构:**订单事件进入队列;发送worker以
shipment-id:event作为幂等键调用REST API。 - **备用:**如果WhatsApp对非WhatsApp用户返回失败状态,worker会用新的键
shipment-id:event:sms发送短信。 - **验证码:**验证码有效期很短,因此过了有效期不再重试发送;由用户重新申请新验证码。参见OTP验证消息指南。
- **回执:**Webhook接收端校验签名、去重,并更新一个永不回退的状态表。
- **限流:**令牌桶限流器把每个渠道的发送速率限制在公布的上限之下。
常见的集成错误有哪些?
- 把“已接受”当作“已送达”。
- 每次重试都换一个新的幂等键。
- 在Webhook请求内部做繁重处理。
- 跳过Webhook的签名校验。
- 反复循环重试4xx校验错误。
- 把验证码和完整消息内容写入日志。
- 在测试环境使用生产凭证。
OmniChannels.ai 如何提供帮助
OmniChannels.ai由BroadNet Technologies提供技术支持,提供公开文档化的REST/JSON API,配有OpenAPI 3.1规范和TypeScript SDK,覆盖SMS、WhatsApp、RCS、Messenger、Instagram、Telegram、邮件和推送,其中包括支持一键、零点击和复制验证码OTP的WhatsApp身份验证模板。Webhook以统一规范的格式回传送达状态,SMPP 3.4通过TLS服务高并发短信,MCP服务器则可连接AI Agent。带筛选和CSV导出的送达报告,有助于您对账集成实际发出的消息。请从开发者文档和快速入门开始。
常见问题
对接消息服务商应该选REST还是SMPP?
几乎所有应用场景都建议选REST:它基于HTTPS,安全配置简单,并且支持WhatsApp等富媒体渠道。如果您发送的短信量很大、已经在运行SMPP客户端,并且需要带窗口机制的持久连接,再选SMPP。SMPP只适用于短信;WhatsApp、邮件和社交渠道都使用HTTP API。
消息API中的幂等键是什么?
幂等键是您的系统随请求一起发送的唯一值,服务端据此识别重复请求。如果发送请求超时,您用同一个键重试,服务商会返回第一次的结果,而不是再发一条消息。IETF已有Idempotency-Key HTTP头的草案标准,但各服务商的实现方式不同,请以其文档为准。
为什么送达回执有时会乱序到达?
状态事件由运营商、Meta和服务商等不同系统产生,并通过带重试的网络传递。已读事件可能先于已送达事件到达,重复事件也属正常。请连同时间戳一起保存每个状态,不要让消息从较新的状态退回较早的状态,并按消息ID和状态去重。
应用应该如何应对限流?
先阅读服务商公布的限制,把待发送消息放入队列,而不是直接在用户请求中发送,并在自己一侧使用令牌桶等限流器。收到HTTP 429时暂停,按Retry-After头给出的时间重试,或采用带抖动的指数退避。不要重试4xx类的校验错误。
在消息沙箱中应该测试什么?
测试鉴权失败、无效手机号、模板变量错误、带幂等重试的超时、重复和乱序的Webhook、限流响应、长文本和阿拉伯语消息,以及Webhook签名校验。随后用真实号码做小规模生产试点,因为沙箱很难完全还原运营商或Meta的真实行为。
资料来源
继续阅读
更多指南集成
如何通过 Webhook 将 CRM 接入全渠道收件箱
通过 Webhook 将 CRM 接入全渠道收件箱的技术指南:应该同步哪些事件、如何做幂等处理与失败重试、如何匹配联系人、如何满足数据隐私合规要求,并附参考架构,帮助出海企业打通客户沟通与客户管理数据,减少人工录入,并附吉达诊所集团的实操案例。
8 分钟阅读
集成
短信API与SMPP对比:该用哪种连接方式?
短信API与SMPP全面对比:会话与bind、窗口机制、吞吐量、送达回执、编码方式、TLS安全、运维成本以及迁移步骤,帮助工程团队判断该用REST、SMPP还是两者混合使用,找到最适合自己业务量和团队能力的短信对接方案,少走弯路。
12 分钟阅读
WhatsApp
WhatsApp Cloud API 错误码:含义与排查方法
整理最常见的 WhatsApp Cloud API 错误码,包括 131047、131026、132001 和 130429:说明每个错误码的含义、修复方法,以及哪些情况下不应该重试,帮助开发和运营团队快速定位发送失败的原因。,并附重试策略清单
8 分钟阅读
