开发者

API 参考文档

一个发送接口,一个查询状态接口,以及使用 HMAC 签名的 Webhook 回执。账户一经创建即签发密钥——无需审批,也无需联系任何人。

v1https://api.worldsms.io/v1

快速入门

新账户与消息送达之间只隔着三样东西:一个令牌、一些余额和一个密钥,全程无需人工介入。

  1. 创建账户——您的浏览器生成令牌,该令牌即是账户。
  2. 为其充值。最低 $40,可使用 付款页面 上列出的任意一种货币。
  3. 在控制台中创建 API 密钥。它只显示一次;我们只存储其哈希值,与令牌完全一样。

余额为空的密钥无法发送

密钥的创建被刻意设置为需先有已充值的账户。一个闲置未用的凭证只有风险、没有好处,因此控制台在有可花费余额之前不会生成密钥。

身份验证

每次请求都使用持有者令牌。密钥用于标识账户;没有第二因素验证,没有请求签名,也没有 IP 白名单——密钥就是全部凭证,请以此对待它。

Authorization
Authorization: Bearer ws_live_9f2c…
传输方式仅支持 HTTPS。通过明文 HTTP 发出的请求会被拒绝而非重定向——重定向本身就已经泄露密钥。
范围一个密钥消耗一个账户的余额。为每个发送消息的系统创建单独的密钥,这样一旦泄露也只需撤销一个范围。
撤销立即生效。被撤销的密钥在下一次请求时会返回 401;已被接受的进行中批次仍会完成。
恢复没有。我们只保存哈希值。密钥丢失后只能更换,无法找回。

发送短信

POST/v1/messages

一次调用,一个或多个收件人,目的地可以混合。每个收件人按其所在目的地的费率计价,并按短信段计费。此次调用要么整体被接受,要么整体被拒绝;不会出现部分扣费的情况。

请求正文

字段类型备注
tostring[]必填。采用 E.164 格式,每次调用最多 5,000 个号码。无法匹配到已定价目的地的号码将在计费前被拒绝。
textstring必填。UTF-8 编码。短信段数按 GSM 03.38 计算——参见短信段说明
fromstring字母数字发送方名称,最多 11 个字符。在路由允许的情况下会被携带;参见 发送方名称
varsobject[]可选的合并变量,每个收件人一个对象,在统计短信段数之前替换到 {{name}} 占位符中。
callback_urlstring可选:按批次覆盖账户级 Webhook。
referencestring可选。会在每份回执中回传,以便您与自己的记录进行关联。

示例

send.sh
# one call, many recipients, mixed destinations
curl -X POST https://api.worldsms.io/v1/messages \
  -H "Authorization: Bearer $WORLDSMS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "ACME",
    "to":   ["+447700900123", "+33612345678"],
    "text": "Your code is 480913"
  }'
202 Accepted
{
  "batch_id": "b_7Kq2xR9wLm",
  "accepted": 2,
  "rejected": 0,
  "segments": 1,
  "cost_usd": 0.0353
}

发往英国 $0.0137,发往法国 $0.0216——价格表按目的地逐一计价,而非取平均值。

批处理

批量任务会立即被接受,并以每分钟 200 条消息的速度(按账户计算)发送,因此 50,000 个收件人需要 约 4 小时 10 分钟。时间敏感的消息不应排在营销群发之后:请为其单独使用一个密钥。

短信状态

GET/v1/messages/{batch_id}

支持轮询且有速率限制,但 Webhook 才是推荐方式。响应会汇总整批任务,并列出每个收件人的状态。

200 OK
{
  "batch_id":    "b_7Kq2xR9wLm",
  "status":      "done",
  "sending":     0,
  "delivered":   1,
  "undelivered": 1,
  "refund_usd":  0.0216
}

refund_usd 仅在批次完成时结算一次。您看到时,它已经计入您的账户余额。

余额

GET/v1/balance

大批量发送前请先检查。账户余额在内部以整数微美元存储——价格精确到小数点后四位,浮点数不应出现在账目记录中——此处显示时四舍五入到小数点后六位。

200 OK
{ "balance_usd": 412.905400, "currency": "USD" }

送达回执

每位收件人的回执会随运营商上报逐一生成。只有这四种状态;不存在一个悄悄意味着“我们弄丢了”的“未知”分类。

状态含义已计费
queued已接受,正在批次中排队等候。
sent已交付运营商,尚未收到确认。
delivered手机已确认收到。
undelivered号码失效、被封锁,或发送方名称被拒绝。已退款

无法解析为已定价目的地的号码会在提交时被拒绝,根本不会进入这一生命周期——它们不是先计费再退款,而是从一开始就不计费。

Webhook

在控制台中设置端点,或通过 callback_url 按批次设置。我们会 POST JSON,并期望在 5 秒内收到 2xx。非 2xx 响应将以指数退避方式重试六次,历时约一小时,之后放弃。

负载

向您的端点发送 POST 请求
{
  "event":     "message.delivered",
  "batch_id":  "b_7Kq2xR9wLm",
  "to":        "+447700900123",
  "destination": "gb",
  "segments":  1,
  "cost_usd":  0.0137,
  "reference": "order-4471",
  "ts":        1785312041
}

正在验证签名

每次投递都带有 X-WorldSMS-SignatureX-WorldSMS-Timestamp。签名采用 HMAC-SHA256(timestamp + "." + body) 算法,使用您的 webhook 密钥生成。请以恒定时间比较签名,并拒绝五分钟以上的时间戳,以防止被截获的投递日后被重放。

verify.php
// $secret is the webhook secret from the dashboard
$raw  = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_WORLDSMS_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_WORLDSMS_SIGNATURE'] ?? '';

// A stale timestamp is a replay, however well it is signed.
if (abs(time() - (int) $ts) > 300) { http_response_code(408); exit; }

$mine = hash_hmac('sha256', $ts . '.' . $raw, $secret);
if (!hash_equals($mine, $sig)) { http_response_code(401); exit; }

http_response_code(204);

保持幂等

当您的接口超时后触发的重试,看起来与首次投递完全相同。请以 batch_id + to + event 作为键,将重复项视为无操作。

错误

每次失败都会返回带有固定 error 标识符的 JSON 消息体。请匹配该标识符,切勿匹配文字说明——文字说明允许持续改进。

HTTP别名该怎么做
400invalid_bodyJSON 格式错误或缺少必填字段。
401key_rejected密钥缺失、已吊销或输入错误,不可重试。
402insufficient_credit该批次的费用超过了账户余额。未发送任何内容;请充值后重新提交。
422no_valid_recipients每个号码都无法解析为已定价的目的地。
422sender_id_invalidfrom 长度超过 11 个字符,或包含会被识别为数字的纯数字字符串。
429rate_limited请退避。Retry-After 中包含需等待的秒数。
503route_unavailable该目的地暂时无法路由,可重试。
402 Payment Required
{
  "error":       "insufficient_credit",
  "message":     "Batch costs $84.20, balance is $12.05.",
  "required_usd": 84.20,
  "balance_usd":  12.05
}

限制

请求每个密钥每分钟 60 次,允许 20 次突发。超出后返回 429,并附带 Retry-After
每次调用的收件人数5,000 条。更大的列表请分多次调用,或在控制台上传文件。
正文大小2 MB.
吞吐量每个账户每分钟 200 条短信,无论有多少个密钥提交。
密钥没有限制。每个发送系统对应一个是预期做法。

速率限制针对的是 API 调用,而非消息本身:一次携带 5,000 个收件人的调用,在限额中只计为一次请求。

密钥即时发放,无需审批环节。

为账户充值,控制台会即时生成一个。

提出具体问题

创建您的账户

只需一个按钮。您的浏览器会生成一个 160 位令牌,该令牌即为账户本身。无需填写其他信息,也无需任何等待。

简体中文ZH · 更改语言

语言