cleat.

面向开发者和 QA

用真实的美国号码接收短信,直接送进你的代码。

一条真实的美国手机线路,不是 VoIP,把每条收到的短信交给你的代码。短信一存储,签名 Webhook 立即触发。REST API 负责列出和轮询。团队里的其他人照样能用实时收件箱、邮件和 Telegram。一条线路,每月 US$24.99,随时取消。

为什么不用电信平台的号码?

电信平台的可编程号码,按分类通常属于 VoIP。Twilio 自己有一篇讲发送验证码前过滤 VoIP 的文章,文中它的 Lookup 把一个 Twilio 号码标记为 nonFixedVoipTwilio)。如果某个服务过滤 VoIP,它的验证码就永远到不了平台号码。Cleat 线路是手机线路,选它的理由就在这里。进一步了解号码类型

快速开始

  1. 获取线路。注册并订阅。读取短信之前先验证身份,验证完成前 API 一律返回 403
  2. 在 Settings(设置)中创建 API 密钥。密钥以 clt_ 开头,只显示一次。如果你更想自动生成客户端,完整接口定义以 OpenAPI 格式提供
  3. 在 Settings 中添加 Webhook 端点(如果你需要推送):填一个公开的 HTTPS URL。端点的签名密钥以 whsec_ 开头,只显示一次。
  4. 列出你的线路,然后轮询短信或等待 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 十六进制值。先用原始字节校验签名,再解析。拒绝过旧的时间戳,防止重放攻击。

校验并处理一次投递(Node.js、Express)
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/linesAPI 密钥所属工作区中的线路,从新到旧:idphonelabelstatusactivegracereleased)和 createdAt
GET /api/v1/lines/{lineId}/messages某条线路上的短信。after(ISO 8601)返回该时刻之后收到的短信,从旧到新,用于轮询。before 向前翻页,从新到旧。limit 取值 1 到 200,默认 50。
基础 URL 为 https://cleat.so。认证方式: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 和 APIAPI 和 Webhook签名 Webhook 和 REST API,外加 Telegram、邮件和收件箱
价格按号码收费,另按消息收费页面上未显示每月 US$24.99,含接收短信
其他公司的信息均来自其官方页面,2026 年 9 月核实。

要和不写代码的同事共享验证码?请看团队共享 2FA。为什么 Google Voice 和其他网络号码会收不到验证码:Google Voice 与验证码。我们如何处理身份验证:信任与安全。完整计费规则:价格

继续阅读

短信转发到 Telegram

常见问题

有免费套餐或沙盒吗?

没有。一条线路每月 US$24.99,随时取消;线路持有人完成身份验证之前,线路上的短信都处于锁定状态。

可以通过 API 发送短信吗?

不可以。Cleat Line 只接收,从不发送。

如果服务打电话念验证码,而不是发短信呢?

来电会被转成文字,作为普通消息送到你的 Webhook 和 API:验证码已提取,来电号码在 from 中。没有字段标明它是来电。

有速率限制吗?

有:每个 API 密钥每分钟 120 次请求。Webhook 投递不计入。

Webhook 多快触发?

Cleat 存储短信后立即推送到你的端点,与实时收件箱、邮件和 Telegram 同步进行。我们没有公布实测延迟,所以不给出具体数字。

可以有多个号码吗?

你可以在工作区中添加线路,每条线路都是单独的 US$24.99 订阅。Cleat 不是为号码池设计的。

你们会保存我的消息吗?

短信会一直保存,直到你删除工作区或账户。详情见隐私政策

资料来源

其他公司的信息来自其官方页面,核实于 2026年9月。

  1. Twilio, filtering VoIP numbers before sending codes https://www.twilio.com/en-us/blog/filter-voip-before-otp-verification
  2. MailSlurp, phone numbers https://www.mailslurp.com/product/phone-number-sms-service/

获取一条线路和 API 密钥。

每月 US$24.99,随时取消。

  • 每位持有人都已验证身份
  • 短信仅你的团队可见
  • 随时取消