发送
通过 POST /v1/batches 发送群发短信
/v1/batches单次请求最多发送至 10,000 个号码,费用将从余额中一次性扣除。
请求体
- toarray of strings可选
共享短信内容的号码列表。可选用 to 搭配 text,或直接使用 messages 参数。
- textstring可选
共享短信内容(与 to 参数必须搭配使用)。
- messagesarray of objects可选
为每个收件人提供 {to, text} 键值对,用于定制短信。
- namestring可选
控制台显示的标签,最多 100 个字符。
- referencestring可选
自定义 ID(最多 100 字符),将随批次及每条短信返回。
- send_atstring可选
ISO 8601 时间格式,可设置 2 分钟后至 45 天内的发送时间。
curl https://bulksmsapi.cc/v1/batches \
-H "Authorization: Bearer $BULKSMSAPI_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: spring-sale-0412" \
-d '{
"name": "Spring sale",
"text": "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
"to": [
"+14155550123",
"+447400123456",
"+4915123456789"
]
}'const res = await fetch("https://bulksmsapi.cc/v1/batches", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BULKSMSAPI_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "spring-sale-0412",
},
body: JSON.stringify({
name: "Spring sale",
text: "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
to: ["+14155550123", "+447400123456", "+4915123456789"],
}),
});
const batch = await res.json();
console.log(res.status, batch.id, batch.recipients, batch.cost);import json, os, urllib.request
req = urllib.request.Request(
"https://bulksmsapi.cc/v1/batches",
data=json.dumps({
"name": "Spring sale",
"text": "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
"to": ["+14155550123", "+447400123456", "+4915123456789"],
}).encode(),
headers={
"Authorization": "Bearer " + os.environ["BULKSMSAPI_KEY"],
"Content-Type": "application/json",
"Idempotency-Key": "spring-sale-0412",
"User-Agent": "northwind-app/1.0",
},
method="POST",
)
with urllib.request.urlopen(req) as res:
batch = json.load(res)
print(res.status, batch["id"], batch["recipients"], batch["cost"])<?php
$ch = curl_init("https://bulksmsapi.cc/v1/batches");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("BULKSMSAPI_KEY"),
"Content-Type: application/json",
"Idempotency-Key: spring-sale-0412",
],
CURLOPT_POSTFIELDS => json_encode([
"name" => "Spring sale",
"text" => "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
"to" => ["+14155550123", "+447400123456", "+4915123456789"],
]),
]);
$batch = json_decode(curl_exec($ch), true);
echo $batch["id"], " ", $batch["recipients"], " ", $batch["cost"], "\n";package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]any{
"name": "Spring sale",
"text": "Spring sale at Northwind: 20% off until Sunday. Opt out: northwind.example/sms",
"to": []string{"+14155550123", "+447400123456", "+4915123456789"},
})
req, _ := http.NewRequest("POST", "https://bulksmsapi.cc/v1/batches", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("BULKSMSAPI_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", "spring-sale-0412")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var batch map[string]any
json.NewDecoder(res.Body).Decode(&batch)
fmt.Println(res.StatusCode, batch["id"], batch["recipients"], batch["cost"])
}{
"id": "bat_6TQ2W8M1ZK4N",
"object": "batch",
"name": "Spring sale",
"status": "queued",
"source": "api",
"encoding": "GSM-7",
"recipients": 3,
"max_segments": 1,
"cost": "0.02741",
"refunded": "0.00000",
"currency": "USD",
"counts": { "scheduled": 0, "queued": 3, "sent": 0, "delivered": 0, "failed": 0, "canceled": 0 },
"send_at": null,
"reference": null,
"created_at": "2026-11-07T09:31:40.102Z",
"completed_at": null,
"set_aside": []
}被过滤的号码
每个号码会独立进行格式校验与计费。无法发送的号码会被排除在批次外(不扣费),并在 set_aside 中列出原因:
| reason | 含义 |
|---|---|
| invalid_number | 清理后不符合 + 号开头加 7-15 位数字的格式。 |
| duplicate | 该号码在本次请求中重复出现。 |
| unsupported_country | 该号码所属国家/地区未开通计费服务。 |
| too_long | 定制短信内容超过 10 个分段。 |
| empty_text | 定制短信内容为空。 |
| suppressed | 该号码在您的拒发名单中。 |
若所有号码均被过滤,请求将失败并返回首个错误代码(如 invalid_number),且不产生任何费用。
为每个号码定制短信
使用 messages 为每个收件人定制内容(如姓名、时间、金额)。每条短信独立计费,因此同一批次可混合单分段与双分段短信。
curl https://bulksmsapi.cc/v1/batches \
-H "Authorization: Bearer $BULKSMSAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Appointment reminders, 14 May",
"send_at": "2026-05-13T16:00:00Z",
"messages": [
{ "to": "+14155550123", "text": "Hi Ana, your dental check-up is tomorrow at 09:30." },
{ "to": "+14155550178", "text": "Hi Sam, your dental check-up is tomorrow at 11:00." }
]
}'Scheduling
通过 send_at 设置的批次将保持 scheduled 状态,并在指定时间进入发送队列。费用在请求受理时扣除,因此定时批次始终预留资金。在开始发送前可随时取消。
/v1/batches/{id}/cancel取消定时批次:所有短信状态变更为 canceled,全额费用将以退款形式返还余额。已开始发送的批次将返回 409 not_cancelable 错误。
curl -X POST https://bulksmsapi.cc/v1/batches/bat_6TQ2W8M1ZK4N/cancel \
-H "Authorization: Bearer $BULKSMSAPI_KEY"获取批次列表
/v1/batches/{id}包含实时状态计数的批次。轮询它以获取进度,或使用 webhooks。
/v1/batches账户的批次,按最新顺序排列,带有 limit(1 到 100)和 starting_after(一个 bat_ id)。
批次字段
- idstring
bat_ 后跟 12 个字符。
- statusstring
scheduled(已计划)、queued(排队中)、sending(发送中)、completed(已完成)或 canceled(已取消)。
- sourcestring
api 或 console。
- encodingstring
GSM-7,或当任何文本需要 Unicode 时使用 UCS-2。
- recipientsinteger
被批次接受的号码。
- max_segmentsinteger
文本中最大的分段计数。
- coststring
从余额中扣除的总金额,美元。
- refundedstring
到目前为止因失败或取消的消息而返回的总金额。
- countsobject
每种状态的消息数:scheduled(已计划)、queued(排队中)、sent(已发送)、delivered(已送达)、failed(失败)、canceled(已取消)。
- send_atstring or null
计划时间(如果有)。
- completed_atstring or null
当最后一条消息达到最终状态时。
大型列表
将超过 10,000 个号码的列表拆分为多个请求,每个请求都有自己的 Idempotency-Key(例如列表 ID 和部分编号)。消息按顺序以每分钟最多 1,200 条的速度交付给网络,因此一个包含 50,000 个号码的群发活动将在不到一小时内完成。控制台从粘贴或 CSV 文件中为每个活动获取 50,000 个号码。