面向开发者和 QA
用真实的美国号码接收短信,直接送进你的代码。
一条真实的美国手机线路,不是 VoIP,把每条收到的短信交给你的代码。短信一存储,签名 Webhook 立即触发。REST API 负责列出和轮询。团队里的其他人照样能用实时收件箱、邮件和 Telegram。一条线路,每月 US$24.99,随时取消。
为什么不用电信平台的号码?
电信平台的可编程号码,按分类通常属于 VoIP。Twilio 自己有一篇讲发送验证码前过滤 VoIP 的文章,文中它的 Lookup 把一个 Twilio 号码标记为 nonFixedVoip(Twilio)。如果某个服务过滤 VoIP,它的验证码就永远到不了平台号码。Cleat 线路是手机线路,选它的理由就在这里。进一步了解号码类型。
快速开始
- 获取线路。注册并订阅。读取短信之前先验证身份,验证完成前 API 一律返回
403。 - 在 Settings(设置)中创建 API 密钥。密钥以
clt_开头,只显示一次。如果你更想自动生成客户端,完整接口定义以 OpenAPI 格式提供。 - 在 Settings 中添加 Webhook 端点(如果你需要推送):填一个公开的 HTTPS URL。端点的签名密钥以
whsec_开头,只显示一次。 - 列出你的线路,然后轮询短信或等待 Webhook。
curl https://cleat.so/api/v1/lines \
-H "Authorization: Bearer $CLEAT_API_KEY"{
"data": [
{
"id": "8f14e45f-ceea-4b6b-9d3c-2a1f0e7c5b10",
"phone": "13055550100",
"label": "Staging sign-ups",
"status": "active",
"createdAt": "2026-09-11T10:00:00.000Z"
}
]
}curl "https://cleat.so/api/v1/lines/$LINE_ID/messages?after=2026-09-11T10:00:00Z&limit=50" \
-H "Authorization: Bearer $CLEAT_API_KEY"{
"data": [
{
"id": "c9a7e0d2-5b1f-4e8a-9f3c-6d2b1a0e4f77",
"line": { "id": "8f14e45f-ceea-4b6b-9d3c-2a1f0e7c5b10", "phone": "13055550100", "label": "Staging sign-ups" },
"from": "55512",
"body": "Your verification code is 704 118",
"code": "704118",
"receivedAt": "2026-09-11T10:02:41.000Z"
}
]
}Webhook
短信到达时,Cleat 会向你的每个端点发送 POST 请求,带上下面的 JSON 请求体、cleat-signature 请求头,User-Agent 为 Cleat-Webhooks/1.0:
{
"type": "message.received",
"data": {
"id": "c9a7e0d2-5b1f-4e8a-9f3c-6d2b1a0e4f77",
"line": { "id": "8f14e45f-ceea-4b6b-9d3c-2a1f0e7c5b10", "phone": "13055550100", "label": "Staging sign-ups" },
"from": "55512",
"body": "Your verification code is 704 118",
"code": "704118",
"receivedAt": "2026-09-11T10:02:41.000Z"
}
}签名请求头形如 t=1789120961,v1=5d41…。v1 是以端点签名密钥为密钥,对“时间戳 + 一个点 + 原始请求体”计算出的 HMAC-SHA256 十六进制值。先用原始字节校验签名,再解析。拒绝过旧的时间戳,防止重放攻击。
import crypto from "node:crypto";
import express from "express";
const app = express();
const secret = process.env.CLEAT_WEBHOOK_SECRET; // whsec_…
// cleat-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body">
function verified(header, body) {
const parts = Object.fromEntries(String(header).split(",").map((part) => part.split("=")));
const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${body}`).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return fresh && parts.v1?.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}
app.post("/cleat-webhook", express.raw({ type: "application/json" }), (req, res) => {
const body = req.body.toString("utf8");
if (!verified(req.get("cleat-signature"), body)) return res.sendStatus(401);
const { type, data } = JSON.parse(body);
if (type === "message.received") {
// data.code is Cleat's best guess at a one-time code; data.body is the full text.
console.log(data.line.phone, data.from, data.code ?? data.body);
}
res.sendStatus(200);
});
app.listen(3000);投递细节
- 端点必须是公开的
https://URL。Cleat 不跟随重定向。 - 请在 10 秒内返回任意 2xx 状态码。
- 每条短信只推送一次。如果你的端点当时宕机,可以用 API 的
?after=加上你最后处理的那条短信的receivedAt补齐。短信的id永不改变,可以用它去重。 - 每个工作区最多五个端点。Settings 页面会显示每个端点最近一次的状态,以及已经连续失败了多少次投递。
code是 Cleat 识别出的最可能的一次性验证码,也可能是null。完整的body始终都在。- 自动语音来电里念出的验证码也以同样方式送达。来电会被转成文字,作为
message.received投递:转写文字在body中,来电号码在from中,code也会填好。载荷里没有任何字段能区分这是来电还是短信。
API 参考
| 端点 | 返回内容 |
|---|---|
GET /api/v1/lines | API 密钥所属工作区中的线路,从新到旧:id、phone、label、status(active、grace 或 released)和 createdAt。 |
GET /api/v1/lines/{lineId}/messages | 某条线路上的短信。after(ISO 8601)返回该时刻之后收到的短信,从旧到新,用于轮询。before 向前翻页,从新到旧。limit 取值 1 到 200,默认 50。 |
Authorization: Bearer clt_…。错误码:400 表示时间戳格式错误,401 表示密钥缺失或已撤销,402 表示线路处于暂停状态,403 表示工作区所有者尚未验证身份,404 表示线路不在该密钥的工作区内,429 表示超出速率限制。限制与权限
每个 API 密钥每分钟 120 次请求;超出后 API 返回 429。只有工作区所有者可以创建 API 密钥和 Webhook 端点,密钥一经撤销立即失效。
适合的用途
- 你们公司自己的账户,例如云控制台、域名注册商和支付服务商,验证码推送到值班工程师盯着的频道。
- 在预发布环境中对你们自己的注册和登录流程做 QA,用的号码表现得和客户的手机一样。
- 需要登记美国手机号码的个人项目。
不适合的用途
- 发送短信。Cleat Line 只能接收。
- 压力测试或号码池。每条线路都是独立订阅,各有一位已验证身份的持有人。Cleat 不是为号码池设计的。
- 不属于你或你公司的账户。
- 任何需要实时语音的场景。线路不能拨出。没有来电铃声可接,没有音频流,也没有录音可下载。通话结束后,你会收到这通电话的转写文字。
对比
| 电信平台号码 | MailSlurp 电话号码 | Cleat Line | |
|---|---|---|---|
| 号码类型 | 按分类通常属于 VoIP;Twilio 的 Lookup 把一个 Twilio 号码标记为 nonFixedVoip | “dedicated, non-VoIP mobile numbers”(专用的非 VoIP 手机号码,MailSlurp) | 真实的美国手机线路,不是 VoIP |
| 面向 | 大规模收发 | QA 和开发测试 | 你自己的账户、QA 和小团队 |
| 持有人验证 | 企业 KYC 和 10DLC 注册 | 未说明 | 政府签发的证件和自拍,或仅证件验证(人工审核) |
| 把短信接入代码 | Webhook 和 API | API 和 Webhook | 签名 Webhook 和 REST API,外加 Telegram、邮件和收件箱 |
| 价格 | 按号码收费,另按消息收费 | 页面上未显示 | 每月 US$24.99,含接收短信 |
要和不写代码的同事共享验证码?请看团队共享 2FA。为什么 Google Voice 和其他网络号码会收不到验证码:Google Voice 与验证码。我们如何处理身份验证:信任与安全。完整计费规则:价格。
继续阅读
常见问题
有免费套餐或沙盒吗?
没有。一条线路每月 US$24.99,随时取消;线路持有人完成身份验证之前,线路上的短信都处于锁定状态。
可以通过 API 发送短信吗?
不可以。Cleat Line 只接收,从不发送。
如果服务打电话念验证码,而不是发短信呢?
来电会被转成文字,作为普通消息送到你的 Webhook 和 API:验证码已提取,来电号码在 from 中。没有字段标明它是来电。
有速率限制吗?
有:每个 API 密钥每分钟 120 次请求。Webhook 投递不计入。
Webhook 多快触发?
Cleat 存储短信后立即推送到你的端点,与实时收件箱、邮件和 Telegram 同步进行。我们没有公布实测延迟,所以不给出具体数字。
可以有多个号码吗?
你可以在工作区中添加线路,每条线路都是单独的 US$24.99 订阅。Cleat 不是为号码池设计的。
你们会保存我的消息吗?
短信会一直保存,直到你删除工作区或账户。详情见隐私政策。
资料来源
其他公司的信息来自其官方页面,核实于 2026年9月。
- Twilio, filtering VoIP numbers before sending codes https://www.twilio.com/en-us/blog/filter-voip-before-otp-verification
- MailSlurp, phone numbers https://www.mailslurp.com/product/phone-number-sms-service/