用途:在已有代码库中上线 Sent v3 集成,按认证、幂等发送、接收校验事件、加固四个阶段推进,避免只做认证而跳过回调接收。
认证与客户端:REST 请求使用 x-api-key 头;组织密钥可加 x-profile-id 代表子 profile,但 profile 级密钥发送该头会返回 403。SDK 示例:TypeScript 用 @sentdm/sentdm 的 new SentDm({ apiKey });Python 用 sentdm(导入 sent_dm)的 Sent(api_key=api_key) 或 AsyncSent;Go 用 github.com/sentdm/sent-dm-go 的 sentdm.NewClient(option.WithAPIKey(apiKey));Java 用 dm.sent:sent-java;C# 用 Sentdm 的 new SentClient { ApiKey = apiKey };PHP 用 sentdm/sent-dm-php;Ruby 用 sentdm。单账号长生命周期客户端复用连接池,多租户代理按请求创建并丢弃。启动时校验密钥,缺失即失败。
幂等发送:仅 to 必填,提供 template 或 text,省略 channel 交由自动路由;不要写多值 channel 数组。所有 POST/PUT/PATCH 携带 Idempotency-Key,由自有领域对象确定性派生;键为 1–255 位 [A-Za-z0-9_-],每客户每键缓存 24 小时。重放返回缓存体并带 Idempotent-Replayed: true;原请求在途时重复请求等待最多 5 秒后返回 409 CONFLICT_001;503 SERVICE_001 表示幂等存储不可用且请求未执行。202 表示已接受而非已送达,需立即持久化 message_id 与自有租户标识。
Webhook 接收端:无 SDK 提供校验器,需自行用 HMAC-SHA256 对 {x-webhook-id}.{x-webhook-timestamp}.{raw_body} 验签,密钥为去掉 whsec_ 后 base64 解码,常量时间比较,拒绝时间戳偏差超过 300 秒的请求。先返回 200 再处理,按 {message_id}:{message_status}(出站)或 message_id(入站)去重;连续 10 次投递失败会禁用端点。
加固:按响应类别重试——2xx、400/422、401/403、404 不重试,401/403 连续 10 次会锁定凭据;409 CONFLICT_001 暂停后重试一次;429 遵循 Retry-After 并加抖动退避;5xx 与 503 SERVICE_001 指数退避加抖动与上限;超时仅在幂等键存在时安全重试。限流为滑动窗口每分钟 200 请求,rotate-secret 与 test 端点每分钟 10 次;限流头仅在 429 出现,需主动设计节流,批量每请求最多 1000 收件人。错误体为 {success, data, error:{code, message, details, doc_url}, meta:{request_id, timestamp, version}},按 AUTH_、VALIDATION_、RESOURCE_、BUSINESS_、CONFLICT_、SERVICE_、INTERNAL_ 前缀分支;注意 BUSINESS_003/004 在 POST /v3/messages 上仍返回 202,消息最终为 BLOCKED 或 FILTERED,余额不足不会使发送调用失败。记录 meta.request_id 与逻辑发送到 message_id 的映射,不要记录密钥、签名密钥、支付数据或原始消息内容。验证:运行 python3 scripts/preflight.py --self-test(无需凭据与网络),再用 sandbox 为 true 验证路径。
限制与边界:SDK 不含验签器,需自行实现接收端校验与去重;多租户接收端需按 webhook id 维护密钥注册表;渠道选择、接收端深度、入站与同意、多租户开通等属于其他专门技能范围。