• 覆盖 228 个目的地
  • 始终无需 KYC
  • 支持 Bitcoin、Monero、USDT 等 7 种币种

SMS API

一次 HTTP 调用即可发送消息。
一次 Webhook 即可确认送达。

这套 REST API 支持 Bearer 密钥、结构稳定的 JSON、幂等重试和送达 Webhook。它与控制面板共用余额和费率,无需议价,也无需审批。

  • 每个密钥每秒 50 次请求
  • 每次 API 请求最多 1,000 条消息
  • 幂等键、IP 允许名单

01接口范围

六个端点覆盖完整产品。

控制面板能做的事,API 都能做;两者不存在独占功能。

方法端点功能
POST/v1/messages发送一条消息,返回 id、价格和初始状态。
POST/v1/messages/batch一次请求最多发送 1,000 条消息,每条都可使用不同文本和发送方。
GET/v1/messages/{id}查询一条消息的当前状态、运营商代码、时间戳和价格。
GET/v1/messages列出并筛选消息:状态、目的地、群发任务和日期范围。结果分页返回。
GET/v1/rates以 JSON 返回完整费率表,或通过 /v1/rates/{iso} 查询单个国家/地区。
GET/v1/balance返回 USD 余额、待确认充值和您设置的低余额阈值。

02消息生命周期

六种状态,每种含义都很明确。

消息状态只会向前推进。无论轮询还是监听 Webhook,都可以依赖以下顺序。

  • Webhook 会推送每次状态变化;如有运营商代码,也会一并提供。
  • 有效期为 48 小时。超过有效期仍未送达的消息会变为 expired。
  • 计费发生在状态变为 sent 时。rejected 消息绝不收费。
  1. 排队中已接受并计价,正在等待路由名额。
  2. 已发送已交给运营商,此时计费。
  3. 已送达手机已确认接收。最终状态。
  4. 失败运营商拒绝发送或无法联系手机,并附错误代码。最终状态。
  5. 已过期未能在有效期内送达。最终状态。
  6. 已拒绝发送前被拒绝:号码无效、内容被拦截或余额为空。不计费。最终状态。

03错误

稳定的代码、易读说明,以及导致错误的字段。

所有非 2xx 响应都使用同一 JSON 结构。遇到 429 和 5xx 时重试;遇到 4xx 时修正后重新发送。

HTTP代码含义处理方法
400invalid_number目的地不是有效的 E.164 号码。将号码规范化;响应会指出对应字段。
401unauthorized密钥缺失、已撤销或受 IP 限制。在控制面板中检查密钥和允许名单。
402insufficient_balance发送该消息会使余额低于零。请充值。设置低余额 Webhook 可避免此问题。
409idempotency_conflict同一密钥被用于不同的请求负载。发送新消息时使用新密钥。
422unsupported_destination没有前往该国家/地区或号段的路由。在覆盖范围页面查询该目的地。
422sender_not_allowed此路由不允许字母数字发送方。省略 from;系统会自动分配数字发送方。
429rate_limited超过 每个密钥每秒 50 次请求。等待 Retry-After 指定的时间,或使用批量端点。
5xxinternal平台端错误,消息未发送。使用相同的 Idempotency-Key 重试。

04示例

复制、粘贴并替换密钥。

以下是同一请求在常用语言中的写法。每个示例都包含幂等键,因为网络第一次闪断时,您就会用到它。

POST /v1/messages/batch
import requests

r = requests.post(
    "https://api.smsmeteor.com/v1/messages/batch",
    headers={"Authorization": f"Bearer {KEY}",
             "Idempotency-Key": "batch-2026-09-21-01"},
    json={"messages": [
        {"to": "+14155550142", "from": "METEOR", "text": "订单 #4821 已发货。"},
        {"to": "+447700900123", "from": "METEOR", "text": "订单 #4822 已发货。"},
    ]},
)
for m in r.json()["messages"]:
    print(m["id"], m["status"], m["price"])
const r = await fetch("https://api.smsmeteor.com/v1/messages/batch", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SMSMETEOR_KEY}`,
    "Idempotency-Key": "batch-2026-09-21-01",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ messages: [
    { to: "+14155550142", from: "METEOR", text: "订单 #4821 已发货。" },
    { to: "+447700900123", from: "METEOR", text: "订单 #4822 已发货。" },
  ]}),
});
const { messages } = await r.json();
$ch = curl_init("https://api.smsmeteor.com/v1/messages/batch");
curl_setopt_array($ch, [
  CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer $key",
    "Idempotency-Key: batch-2026-09-21-01", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => json_encode(["messages" => [
    ["to" => "+14155550142", "from" => "METEOR", "text" => "订单 #4821 已发货。"],
    ["to" => "+447700900123", "from" => "METEOR", "text" => "订单 #4822 已发货。"],
  ]]),
]);
$res = json_decode(curl_exec($ch), true);
body, _ := json.Marshal(map[string]any{"messages": []map[string]string{
    {"to": "+14155550142", "from": "METEOR", "text": "订单 #4821 已发货。"},
    {"to": "+447700900123", "from": "METEOR", "text": "订单 #4822 已发货。"},
}})
req, _ := http.NewRequest("POST", "https://api.smsmeteor.com/v1/messages/batch", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("SMSMETEOR_KEY"))
req.Header.Set("Idempotency-Key", "batch-2026-09-21-01")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
201 Created
{ "batch_id": "bat_3Hq9Zr", "accepted": 2, "rejected": 0,
  "total_price": "0.0214", "currency": "USD",
  "messages": [ { "id": "msg_9Kd2fQ", "status": "queued", "price": "0.0084" },
                { "id": "msg_9Kd2fR", "status": "queued", "price": "0.0130" } ] }

05常见问题解答

开发者在首次请求前常问的问题。

如何获取 API 密钥?

在控制面板的“开发者”页面创建。密钥是仅显示一次的 Bearer 令牌,可授予发送、读取或两者兼有的权限,也可限制为仅允许指定 IP。您随时可以撤销或轮换密钥,余额不会受到影响。

API 与控制面板使用相同的余额和费率吗?

是。同一个账户、同一份余额、同一张费率表。通过代码发送消息的费用与费率表中该目的地显示的完全一致,也会出现在同一套报告中。

速率限制是多少?

单条发送接口的限制为 每个密钥每秒 50 次请求。批量接口每次最多接受 每次 API 请求最多 1,000 条消息,因此发送一百万条消息只需一千次请求。超过限制时,您会收到 429 响应和 Retry-After 标头。

幂等键有什么作用?

重试请求时使用相同的 Idempotency-Key,API 会返回原消息,而不会再次发送。每个账户的密钥会保留 24 小时。

如何知道消息是否已送达?

轮询 GET /v1/messages/{id},或注册 Webhook,接收带运营商代码的 message.delivered 和 message.failed 事件。只要发送量不止几条,就建议使用 Webhook。

有沙盒环境吗?

每个账户都有测试密钥。使用它发送的消息会经过验证和计价,并以 test 状态返回,但不会离开平台,也不会产生任何费用。

支持哪些编程语言?

任何能发起 HTTPS 请求的语言都可以。我们提供可直接粘贴使用的 cURL、Python、Node、PHP 和 Go 示例;如果您希望生成客户端,也可使用 OpenAPI 描述文件。

在哪里查看错误说明?

每个错误均为 JSON,包含稳定的错误代码、易读说明,以及相关时导致错误的字段。完整列表位于 API 参考文档,本页也列出了最常见的错误。