Permulaan pantas
- Buat akaun dan isi baki anda dalam konsol.
- Buka Kunci API dan buat kunci. Kunci boleh dibuat selepas isian pertama dikreditkan. Kunci hanya dipaparkan sekali; simpan sebagai rahsia.
- Hantar permintaan POST ke
/smsdengan nombor dan teks. Baca ID kempen yang dikembalikan, kemudian ikuti penghantaran dalam konsol atau melalui webhook.
Pengesahan
Setiap permintaan kecuali senarai kadar awam membawa kunci anda dalam header Pengecualian. Kunci bermula dengan sbk_live_. Kunci baru menggantikan yang lama dengan segera.
Authorization: Bearer sbk_live_YOUR_KEYHantar SMS
POST/sms
Mencipta kempen, mengecasnya dari baki dan mengatur setiap mesej. Nombor dibersihkan dan disahduplikat; yang tidak boleh digunakan dikembalikan dalam dropped dengan sebab dan tidak dicaj.
| Medan | Jenis | Penerangan |
|---|---|---|
todiperlukan | rentetan atau tatasusunan | Satu nombor atau tatasusunan sehingga 10,000 nombor dalam format antarabangsa, contohnya "+447700900461" |
textdiperlukan | rentetan | Teks mesej, sehingga 10 segmen. Teks GSM-7 muat 160 aksara setiap segmen, UCS-2 muat 70 |
schedule_atpilihan | rentetan | Masa ISO 8601 dari 5 minit hingga 60 hari ke hadapan. Abaikan untuk hantar sekarang |
client_refpilihan | rentetan | Rujukan anda sendiri, sehingga 64 aksara a-z A-Z 0-9 _ . : -, dikembalikan dalam laporan dan webhook |
opt_outpilihan | boolean | true menambahkan baris berhenti langganan yang ditetapkan dalam tetapan akaun anda |
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"];Respons: kempen dengan kos dan 1,000 mesej pertama. Dapatkan lebih banyak dengan mesej kempen.
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 }
]
}Anggaran penghantaran
POST/estimate
Mengambil badan yang sama seperti /sms dan mengembalikan penerima, segmen, pengekodan, jumlah kos dan kos setiap negara tanpa mengecas atau menghantar apa-apa.
{ "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" } ] }Status mesej
GET/sms/{message_id}
Mengembalikan satu mesej: nombor, negara, segmen, harga, status, ralat untuk mesej gagal dan masa setiap langkah.
Kempen
GET/campaigns/{campaign_id}
Kempen dengan kos, bayaran balik dan kiraan mesej setiap status.
GET/campaigns/{campaign_id}/messages?offset=0&limit=100
Mesej dalam urutan ia diatur, sehingga 1,000 setiap halaman.
POST/campaigns/{campaign_id}/cancel
Membatalkan kempen yang dijadualkan yang belum bermula dan membayar balik kos penuh ke baki.
Baki dan kadar
GET/balance
{ "balance": "248.31500", "currency": "USD" }GET/rates
Awam, tiada kunci diperlukan. Setiap negara dengan kod panggilan dan harga setiap segmen. /rates/GB mengembalikan satu negara.
{ "updated": "2026-11-07", "rates": [ { "country": "GB", "name": "United Kingdom", "calling_code": "+44", "price": "0.00819", "currency": "USD", "unit": "SMS segment" } ] }Webhook penghantaran
Tetapkan URL webhook dalam konsol di bawah Kunci API. Apabila mesej mencapai status akhir (dihantar atau gagal) kami POST laporan kepadanya. Jawab dengan sebarang status 2xx dalam 8 saat; jika tidak, panggilan akan dicuba semula sehingga 8 kali dalam kira-kira 11 jam. Gunakan id untuk mengabaikan laporan yang telah anda proses.
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"
}
}Semak tandatangan sebelum mempercayai laporan: HMAC-SHA256 bagi t + "." + badan mentah dengan rahsia webhook anda, dibandingkan dalam masa tetap, dan tolak masa lebih lama daripada 5 minit.
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]);
}Status
| Status | Maksud |
|---|---|
queued | Diterima dan dicaj, menunggu giliran dalam barisan |
sent | Diserahkan kepada laluan, menunggu laporan penghantaran |
delivered | Rangkaian mengesahkan penghantaran ke telefon bimbit |
failed | Tidak dihantar; harga dikembalikan dan ralat menyatakan sebab |
canceled | Sebahagian daripada kempen berjadual dibatalkan sebelum ia bermula; dikembalikan |
Ralat
Ralat menggunakan kod status HTTP dan badan JSON: { "error": { "code": "insufficient_balance", "message": "..." } }. Permintaan yang mengembalikan ralat tidak akan mengecaj saldo.
| HTTP | Kod | Bila |
|---|---|---|
| 400 | bad_requestMedan tiada atau tidak sah; mesej menerangkan yang mana | Medan tiada atau tidak sah; mesej menerangkan yang mana |
| 400 | no_valid_numbersTiada nombor dalam "to" boleh digunakan | Tiada nombor dalam "to" boleh digunakan |
| 401 | unauthorizedKunci API tiada atau tidak sah | Kunci API tiada atau tidak sah |
| 402 | insufficient_balanceSaldo tidak mencukupi untuk penghantaran; tiada caj dikenakan | Saldo tidak mencukupi untuk penghantaran; tiada caj dikenakan |
| 404 | not_foundKempen, mesej atau endpoint tidak wujud dalam akaun anda | Kempen, mesej atau endpoint tidak wujud dalam akaun anda |
| 409 | not_scheduledHanya kempen berjadual yang belum bermula boleh dibatalkan | Hanya kempen berjadual yang belum bermula boleh dibatalkan |
| 413 | too_many_recipientsLebih daripada 10,000 nombor dalam satu permintaan | Lebih daripada 10,000 nombor dalam satu permintaan |
| 429 | rate_limitedLebih daripada 300 permintaan dalam satu minit untuk kunci ini | Lebih daripada 300 permintaan dalam satu minit untuk kunci ini |
| 500 | server_errorCuba lagi; tiada caj dikenakan untuk permintaan yang gagal | Cuba lagi; tiada caj dikenakan untuk permintaan yang gagal |
Had
- 300 permintaan seminit setiap kunci API.
- 10,000 nombor setiap permintaan penghantaran; 10 segmen setiap mesej.
- Mesej dihantar sehingga 200 seminit setiap barisan, mengikut urutan penerimaan.
- Penjadualan dari 5 minit hingga 60 hari ke hadapan.
- Nombor dalam senarai jangan-hantar anda dilangkau dan dikembalikan dalam dropped dengan kod suppressed; tiada caj dikenakan.