sent-integration-starter
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSent Integration Starter
Sent集成入门指南
Bring up a Sent integration in four stages: authenticate, send idempotently, receive verified events, then harden. Do not conflate them — most broken integrations pass stage one and skip stage three.
通过四个阶段搭建Sent集成:认证、幂等发送、接收已验证事件、然后强化集成。请勿混淆这些阶段——大多数集成失败都是因为通过了第一阶段却跳过了第三阶段。
Stage 1: client and credentials
阶段1:客户端与凭证
Direct Sent v3 REST requests authenticate with the header. An application proxy may accept from its own callers, and the Sent MCP server uses client-managed OAuth, but neither changes the REST header sent to . Organization keys may add to act for a child profile; a profile-scoped key that sends that header receives .
x-api-keyAuthorization: Bearerapi.sent.dmx-profile-id403| Language | Package | Client |
|---|---|---|
| TypeScript | | |
| Python | | |
| Go | | |
| Java | | |
| C# | | |
| PHP | | |
| Ruby | | |
Every SDK except PHP reads automatically. Single-endpoint receiver samples read ; multi-tenant production receivers need a secret registry keyed by webhook id instead of one process-wide secret. Older documentation uses and — treat those as aliases and standardize on the names.
SENT_DM_API_KEYSENT_DM_WEBHOOK_SECRETSENT_API_KEYSENT_WEBHOOK_SECRETSENT_DM_Choose the client lifecycle from the credential model. A single-account service with one server-managed key should reuse a long-lived client and its connection pool. A multi-tenant proxy that resolves a caller or profile credential per request should construct the client for that request and discard it, so tenant credentials cannot leak through shared state. Framework-specific wiring, the Ruby naming quirk, and per-ecosystem background-work choices are in references/sdk-and-frameworks.md.
messages.send_Validate configuration at boot and fail fast when the key is missing, rather than surfacing an auth error on the first customer send.
直接调用Sent v3 REST接口需通过头进行认证。应用代理可能会从自身调用者处接收凭证,Sent MCP服务器使用客户端管理的OAuth,但这两者都不会改变发送至的REST请求头。组织级密钥可添加以代表子配置文件操作;若使用配置文件范围的密钥发送该头,会收到错误。
x-api-keyAuthorization: Bearerapi.sent.dmx-profile-id403| 语言 | 包 | 客户端 |
|---|---|---|
| TypeScript | | |
| Python | | |
| Go | | |
| Java | | |
| C# | | |
| PHP | | |
| Ruby | | |
除PHP外,所有SDK都会自动读取。单端点接收器示例会读取;多租户生产级接收器需要一个按Webhook ID索引的密钥注册表,而非全局单一密钥。旧版文档使用和——可将其视为别名,并统一使用前缀的命名。
SENT_DM_API_KEYSENT_DM_WEBHOOK_SECRETSENT_API_KEYSENT_WEBHOOK_SECRETSENT_DM_根据凭证模型选择客户端生命周期。使用单个服务器管理密钥的单账户服务应复用长期存在的客户端及其连接池。每个请求解析调用者或配置文件凭证的多租户代理应针对该请求构建客户端并在使用后丢弃,避免租户凭证通过共享状态泄露。框架特定配置、Ruby的命名特性以及各生态系统的后台任务选择可查看references/sdk-and-frameworks.md。
messages.send_在启动时验证配置,当密钥缺失时快速失败,而非在首次客户发送时才暴露认证错误。
Stage 2: idempotent sends
阶段2:幂等发送
json
{
"to": ["+14155551234"],
"template": {
"name": "order_confirmation",
"parameters": { "order_id": "12345" }
},
"sandbox": true
}totemplatetextchannelchannelsent-routing-strategistSend on every POST, PUT, and PATCH, derived deterministically from your own domain object (for example the order id plus the notification type) so a retry after a timeout cannot double-send. Keys are 1–255 characters of , cached 24 hours per key per customer. A replay returns the cached body with and . A duplicate arriving while the original is still in flight waits up to five seconds and then fails ; a means the idempotency store was unavailable and the request was deliberately not executed.
Idempotency-Key[A-Za-z0-9_-]Idempotent-Replayed: trueX-Original-Request-Id409 CONFLICT_001503 SERVICE_001202message_idjson
{
"to": ["+14155551234"],
"template": {
"name": "order_confirmation",
"parameters": { "order_id": "12345" }
},
"sandbox": true
}totemplatetextchannelchannelsent-routing-strategist在每个POST、PUT和PATCH请求中发送,该密钥应从您自己的领域对象(例如订单ID加通知类型)确定性生成,这样超时后的重试不会导致重复发送。密钥长度为1-255字符,允许的字符为,每个客户的密钥会被缓存24小时。重放请求会返回缓存的响应体,并带有和头。当原始请求仍在处理时收到重复请求,会等待最多5秒,然后返回错误;表示幂等存储不可用,请求未被执行。
Idempotency-Key[A-Za-z0-9_-]Idempotent-Replayed: trueX-Original-Request-Id409 CONFLICT_001503 SERVICE_001202message_idStage 3: verified webhook receiver
阶段3:已验证的Webhook接收器
An integration without a receiver has no delivery truth. Register an endpoint, then verify every delivery: HMAC-SHA256 over , keyed on the base64-decoded secret after stripping , compared in constant time, rejecting timestamps outside 300 seconds. No SDK ships a verifier in any language.
{x-webhook-id}.{x-webhook-timestamp}.{raw_body}whsec_Acknowledge with before doing work, and deduplicate on for outbound events and for inbound. Ten consecutive failed deliveries disable the endpoint. Full mechanics belong to ; treat a verified, fast-acknowledging, deduplicating receiver as a launch requirement here.
200{message_id}:{message_status}message_idsent-webhook-engineer没有接收器的集成无法获取真实的送达状态。注册一个端点,然后验证每一次送达:使用去除前缀后经base64解码的密钥,对进行HMAC-SHA256签名,以恒定时间进行比较,拒绝超出300秒的时间戳。目前没有任何语言的SDK提供验证器。
whsec_{x-webhook-id}.{x-webhook-timestamp}.{raw_body}先返回确认,再处理任务;针对出站事件按去重,针对入站事件按去重。连续十次送达失败会禁用该端点。完整机制可查看;在此处,需将已验证、快速确认、可去重的接收器视为发布必备条件。
200{message_id}:{message_status}message_idsent-webhook-engineerStage 4: harden
阶段4:强化集成
Retry policy by response class
按响应类别制定重试策略
| Response | Retry | How |
|---|---|---|
| No | Success |
| No | Fix the request |
| No | Stop immediately; ten consecutive auth failures lock the credential with escalating lockouts |
| No | The referenced object does not exist |
| Yes, once, after a pause | A concurrent duplicate is in flight |
| Yes | Honor |
| Yes | Exponential backoff with jitter and a ceiling |
| Timeout with no response | Retry safely only with evidence | Reuse the same |
The standard limit is 200 requests per minute on a sliding window. and are limited to 10 per minute. Rate-limit headers appear only on responses, so pacing must be designed rather than measured — batch up to 1,000 recipients per request and pace at roughly one request per second for bulk work.
POST /v3/webhooks/{id}/rotate-secretPOST /v3/webhooks/{id}/test429| 响应 | 是否重试 | 方式 |
|---|---|---|
| 否 | 成功 |
| 否 | 修改请求 |
| 否 | 立即停止;连续十次认证失败会锁定凭证并逐步延长锁定时间 |
| 否 | 引用的对象不存在 |
| 是,暂停后重试一次 | 存在并发的重复请求 |
| 是 | 遵循 |
| 是 | 带抖动的指数退避策略,并设置上限 |
| 无响应超时 | 仅在有依据时安全重试 | 复用相同的 |
标准限制为滑动窗口内每分钟200次请求。和的限制为每分钟10次。限流头仅出现在响应中,因此必须主动设计请求节奏而非被动测量——批量请求最多包含1000个收件人,批量处理时大致保持每秒一次请求的节奏。
POST /v3/webhooks/{id}/rotate-secretPOST /v3/webhooks/{id}/test429Error handling
错误处理
Errors arrive as . Branch on the prefix family (, , , , , , ) rather than on message text or on individual codes. The full 46-code catalog with retry classification is in references/errors-and-limits.md.
{success, data, error: {code, message, details, doc_url}, meta: {request_id, timestamp, version}}error.codeAUTH_VALIDATION_RESOURCE_BUSINESS_CONFLICT_SERVICE_INTERNAL_Two codes are counterintuitive: and are documented as request-level errors, but on the request is accepted with and the affected messages finalize as and . Insufficient balance therefore does not fail the send call.
BUSINESS_003BUSINESS_004POST /v3/messages202BLOCKEDFILTERED错误响应格式为。应根据的前缀类别(、、、、、、)进行分支处理,而非根据消息文本或单个错误码。包含重试分类的完整46项错误码目录可查看references/errors-and-limits.md。
{success, data, error: {code, message, details, doc_url}, meta: {request_id, timestamp, version}}error.codeAUTH_VALIDATION_RESOURCE_BUSINESS_CONFLICT_SERVICE_INTERNAL_有两个错误码较为特殊:和被记录为请求级错误,但在调用时,请求会被接受,受影响的消息最终会变为和状态。因此余额不足不会导致发送调用失败。
BUSINESS_003BUSINESS_004POST /v3/messages202BLOCKEDFILTEREDObservability
可观测性
Log on every response, success or failure — it is the correlation handle for support. Record the mapping from your logical send to the returned values, and keep an append-only event history so a reroute's sequence remains auditable. Never log the API key, the webhook signing secret, , or raw recipient message content beyond your retention policy.
meta.request_idmessage_idpayment_details无论响应成功或失败,都要记录——这是支持团队的关联标识。记录您的逻辑发送与返回的值之间的映射,并保留追加式事件历史,以便重新路由的序列可被审计。切勿记录API密钥、Webhook签名密钥、或超出您保留策略的原始收件人消息内容。
meta.request_idmessage_idpayment_detailsLaunch checklist
发布检查清单
- Credentials load from the environment; nothing is committed, and separate keys exist per environment.
- Client lifecycle matches credential scope: shared for one server-managed key, per request for tenant-supplied credentials.
- on every mutating call, derived deterministically.
Idempotency-Key - Retry policy distinguishes retryable from terminal by error family.
- Bulk paths pace against 200 requests per minute and batch to at most 1,000 recipients.
- Webhook receiver verifies signature and timestamp, returns fast, and dedupes.
200 - Receiver returns non-2xx on genuine failure so Sent retries.
- to tenant mapping is persisted before sending.
message_id - is logged; secrets and card data are not.
request_id - Sandbox smoke test passes, then a real send reaches .
DELIVERED - Alerting covers webhook ,
consecutive_failuresvolume, and filtered or blocked rates.429
- 凭证从环境变量加载;无硬编码凭证,每个环境使用独立密钥。
- 客户端生命周期与凭证范围匹配:单服务器管理密钥使用共享客户端,租户提供的凭证则按请求创建客户端。
- 每个变更请求都携带,且该密钥由确定性方式生成。
Idempotency-Key - 重试策略根据错误类别区分可重试与终端错误。
- 批量请求按每分钟200次的限制控制节奏,每次批量最多包含1000个收件人。
- Webhook接收器验证签名和时间戳,快速返回,并进行去重。
200 - 接收器在真正失败时返回非2xx状态码,以便Sent进行重试。
- 在发送前持久化与租户的映射关系。
message_id - 记录;不记录密钥和卡片数据。
request_id - 沙箱冒烟测试通过,且至少有一次真实发送通过接收器确认已。
DELIVERED - 告警覆盖Webhook、
consecutive_failures请求量以及过滤或拦截率。429
Verification
验证
Run the local preflight, which needs no credentials and no network:
bash
python3 scripts/preflight.py --self-testThen verify a real path with , which authenticates and validates without executing, and finally with one live send confirmed to through the receiver.
"sandbox": trueDELIVERED运行本地预检,无需凭证和网络:
bash
python3 scripts/preflight.py --self-test然后使用验证真实路径,该模式会进行认证和验证但不会执行实际发送,最后通过接收器确认至少一次真实发送已。
"sandbox": trueDELIVEREDBoundaries
边界说明
Use for receiver depth, for channel choice, for a confirmed one-off send, for inbound and consent, for multi-tenant provisioning, and when replacing another CPaaS provider.
sent-webhook-engineersent-routing-strategistsent-messagingsent-two-way-messagingsent-profile-provisioningmigrate-to-sent如需深入了解接收器,请使用;渠道选择请使用;确认一次性发送请使用;入站消息与同意管理请使用;多租户配置请使用;替换其他CPaaS提供商请使用。
sent-webhook-engineersent-routing-strategistsent-messagingsent-two-way-messagingsent-profile-provisioningmigrate-to-sent