短信验证API
短信验证API就是三次调用:买号码、等验证码、释放号码。它覆盖225个国家的517个平台,号码€0.07起,什么都没收到的订单不用开工单就会退款。密钥有权限范围,购买是幂等的,老的handler_api客户端不用改就能跑。
一屏看完这套API
更新于2026年8月28日- 基础URL
- https://virtualsmsnumbers.com/api/v1
- 认证方式
- Bearer密钥,或X-Api-Key
- 限流
- 120次/分,突发20次/秒
- 幂等窗口
- 24小时
- 自动退款时限
- 20分钟
- 最便宜的一次接码
- €0.07
- 覆盖国家数
- 225
- 格式
- JSON,以分计价,ISO 8601 UTC
价格与库存来自运营商号码池的当前状态,而不是一份对外公布的价目表。
三次调用的流程
参考文档里的其他内容都是可选的。这就是完整的验证路径,从2019年至今没变过。
- 1
POST /activations
指定一个平台,如果你在意国家,再加上国家。响应里带着号码、以分为单位的价格和到期时间戳。带上Idempotency-Key,重试的请求就不会再买一个号码;如果调用方是自动化程序,再加上max_price_cents。
- 2
GET /activations/{id}?wait=180
长轮询。连接会一直挂着,直到短信落地或者超时,所以一个请求就顶掉了本来要发九十次的循环。状态返回为code_received,解析出的验证码和原始短信文本一起给出,因为不同发送方的格式并不一样。
- 3
POST /activations/{id}/complete
关闭订单,释放线路。如果什么都没来,那就什么都别做:窗口期会自己到期,余额会退回来。提前取消是同一个调用的另一个名字。
一个能跑的示例
设好VSN_KEY就能运行。注释里的响应是真实结构,包括那些你会想存下来的字段。
# 1. Buy a Telegram number in Portugal
-kw">curl -X POST https://virtualsmsnumbers.com/api/v1/activations \
-H "Authorization: Bearer $VSN_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"service":"telegram","country":"PT"}'
# {"id":"1043872915","phone_number":"351926114508","status":"waiting",
# "price_cents":11,"expires_at":"2026-08-26T12:41:07Z"}
# 2. Long-poll until the code lands (blocks up to 120 s)
-kw">curl "https://virtualsmsnumbers.com/api/v1/activations/1043872915?wait=120" \
-H "Authorization: Bearer $VSN_KEY"
# {"id":"1043872915","status":"code_received",
# "messages":[{"code":"48219","text":"Telegram code: 48219"}]}
# 3. Release the number
-kw">curl -X POST https://virtualsmsnumbers.com/api/v1/activations/1043872915/complete \
-H "Authorization: Bearer $VSN_KEY"限流
每把密钥每分钟120个请求,突发到每秒20个。每个响应都带X-RateLimit-Limit、X-RateLimit-Remaining和X-RateLimit-Reset,429会告诉你要等多久,而不是让你猜。
只要按设计意图使用,限流很少成为瓶颈:一次长轮询代替九十次轮询,用Webhook代替定时器,国家和平台列表在启动时缓存好。如果你确实需要更多余量,直接说一声,把限额调高对我们双方都比调试一堆密钥容易。
幂等
在POST /activations上发送Idempotency-Key请求头。24小时内重放同一个键,返回的是最初那笔订单的当前状态,并带上Idempotent-Replay响应头,而不是再买一个号码、再扣你一次钱。
这个键不是请求体的哈希:用已经用过的键发送不同的载荷,返回的仍然是第一笔订单。按一次逻辑购买生成一个键——用UUID就行——重试时复用它,但绝不要跨购买复用。
老的handler_api客户端
按经典handler_api.php协议写的脚本可以继续用。把它们指向兼容端点,换掉api_key,同样的动作仍然返回和以前一样的ACCESS_和STATUS_令牌。
它是同一个号码池之上的一层转换,所以两边的价格、库存和退款行为完全一致。新代码还是应该用/api/v1:JSON响应里带着时间戳、错误码和价格字段,令牌格式装不下这些。
# Existing scripts keep working: same actions, same response tokens.
BASE="https://virtualsmsnumbers.com/stubs/handler_api.php"
-kw">curl "$BASE?api_key=$KEY&action=getNumber&service=tg&country=117"
# ACCESS_NUMBER:1043872915:351926114508
-kw">curl "$BASE?api_key=$KEY&action=getStatus&id=1043872915"
# STATUS_WAIT_CODE
# STATUS_OK:48219
-kw">curl "$BASE?api_key=$KEY&action=setStatus&id=1043872915&status=6"
# ACCESS_ACTIVATION
-kw">curl "$BASE?api_key=$KEY&action=getBalance"
# ACCESS_BALANCE:41.87代理、MCP与发现
我们提供托管的MCP服务器、一份OpenAPI 3.1文档和一份llms.txt索引,代理不用手写胶水代码就能发现它需要的那三个工具。把你的客户端指向下面这个端点,它会找到购买、等待和释放。
在让任何自主程序动用余额之前:把密钥的权限范围限定为numbers:read和numbers:write,每次购买都设一个max_price_cents上限,并且给它单独一把密钥,这样吊销它不会连带弄停你的生产集成。
{
"mcpServers": {
"virtualsmsnumbers": {
"type": "http",
"url": "https://virtualsmsnumbers.com/api/mcp",
"headers": { "Authorization": "Bearer vsn_live_xxxxxxxxxxxx" }
}
}
}上生产之前
- 每次购买都设max_price_cents。价格跟着号码池走,没有上限的代理会兴高采烈地买下最贵的那一头。
- 把各种ID当成不透明字符串。订单ID今天恰好是十位数字;这不是承诺,它的长度也不是。
- 按错误码分支,永远不要按错误消息分支。错误码在一个版本内是稳定的;消息是写给人看的,会被改写。
- 订阅sms.received并校验签名——对原始请求体做HMAC-SHA256,重放窗口五分钟——而不是去轮询一个本可以直接通知你的状态。
- 用以分为单位的整数字段做运算。旁边那些格式化过的字符串是用来显示的,而且随地区设置而变。
常见问题
从平台发出算起,送达中位数不到九秒。长轮询之所以存在,是因为长尾很长:订单会保持打开20分钟,什么都没到就过期并退款。
没有你需要处理的东西。窗口期关闭,余额自动退回,订单以过期状态结束,这个状态可以从API读到。
需要,而且不花钱。密钥的权限范围是固定的,还可以有IP允许列表和创建时选定的有效期,所以测试环境的密钥即使泄露,也买不了生产环境的号码。
有很薄、无依赖的封装,但这套API就是六个基于JSON的端点——fetch、requests或者curl,跑完这三次调用真的够用。
在同一笔订单里可以:只要它还开着,后续短信都会到同一个号码。跨会话就需要租用号码,它能把线路从四小时一直持有到十二个月。
不会。同一个号码池,同样的价格;不同的只有响应的编码方式。