Referensi API SMS massal

REST API BulkSMSOnline mengirim pesan teks ke 227 negara dari perangkat lunak Anda sendiri, dengan harga, aturan segmen, penjadwalan, dan pengembalian dana yang sama seperti konsol. Permintaan dan respons berupa JSON lewat HTTPS, dan setiap status pengiriman akhir dapat dikirim ke server Anda sebagai webhook bertanda tangan.

URL dasarhttps://bulksmsonline.cc/api/v1

Ringkasan

Gunakan API saat pesan dipicu oleh sistem Anda sendiri: info pesanan dari toko, kode dari formulir login, pengingat dari alat pemesanan. Permintaan ke POST /v1/messages dengan hingga 10,000 nomor membuat satu kampanye, memotong saldo, dan mengantrekan setiap pesan. Kampanye yang dibuat lewat API juga muncul di konsol beserta laporan pengirimannya.

  • Semua jumlah berupa dolar AS dalam bentuk string dengan lima desimal, misalnya "0.00534".
  • Nomor telepon berformat internasional, dengan atau tanpa + di depan; spasi dan tanda hubung dihapus.
  • Waktu berformat ISO 8601 dalam UTC, misalnya 2026-12-01T09:00:00Z.
  • ID pesan dan kampanye berbentuk seperti MSG-XXXX-XXXX-XXXX dan CMP-XXXX-XXXX-XXXX.

Autentikasi

Buat kunci API di bagian API pada konsol (kunci aktif setelah isi saldo pertama Anda masuk). Kirim di header Authorization pada setiap permintaan. Kunci berbentuk bso_api_ diikuti 36 karakter; kunci hanya ditampilkan sekali, jadi simpan sebagai rahasia di server Anda. Membuat kunci baru langsung menggantikan kunci sebelumnya.

Authorization: Bearer bso_api_0123456789abcdef0123456789abcdef0123
Content-Type: application/json

Batas

Permintaan300 per menit per kunci; selebihnya dijawab 429 rate_limited
Nomor per permintaan10,000
Teks pesan2,000 karakter sesuai tulisan, hingga 10 segmen
Penjadwalansend_at dari 5 menit hingga 60 hari ke depan
Kecepatan pengiriman400 pesan per menit per antrean
Percobaan ulang webhook9 percobaan selama sekitar 22 jam

Kirim pesan

POST/v1/messages

Mengirim satu teks ke satu nomor atau lebih. Seluruh biaya diambil dari saldo saat permintaan diterima; setiap pesan yang tidak dapat dikirim dikembalikan kemudian. Responsnya berstatus 201 dan berisi kampanye beserta setiap pesan.

FieldDeskripsi
towajibSatu nomor atau array hingga 10,000 nomor dalam format internasional. Nomor ganda dikirim sekali; yang tidak terbaca dicantumkan di skipped.
textwajibPesannya, hingga 2,000 karakter dan 10 segmen. Teks GSM-7 memuat 160 karakter per SMS, Unicode 70.
send_atopsionalWaktu ISO 8601 untuk menjadwalkan pengiriman, 5 menit hingga 60 hari ke depan. Kosongkan untuk mengirim sekarang.
opt_outopsionaltrue menambahkan baris berhenti berlangganan dari pengaturan konsol Anda di baris baru pada bagian akhir.
client_refopsionalReferensi Anda sendiri, hingga 64 huruf, angka, dan _ . : -. Dikembalikan dalam laporan dan webhook.
curl -X POST https://bulksmsonline.cc/api/v1/messages \
  -H "Authorization: Bearer $BSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":["+447700900412","+33612345678"],"text":"Order 4521 has shipped. Track it at shop.example/t/4521","client_ref":"order-4521"}'
HTTP/1.1 201 Created
{
  "id": "CMP-7KQ2-M9XA-4HTD",
  "status": "sending",
  "channel": "api",
  "recipients": 2,
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.02158",
  "refunded": "0.00000",
  "client_ref": "order-4521",
  "send_at": null,
  "counts": { "queued": 2, "submitted": 0, "delivered": 0, "failed": 0, "canceled": 0 },
  "skipped": [],
  "balance": "118.43120",
  "messages": [
    { "id": "MSG-3RTW-81KD-ZQ0P", "to": "+447700900412", "country": "GB", "segments": 1, "price": "0.00834", "status": "queued" },
    { "id": "MSG-5HNA-4C2E-7YVB", "to": "+33612345678", "country": "FR", "segments": 1, "price": "0.01324", "status": "queued" }
  ]
}

Estimasi pengiriman

POST/v1/quote

Menerima isi yang sama dengan /v1/messages dan mengembalikan biaya pasti, segmen, dan encoding tanpa mengirim atau memotong apa pun. Gunakan untuk menampilkan harga kepada pengguna Anda sebelum mereka mengonfirmasi.

{
  "recipients": 2,
  "skipped": [],
  "segments": 1,
  "encoding": "GSM-7",
  "cost": "0.02158",
  "balance": "118.45278",
  "countries": [ { "country": "GB", "recipients": 1, "cost": "0.00834" }, { "country": "FR", "recipients": 1, "cost": "0.01324" } ]
}

Saldo

GET/v1/balance

{ "balance": "118.43120", "currency": "USD" }

Tarif

GET/v1/rates

GET/v1/rates/{country}

Harga satu segmen SMS untuk setiap tujuan, atau untuk satu kode negara ISO dua huruf. Kedua endpoint ini publik dan tidak memerlukan kunci.

{ "country": "DE", "name": "Germany", "calling_code": "+49", "price": "0.01544", "currency": "USD", "per": "segment" }

Status pesan

GET/v1/messages/{id}

{
  "id": "MSG-3RTW-81KD-ZQ0P",
  "campaign_id": "CMP-7KQ2-M9XA-4HTD",
  "to": "+447700900412",
  "country": "GB",
  "segments": 1,
  "price": "0.00834",
  "status": "delivered",
  "error": null,
  "created_at": "2026-11-07T09:00:02Z",
  "submitted_at": "2026-11-07T09:00:03Z",
  "final_at": "2026-11-07T09:00:08Z"
}

Kampanye

GET/v1/campaigns/{id}

GET/v1/campaigns/{id}/messages?offset=0&limit=100

Yang pertama mengembalikan kampanye beserta jumlah per status; yang kedua menelusuri pesannya per halaman, hingga 1,000 per halaman. Kampanye yang dikirim dari konsol dapat dibaca dengan cara yang sama memakai id yang ditampilkan di halamannya.

Batalkan pengiriman terjadwal

POST/v1/campaigns/{id}/cancel

Menghentikan kampanye yang dibuat dengan send_at dan belum dimulai. Setiap pesan dibatalkan dan seluruh biaya kembali ke saldo. Kampanye yang sudah berjalan dijawab 409 not_scheduled.

Webhook pengiriman

Tambahkan URL HTTPS di bagian API pada konsol untuk menerima setiap status akhir (delivered atau failed) sebagai permintaan POST. Jawab dengan status 2xx apa pun dalam 8 detik. Jawaban lain dan timeout dicoba ulang setelah 20 detik, 1, 5, dan 15 menit, lalu 1, 3, 6, dan 12 jam, total 9 percobaan. Kejadian yang sama bisa datang dua kali, jadi gunakan event_id agar diproses sekali.

POST https://your-server.example/sms-status
Content-Type: application/json
X-BulkSMSOnline-Signature: t=1794042008,v1=5f0c2a...e91b

{
  "type": "message.status",
  "event_id": "ev_8f1c22d0a4b97e63c1f0",
  "sent_at": "2026-11-07T09:00:09Z",
  "data": {
    "message_id": "MSG-3RTW-81KD-ZQ0P",
    "campaign_id": "CMP-7KQ2-M9XA-4HTD",
    "to": "+447700900412",
    "country": "GB",
    "status": "delivered",
    "error": null,
    "segments": 1,
    "price": "0.00834",
    "currency": "USD",
    "client_ref": "order-4521",
    "final_at": "2026-11-07T09:00:08Z"
  }
}

Verifikasi tanda tangan

Header berisi waktu Unix t dan tanda tangan v1 = HMAC-SHA256 dari string "t.raw_body" dengan rahasia webhook Anda, dalam hex. Hitung atas isi mentah sebelum mengurai JSON, bandingkan dalam waktu konstan, dan tolak kejadian yang lebih lama dari lima menit.

import crypto from "node:crypto";

export function verify(rawBody, 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 = crypto.createHmac("sha256", secret).update(m[1] + "." + rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}

Status

queuedDiterima dan menunggu keluar dari antrean
submittedDiserahkan ke jaringan tujuan
deliveredDikonfirmasi oleh ponsel (final)
failedTidak dapat dikirim; harga dikembalikan (final)
canceledBagian dari kampanye terjadwal yang dibatalkan sebelum dikirim (final)

Status kampanye adalah scheduled, sending, complete, atau canceled.

Error

Error dijawab dengan status HTTP dan isi JSON: { "error": { "code": "insufficient_balance", "message": "..." } }. Tidak ada biaya yang dipotong saat permintaan dijawab dengan error.

HTTPKodeArti
400invalid_requestAda field yang hilang atau tidak valid; pesannya menyebutkan yang mana.
400invalid_jsonIsi permintaan bukan JSON.
400no_valid_numbersTidak ada nomor yang dapat dibaca.
401unauthorizedKunci hilang, salah format, atau sudah diganti.
402insufficient_balanceSaldo tidak mencukupi biaya; isi saldo lalu kirim lagi.
404not_foundID atau endpoint tidak dikenal.
409not_scheduledHanya kampanye terjadwal yang belum dimulai yang dapat dibatalkan.
413too_many_recipientsLebih dari 10,000 nomor dalam satu permintaan.
429rate_limitedLebih dari 300 permintaan dalam semenit.
500server_errorUlangi permintaan; tidak ada biaya yang dipotong.

Dapatkan kunci API di konsol

Buat akun, lakukan isi saldo pertama, dan buat kunci di bagian API. Permintaan pertama Anda dapat dikirim semenit kemudian.

Buat akun
Referensi API SMS Massal: Endpoint REST dan Webhook | BulkSMSOnline