Mulai cepat
- Buat akun dan isi saldo Anda di konsol.
- Buka API keys dan buat kunci. Kunci dapat dibuat setelah pengisian pertama dikreditkan. Kunci hanya ditampilkan sekali; simpan sebagai rahasia.
- Kirim permintaan POST ke
/smsdengan nomor dan teks. Baca ID kampanye yang dikembalikan, lalu pantau pengiriman di konsol atau melalui webhook.
Autentikasi
Setiap permintaan kecuali daftar tarif publik membawa kunci Anda di header Authorization. Kunci dimulai dengan sbk_live_. Kunci baru menggantikan yang lama segera.
Authorization: Bearer sbk_live_YOUR_KEYKirim SMS
POST/sms
Membuat kampanye, menagihnya dari saldo dan mengantre setiap pesan. Nomor dibersihkan dan dihapus duplikat; yang tidak dapat digunakan dikembalikan di dropped dengan alasan dan tidak dikenakan biaya.
| Kolom | Tipe | Deskripsi |
|---|---|---|
towajib | string atau array | Satu nomor atau array hingga 10,000 nomor dalam format internasional, contohnya "+447700900461" |
textwajib | string | Teks pesan, hingga 10 segmen. Teks GSM-7 muat 160 karakter per segmen, UCS-2 muat 70 |
schedule_atopsional | string | Waktu ISO 8601 dari 5 menit hingga 60 hari ke depan. Abaikan untuk mengirim sekarang |
client_refopsional | string | Referensi Anda sendiri, hingga 64 karakter a-z A-Z 0-9 _ . : -, dikembalikan dalam laporan dan webhook |
opt_outopsional | boolean | true menambahkan baris opt-out yang diatur di pengaturan akun 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: kampanye dengan biayanya dan 1.000 pesan pertama. Ambil lebih banyak dengan pesan kampanye.
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 }
]
}Estimasi pengiriman
POST/estimate
Mengambil body yang sama seperti /sms dan mengembalikan penerima, segmen, encoding, total biaya dan biaya per negara tanpa menagih atau mengirim apa pun.
{ "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 pesan
GET/sms/{message_id}
Mengembalikan satu pesan: nomor, negara, segmen, harga, status, kesalahan untuk pesan yang gagal dan waktu setiap langkah.
Kampanye
GET/campaigns/{campaign_id}
Kampanye dengan biaya, pengembalian dana dan jumlah pesan per status.
GET/campaigns/{campaign_id}/messages?offset=0&limit=100
Pesan dalam urutan antrean, hingga 1.000 per halaman.
POST/campaigns/{campaign_id}/cancel
Membatalkan kampanye terjadwal yang belum dimulai dan mengembalikan biaya penuh ke saldo.
Saldo dan tarif
GET/balance
{ "balance": "248.31500", "currency": "USD" }GET/rates
Publik, tidak perlu kunci. Setiap negara dengan kode panggilan dan harga per 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 pengiriman
Atur URL webhook di konsol di bawah API keys. Ketika pesan mencapai status akhir (terkirim atau gagal) kami POST laporan ke sana. Jawab dengan status 2xx dalam 8 detik; jika tidak, panggilan akan diulang hingga 8 kali dalam sekitar 11 jam. Gunakan id untuk mengabaikan laporan yang sudah 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"
}
}Periksa tanda tangan sebelum mempercayai laporan: HMAC-SHA256 dari t + "." + raw body dengan rahasia webhook Anda, dibandingkan dalam waktu konstan, dan tolak waktu yang lebih lama dari 5 menit.
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 | Arti |
|---|---|
queued | Diterima dan dikenakan biaya, menunggu gilirannya dalam antrian |
sent | Diteruskan ke rute, menunggu laporan pengiriman |
delivered | Jaringan mengonfirmasi pengiriman ke ponsel |
failed | Tidak terkirim; biaya dikembalikan dan error berisi alasannya |
canceled | Bagian dari kampanye terjadwal yang dibatalkan sebelum dimulai; dana dikembalikan |
Kesalahan
Error menggunakan kode status HTTP dan badan JSON: { "error": { "code": "insufficient_balance", "message": "..." } }. Permintaan yang mengembalikan error tidak akan mengurangi saldo.
| HTTP | Kode | Ketika |
|---|---|---|
| 400 | bad_requestKolom tidak ada atau tidak valid; pesan menjelaskan yang mana | Kolom tidak ada atau tidak valid; pesan menjelaskan yang mana |
| 400 | no_valid_numbersTidak ada nomor dalam "to" yang dapat digunakan | Tidak ada nomor dalam "to" yang dapat digunakan |
| 401 | unauthorizedKunci API tidak ada atau tidak valid | Kunci API tidak ada atau tidak valid |
| 402 | insufficient_balanceSaldo tidak mencukupi untuk pengiriman; tidak ada biaya yang dikenakan | Saldo tidak mencukupi untuk pengiriman; tidak ada biaya yang dikenakan |
| 404 | not_foundKampanye, pesan, atau endpoint tidak ada di akun Anda | Kampanye, pesan, atau endpoint tidak ada di akun Anda |
| 409 | not_scheduledHanya kampanye terjadwal yang belum dimulai yang dapat dibatalkan | Hanya kampanye terjadwal yang belum dimulai yang dapat dibatalkan |
| 413 | too_many_recipientsLebih dari 10,000 nomor dalam satu permintaan | Lebih dari 10,000 nomor dalam satu permintaan |
| 429 | rate_limitedLebih dari 300 permintaan dalam satu menit untuk kunci ini | Lebih dari 300 permintaan dalam satu menit untuk kunci ini |
| 500 | server_errorCoba lagi; tidak ada biaya untuk permintaan yang gagal | Coba lagi; tidak ada biaya untuk permintaan yang gagal |
Batasan
- 300 permintaan per menit per kunci API.
- 10,000 nomor per permintaan pengiriman; 10 segmen per pesan.
- Pesan dikirim hingga 200 per menit per antrian, sesuai urutan penerimaan.
- Penjadwalan dari 5 menit hingga 60 hari ke depan.
- Nomor dalam daftar jangan-kirim akan dilewati dan dikembalikan di dropped dengan kode suppressed; tidak dikenakan biaya.