Bắt đầu nhanh
- Tạo tài khoản và nạp tiền vào số dư trong bảng điều khiển.
- Mở Khóa API và tạo một khóa. Khóa có thể được tạo sau khi lần nạp tiền đầu tiên được ghi có. Khóa chỉ hiển thị một lần; hãy lưu trữ nó như một bí mật.
- Gửi yêu cầu POST đến
/smsvới số điện thoại và văn bản. Đọc ID chiến dịch được trả về, sau đó theo dõi việc giao hàng trong bảng điều khiển hoặc qua webhook.
Xác thực
Mọi yêu cầu trừ danh sách giá công khai đều mang khóa của bạn trong tiêu đề Authorization. Khóa bắt đầu bằng sbk_live_. Một khóa mới thay thế khóa cũ ngay lập tức.
Authorization: Bearer sbk_live_YOUR_KEYGửi SMS
POST/sms
Tạo một chiến dịch, tính phí từ số dư và xếp hàng mọi tin nhắn. Số điện thoại được làm sạch và loại bỏ trùng lặp; những số không thể sử dụng được trả về trong dropped với lý do và không bị tính phí.
| Trường | Loại | Mô tả |
|---|---|---|
tobắt buộc | chuỗi hoặc mảng | Một số hoặc một mảng tối đa 10,000 số ở định dạng quốc tế, ví dụ "+447700900461" |
textbắt buộc | chuỗi | Văn bản tin nhắn, tối đa 10 phân đoạn. Văn bản GSM-7 phù hợp 160 ký tự mỗi phân đoạn, UCS-2 phù hợp 70 |
schedule_attùy chọn | chuỗi | Thời gian ISO 8601 từ 5 phút đến 60 ngày sau. Bỏ qua để gửi ngay |
client_reftùy chọn | chuỗi | Tham chiếu riêng của bạn, tối đa 64 ký tự a-z A-Z 0-9 _ . : -, được trả về trong báo cáo và webhook |
opt_outtùy chọn | boolean | true thêm dòng từ chối nhận đặt trong cài đặt tài khoản của bạn |
curl -X POST https://sendbulksms.cc/api/v1/sms \
-H "Authorization: Bearer sbk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": ["+447700900461", "+5511955550123"],
"text": "Hi, your order 4821 ships today.",
"client_ref": "orders-4821"
}'const res = await fetch("https://sendbulksms.cc/api/v1/sms", {
method: "POST",
headers: { Authorization: "Bearer " + process.env.SENDBULKSMS_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ to: ["+447700900461", "+5511955550123"], text: "Hi, your order 4821 ships today.", client_ref: "orders-4821" }),
});
const campaign = await res.json();
console.log(res.status, campaign.id, campaign.cost);import os, requests
r = requests.post(
"https://sendbulksms.cc/api/v1/sms",
headers={"Authorization": "Bearer " + os.environ["SENDBULKSMS_KEY"]},
json={"to": ["+447700900461", "+5511955550123"], "text": "Hi, your order 4821 ships today.", "client_ref": "orders-4821"},
timeout=30,
)
print(r.status_code, r.json()["id"])<?php
$ch = curl_init("https://sendbulksms.cc/api/v1/sms");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("SENDBULKSMS_KEY"), "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["to" => ["+447700900461", "+5511955550123"], "text" => "Hi, your order 4821 ships today.", "client_ref" => "orders-4821"]),
]);
$campaign = json_decode(curl_exec($ch), true);
echo $campaign["id"];Phản hồi: chiến dịch với chi phí và 1.000 tin nhắn đầu tiên. Tải thêm với tin nhắn chiến dịch.
HTTP/1.1 201 Created
{
"id": "CP-7KQ2-M9XA-4HTD",
"status": "sending",
"source": "api",
"recipients": 2,
"segments": 1,
"encoding": "GSM-7",
"cost": "0.01078",
"refunded": "0.00000",
"client_ref": "orders-4821",
"scheduled_at": null,
"created_at": "2026-11-07T10:32:04.118Z",
"done_at": null,
"counts": { "queued": 2, "sent": 0, "delivered": 0, "failed": 0, "canceled": 0 },
"dropped": [],
"balance": "248.30422",
"messages": [
{ "id": "SM-2RBW-8MZN-QF6K", "campaign_id": "CP-7KQ2-M9XA-4HTD", "to": "+447700900461", "country": "GB", "parts": 1, "price": "0.00819", "status": "queued", "error": null, "created_at": "2026-11-07T10:32:04.118Z", "sent_at": null, "done_at": null }
]
}Ước tính gửi
POST/estimate
Lấy cùng nội dung như /sms và trả về người nhận, phân đoạn, mã hóa, tổng chi phí và chi phí mỗi quốc gia mà không tính phí hoặc gửi bất cứ thứ gì.
{ "recipients": 2, "dropped": [], "segments": 1, "encoding": "GSM-7", "cost": "0.01078", "balance": "248.31500",
"countries": [ { "country": "GB", "recipients": 1, "cost": "0.00819" }, { "country": "BR", "recipients": 1, "cost": "0.00259" } ] }Trạng thái tin nhắn
GET/sms/{message_id}
Trả về một tin nhắn: số, quốc gia, phân đoạn, giá, trạng thái, lỗi cho tin nhắn thất bại và thời gian của mỗi bước.
Chiến dịch
GET/campaigns/{campaign_id}
Chiến dịch với chi phí, hoàn tiền và số lượng tin nhắn theo trạng thái.
GET/campaigns/{campaign_id}/messages?offset=0&limit=100
Tin nhắn theo thứ tự chúng được xếp hàng, tối đa 1.000 mỗi trang.
POST/campaigns/{campaign_id}/cancel
Hủy một chiến dịch đã lên lịch chưa bắt đầu và hoàn lại toàn bộ chi phí vào số dư.
Số dư và giá
GET/balance
{ "balance": "248.31500", "currency": "USD" }GET/rates
Công khai, không cần khóa. Mọi quốc gia với mã gọi và giá mỗi phân đoạn. /rates/GB trả về một quốc gia.
{ "updated": "2026-11-07", "rates": [ { "country": "GB", "name": "United Kingdom", "calling_code": "+44", "price": "0.00819", "currency": "USD", "unit": "SMS segment" } ] }Webhook giao hàng
Đặt URL webhook trong bảng điều khiển dưới Khóa API. Khi tin nhắn đạt trạng thái cuối cùng (đã giao hoặc thất bại), chúng tôi POST báo cáo đến đó. Trả lời với bất kỳ trạng thái 2xx nào trong vòng 8 giây; nếu không, cuộc gọi sẽ được thử lại tối đa 8 lần trong khoảng 11 giờ. Sử dụng id để bỏ qua báo cáo bạn đã xử lý.
POST https://your-server.example/sms-status
Content-Type: application/json
X-SendBulkSMS-Signature: t=1794047524,v1=5f0c3b9e...
{
"event": "message.status",
"id": "evt_8c1d2e4f6a7b9c0d1e2f",
"created_at": "2026-11-07T10:32:09.004Z",
"data": {
"message_id": "SM-2RBW-8MZN-QF6K",
"campaign_id": "CP-7KQ2-M9XA-4HTD",
"to": "+447700900461",
"country": "GB",
"status": "delivered",
"error": null,
"parts": 1,
"price": "0.00819",
"client_ref": "orders-4821",
"done_at": "2026-11-07T10:32:08.912Z"
}
}Kiểm tra chữ ký trước khi tin tưởng báo cáo: HMAC-SHA256 của t + "." + raw body với bí mật webhook của bạn, so sánh trong thời gian không đổi, và từ chối thời gian cũ hơn 5 phút.
import { createHmac, timingSafeEqual } from "node:crypto";
// raw = the request body exactly as received (string), header = X-SendBulkSMS-Signature
export function verify(raw, header, secret) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || "");
if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
const want = Buffer.from(createHmac("sha256", secret).update(m[1] + "." + raw).digest("hex"));
const got = Buffer.from(m[2]);
return want.length === got.length && timingSafeEqual(want, got);
}import hmac, hashlib, re, time
def verify(raw: bytes, header: str, secret: str) -> bool:
m = re.fullmatch(r"t=(\d+),v1=([0-9a-f]{64})", header or "")
if not m or abs(time.time() - int(m.group(1))) > 300:
return False
want = hmac.new(secret.encode(), m.group(1).encode() + b"." + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(want, m.group(2))<?php
function verify(string $raw, string $header, string $secret): bool {
if (!preg_match('/^t=(\d+),v1=([0-9a-f]{64})$/', $header, $m) || abs(time() - (int)$m[1]) > 300) return false;
$want = hash_hmac('sha256', $m[1] . '.' . $raw, $secret);
return hash_equals($want, $m[2]);
}Trạng thái
| Trạng thái | Ý nghĩa |
|---|---|
queued | Đã được chấp nhận và tính phí, đang chờ đến lượt trong hàng đợi |
sent | Đã chuyển đến tuyến đường, đang chờ báo cáo giao hàng |
delivered | Mạng đã xác nhận giao hàng đến thiết bị |
failed | Không giao được; giá được hoàn lại và lỗi giữ nguyên lý do |
canceled | Một phần của chiến dịch đã lên lịch bị hủy trước khi bắt đầu; đã được hoàn lại |
Lỗi
Lỗi sử dụng mã trạng thái HTTP và nội dung JSON: { "error": { "code": "insufficient_balance", "message": "..." } }. Một yêu cầu trả về lỗi sẽ không tính phí vào số dư.
| HTTP | Mã | Khi |
|---|---|---|
| 400 | bad_requestMột trường bị thiếu hoặc không hợp lệ; thông báo giải thích trường nào | Một trường bị thiếu hoặc không hợp lệ; thông báo giải thích trường nào |
| 400 | no_valid_numbersKhông có số nào trong "to" có thể được sử dụng | Không có số nào trong "to" có thể được sử dụng |
| 401 | unauthorizedAPI key bị thiếu hoặc không hợp lệ | API key bị thiếu hoặc không hợp lệ |
| 402 | insufficient_balanceSố dư không đủ để gửi; không có gì được tính phí | Số dư không đủ để gửi; không có gì được tính phí |
| 404 | not_foundChiến dịch, tin nhắn hoặc điểm cuối không tồn tại trong tài khoản của bạn | Chiến dịch, tin nhắn hoặc điểm cuối không tồn tại trong tài khoản của bạn |
| 409 | not_scheduledChỉ một chiến dịch đã lên lịch chưa bắt đầu mới có thể bị hủy | Chỉ một chiến dịch đã lên lịch chưa bắt đầu mới có thể bị hủy |
| 413 | too_many_recipientsHơn 10,000 số trong một yêu cầu | Hơn 10,000 số trong một yêu cầu |
| 429 | rate_limitedHơn 300 yêu cầu trong một phút cho key này | Hơn 300 yêu cầu trong một phút cho key này |
| 500 | server_errorThử lại; không tính phí cho một yêu cầu thất bại | Thử lại; không tính phí cho một yêu cầu thất bại |
Giới hạn
- 300 yêu cầu mỗi phút cho mỗi API key.
- 10,000 số mỗi yêu cầu gửi; 10 đoạn mỗi tin nhắn.
- Tin nhắn được gửi đi với tốc độ tối đa 200 mỗi phút cho mỗi hàng đợi, theo thứ tự chúng được chấp nhận.
- Lên lịch từ 5 phút đến 60 ngày trước.
- Các số trong danh sách không gửi của bạn sẽ bị bỏ qua và trả về trong dropped với mã suppressed; chúng không bị tính phí.