Bird 与 Prelude
Bird 与 Prelude 的 Verify 对比
Prelude 围绕可供分支判断的风险裁定而构建,Bird 没有与之对应的功能。两者的 API 在其他方面足够相似,迁移基本上只是重命名。本页讨论的是:对于您正在构建的产品,这两个差异哪个更重要。
Prelude 的优势所在。
Bird 的不同之处。
Prelude 的优势所在
可供分支判断的裁定。创建调用接受 IP、设备和指纹信号,并返回 success、retry、challenged、blocked 或 shadow_blocked 的路由裁定,拒绝时附带原因。Bird 的创建调用返回的是验证本身:没有裁定、没有信号对象、没有影子封禁。依赖该决策进行注册拦截的流程,必须在调用 Bird 之前自行做出判断。
Bird 无法覆盖的渠道。语音通话、RCS、Viber、Zalo 和静默网络认证,覆盖 230 多个国家和地区。两个平台都支持 SMS、WhatsApp 和 Telegram,因此差距在于这五个渠道,而非全部:Prelude 通过 Viber 或 Zalo 触达的号码在 Bird 上会回退到 SMS,这是一个值得在试点阶段实测而非等到全量才发现的送达率问题。
消息内容和回退策略由您掌控。包含变量的模板、语言区域、自定义发送者 ID 和自定义验证码均可按请求设置,max_auto_fallbacks 和 force_challenge 可按调用调节升级策略。在 Bird 上,验证码文本由 Bird 控制,回退遵循该国家的渠道计划;发送者按渠道而非按请求配置,且只有邮件渠道可使用您自己的地址。
Bird 的不同之处
验证失败时会告诉您具体的失败类型。Prelude 将错误验证码和尝试次数耗尽合并为一个失败状态。Bird 返回 incorrect_code、expired 或 attempts_exhausted 的具体原因,并附带 attempts_remaining,这样界面可以告知用户还剩多少次尝试机会,无需您自行计数。
投递事件通过工作空间订阅获取,带有签名。Prelude 将事件发送到您为每次验证设置的 callback_url。Bird 的端点只需注册一次,每个端点订阅所需的事件类型,每次投递均按 Standard Webhooks 规范签名——URL 不再出现在请求体中,接收方有签名可验证。
智能代理可以运行验证流程。Bird 托管的 MCP 服务器为代理提供三个验证工具,操作真实的工作空间:发起验证、校验验证码、推进到下一个渠道。它无法重新配置背后的策略,这是有意为之而非遗漏。
对比矩阵
逐项能力对比。
两者的 API 结构相似,因此大多数对比项持平,差异很小。请将安全重试行与 Twilio Verify 页面对照阅读:在这两项对比中 Bird 都胜出,因为两者的创建接口文档中都没有幂等键。Prelude 的风险层是上文提到的让步,而非矩阵中的一行,因为 Bird 没有可与之对比的功能。
| Capability | Bird | Prelude | Who wins? |
|---|---|---|---|
| 创建请求 | 使用 Bearer 密钥向 /v1/verify/verifications 发送 JSON。接收方为 to.phone_number 或 to.email,对同一活跃接收方再次调用创建会重试而非发起新验证。 | 使用 Bearer 密钥向 v2 验证端点发送 JSON。接收方为 target.type 和 target.value,对同一活跃接收方再次调用创建同样会重试。 | |
| 安全重试 | 在创建请求中添加 Idempotency-Key 头即可使重试安全。 | 其创建接口文档中没有记录幂等键或专属请求头,因此超时后重试可能会发出第二个验证码。dispatch_id 并非幂等键:Prelude 将其定义为来自前端 SDK 的调度标识符,用于让其反欺诈层将捕获的信号与此次验证关联起来。 | |
| 验证失败时返回的信息 | success 为 false,附带 incorrect_code、expired 或 attempts_exhausted 的原因,以及 attempts_remaining。 | failure 状态同时涵盖错误验证码和尝试次数耗尽,expired_or_not_found 作为单独的值。两种失败类型不做区分。 | |
| 验证码可送达的渠道 | Email、SMS、WhatsApp 和 Telegram。语音标注为 | 其公布的渠道组合为 SMS、语音、RCS、WhatsApp、Telegram、Viber、Zalo 和静默网络认证,覆盖 230 多个国家和地区,渠道之间自动回退。 | |
| 投递事件 | 工作空间 Webhook 订阅您指定的验证事件类型,如 verify.verification.verified 和 verify.attempt.delivered,按 Standard Webhooks 规范签名。 | 在创建请求中为每次验证设置 callback_url,目标地址随每次调用一起传递。 | |
| 回退控制 | 国家的渠道计划设定顺序并自动执行,每次尝试的投递计时器在未收到投递状态时推进到下一个渠道。next-channel 调用也可按需推进单次验证。 | max_auto_fallbacks 和 force_challenge 在创建请求中调节升级策略。 | |
| 托管 MCP 服务器 | 托管服务器 mcp.bird.com 上的三个验证工具:发起验证、校验验证码、推进到下一个渠道。不包含配置功能。 | Prelude 发布了适用于 Node.js、Python、Go、Kotlin/Java、Ruby、PHP 和 C# 的后端 SDK,以及适用于 Web、Android、iOS、React Native 和 Flutter 的前端 SDK,因此其代理方案是由您自己的运行时调用的库。 | |
| 验证码长度 | 创建时的 options.code_length,否则使用工作区默认值。 | 创建时的 options.code_size。 |
相同的验证
发起一次验证。
两者的结构足够相似,迁移基本上就是重命名:target 变为 to,code_size 变为 code_length。在 Bird 中没有对应项的是 signals 对象、为其提供数据的 dispatch_id,以及响应中用于分支判断的 verdict。仅在 Bird 端出现的是 Idempotency-Key 请求头。
Prelude
const signupId = crypto.randomUUID();
const response = await fetch("https://api.prelude.dev/v2/verification", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PRELUDE_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
target: { type: "phone_number", value: "+15551234567" },
dispatch_id: signupId,
options: { code_size: 6 },
}),
});
const verification = await response.json();
console.log(verification.id, verification.status);
Bird
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const signupId = crypto.randomUUID();
const { data, error } = await bird.verify.verifications
.create(
{
to: { phone_number: "+15551234567" },
options: { code_length: 6 },
},
{ idempotencyKey: signupId },
)
.safe();
if (error) console.error(error.message);
else console.log(data.id, data.status);
迁移成本
较低,除非您使用了风控层。
两个 API 都以接收者而非验证 ID 为键,因此调用几乎可以原样迁移:target.value 变为 to.phone_number 或 to.email,code_size 变为 code_length,每次验证的 callback_url 变为订阅了您指定的 verify 事件类型的工作区 webhook。dispatch_id 无处可迁,因为它属于下面的风控层而非创建调用的机制,而且 Bird 的创建请求接受 Idempotency-Key 请求头,Prelude 的文档中没有记录此项。
风控层是完全无法直接迁移的部分。如果您依赖 Prelude 的 verdict 进行分支判断、在创建时发送 signals,或依赖 shadow block,Bird 端没有对应的功能来承载这些逻辑,决策必须在调用之前完成。请先评估这一差距,因为其他所有内容只需一个下午就能搞定。