开发者
API 参考文档
一个发送接口,一个查询状态接口,以及使用 HMAC 签名的 Webhook 回执。账户一经创建即签发密钥——无需审批,也无需联系任何人。
快速入门
新账户与消息送达之间只隔着三样东西:一个令牌、一些余额和一个密钥,全程无需人工介入。
- 创建账户——您的浏览器生成令牌,该令牌即是账户。
- 为其充值。最低 $40,可使用 付款页面 上列出的任意一种货币。
- 在控制台中创建 API 密钥。它只显示一次;我们只存储其哈希值,与令牌完全一样。
余额为空的密钥无法发送
密钥的创建被刻意设置为需先有已充值的账户。一个闲置未用的凭证只有风险、没有好处,因此控制台在有可花费余额之前不会生成密钥。
身份验证
每次请求都使用持有者令牌。密钥用于标识账户;没有第二因素验证,没有请求签名,也没有 IP 白名单——密钥就是全部凭证,请以此对待它。
Authorization: Bearer ws_live_9f2c…
| 传输方式 | 仅支持 HTTPS。通过明文 HTTP 发出的请求会被拒绝而非重定向——重定向本身就已经泄露密钥。 |
|---|---|
| 范围 | 一个密钥消耗一个账户的余额。为每个发送消息的系统创建单独的密钥,这样一旦泄露也只需撤销一个范围。 |
| 撤销 | 立即生效。被撤销的密钥在下一次请求时会返回 401;已被接受的进行中批次仍会完成。 |
| 恢复 | 没有。我们只保存哈希值。密钥丢失后只能更换,无法找回。 |
发送短信
POST/v1/messages
一次调用,一个或多个收件人,目的地可以混合。每个收件人按其所在目的地的费率计价,并按短信段计费。此次调用要么整体被接受,要么整体被拒绝;不会出现部分扣费的情况。
请求正文
| 字段 | 类型 | 备注 |
|---|---|---|
to | string[] | 必填。采用 E.164 格式,每次调用最多 5,000 个号码。无法匹配到已定价目的地的号码将在计费前被拒绝。 |
text | string | 必填。UTF-8 编码。短信段数按 GSM 03.38 计算——参见短信段说明。 |
from | string | 字母数字发送方名称,最多 11 个字符。在路由允许的情况下会被携带;参见 发送方名称。 |
vars | object[] | 可选的合并变量,每个收件人一个对象,在统计短信段数之前替换到 {{name}} 占位符中。 |
callback_url | string | 可选:按批次覆盖账户级 Webhook。 |
reference | string | 可选。会在每份回执中回传,以便您与自己的记录进行关联。 |
示例
# 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"
}'
{
"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 才是推荐方式。响应会汇总整批任务,并列出每个收件人的状态。
{
"batch_id": "b_7Kq2xR9wLm",
"status": "done",
"sending": 0,
"delivered": 1,
"undelivered": 1,
"refund_usd": 0.0216
}
refund_usd 仅在批次完成时结算一次。您看到时,它已经计入您的账户余额。
余额
GET/v1/balance
大批量发送前请先检查。账户余额在内部以整数微美元存储——价格精确到小数点后四位,浮点数不应出现在账目记录中——此处显示时四舍五入到小数点后六位。
{ "balance_usd": 412.905400, "currency": "USD" }
送达回执
每位收件人的回执会随运营商上报逐一生成。只有这四种状态;不存在一个悄悄意味着“我们弄丢了”的“未知”分类。
| 状态 | 含义 | 已计费 |
|---|---|---|
queued | 已接受,正在批次中排队等候。 | 是 |
sent | 已交付运营商,尚未收到确认。 | 是 |
delivered | 手机已确认收到。 | 是 |
undelivered | 号码失效、被封锁,或发送方名称被拒绝。 | 已退款 |
无法解析为已定价目的地的号码会在提交时被拒绝,根本不会进入这一生命周期——它们不是先计费再退款,而是从一开始就不计费。
Webhook
在控制台中设置端点,或通过 callback_url 按批次设置。我们会 POST JSON,并期望在 5 秒内收到 2xx。非 2xx 响应将以指数退避方式重试六次,历时约一小时,之后放弃。
负载
{
"event": "message.delivered",
"batch_id": "b_7Kq2xR9wLm",
"to": "+447700900123",
"destination": "gb",
"segments": 1,
"cost_usd": 0.0137,
"reference": "order-4471",
"ts": 1785312041
}
正在验证签名
每次投递都带有 X-WorldSMS-Signature 和 X-WorldSMS-Timestamp。签名采用 HMAC-SHA256(timestamp + "." + body) 算法,使用您的 webhook 密钥生成。请以恒定时间比较签名,并拒绝五分钟以上的时间戳,以防止被截获的投递日后被重放。
// $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 | 别名 | 该怎么做 |
|---|---|---|
| 400 | invalid_body | JSON 格式错误或缺少必填字段。 |
| 401 | key_rejected | 密钥缺失、已吊销或输入错误,不可重试。 |
| 402 | insufficient_credit | 该批次的费用超过了账户余额。未发送任何内容;请充值后重新提交。 |
| 422 | no_valid_recipients | 每个号码都无法解析为已定价的目的地。 |
| 422 | sender_id_invalid | from 长度超过 11 个字符,或包含会被识别为数字的纯数字字符串。 |
| 429 | rate_limited | 请退避。Retry-After 中包含需等待的秒数。 |
| 503 | route_unavailable | 该目的地暂时无法路由,可重试。 |
{
"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 个收件人的调用,在限额中只计为一次请求。
密钥即时发放,无需审批环节。
为账户充值,控制台会即时生成一个。