Lewati ke konten
smsbulk

API SMS Massal v1

API REST kecil untuk mengirim SMS massal dari perangkat lunak Anda sendiri: JSON masuk dan keluar, kunci Bearer, harga dan pemeriksaan yang sama seperti di konsol, serta webhook yang ditandatangani untuk laporan pengiriman. URL Dasar https://smsbulk.cc/rest/v1

Ikhtisar

Kirim hingga 8,000 nomor per permintaan, masing-masing dengan nilai gabungannya sendiri, dan API memberi harga setiap penerima dengan teks gabungan mereka sendiri, persis seperti konsol. Minta kutipan terlebih dahulu dengan teks yang sama untuk mengetahui biayanya; tidak ada yang dikirim atau dibebankan oleh kutipan. Waktu adalah ISO 8601 dalam UTC, uang adalah string dalam dolar AS dengan lima desimal.

curl https://smsbulk.cc/rest/v1/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipients": [
      { "to": "+14155550142", "fields": { "name": "Maria" } },
      { "to": "+447400123456", "fields": { "name": "Tom" } }
    ],
    "text": "Hi {{name}}, your order ships today.",
    "client_ref": "order-batch-17"
  }'

Autentikasi

Buat kunci di konsol di bawah API dan webhook; kunci terbuka setelah top-up pertama Anda yang dikreditkan. Kirimkan pada setiap permintaan sebagai token Bearer. Kunci ditampilkan sekali; Anda dapat menyimpan hingga 5 kunci dan mencabut salah satunya sekaligus.

Authorization: Bearer smsb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Tarif

Publik, tidak perlu kunci. Harga per segmen SMS untuk setiap tujuan, atau untuk satu kode ISO.

GEThttps://smsbulk.cc/rest/v1/rates

GEThttps://smsbulk.cc/rest/v1/rates/{ISO}

{
  "country": "US",
  "name": "United States",
  "dial_code": "+1",
  "rate": "0.00485",
  "currency": "USD",
  "per": "message segment"
}

Kredit

GEThttps://smsbulk.cc/rest/v1/credit

{ "credit": "125.40000", "currency": "USD", "account": "A418820037715" }

Kutipan

Menghitung biaya pengiriman tanpa mengirimkannya. Mengambil teks yang sama seperti Kirim.

POSThttps://smsbulk.cc/rest/v1/quote

KolomArti
toSatu nomor atau daftar. Format internasional dengan + paling aman; nomor lokal memerlukan default_country.
recipientsAlih-alih ke: daftar { to, fields } di mana fields mengisi bidang gabungan seperti {{name}}.
textPesan, hingga 2,000 karakter dan 10 segmen setelah penggabungan.
default_countryKode ISO digunakan untuk nomor yang ditulis tanpa +, seperti GB. Kembali ke default yang disimpan di Pengaturan.
opt_outMenambahkan teks opt-out yang disimpan Anda sebagai baris terakhir (simpan terlebih dahulu di Pengaturan).
{
  "recipients": 2,
  "messages": 2,
  "segments": { "min": 1, "max": 1 },
  "encoding": "GSM-7",
  "total": "0.01240",
  "currency": "USD",
  "credit": "125.40000",
  "credit_after": "125.38760",
  "countries": [
    { "country": "US", "recipients": 1, "rate": "0.00485", "segments": 1, "subtotal": "0.00485" },
    { "country": "GB", "recipients": 1, "rate": "0.00755", "segments": 1, "subtotal": "0.00755" }
  ],
  "left_out": []
}

Kirim

Membuat kampanye, mengambil totalnya dari kredit Anda dan mengantrekan pesan. Menjawab 201 dengan kampanye. Nomor yang tidak dapat dikirim dicantumkan di left_out dan tidak pernah dibebankan.

POSThttps://smsbulk.cc/rest/v1/send

KolomArti
to / recipients / text / default_country / opt_outSeperti dalam Quote.
send_atWaktu ISO 8601 untuk memulai, 5 menit hingga 90 hari ke depan. Biarkan kosong untuk mengirim sekarang.
nameLabel Anda untuk kampanye, hingga 80 karakter.
client_refReferensi Anda sendiri, hingga 64 karakter, dikembalikan pada setiap pesan dan webhook.
HTTP/1.1 201 Created
{
  "campaign": {
    "id": "C507318264409",
    "name": null,
    "status": "sending",
    "source": "api",
    "test": false,
    "recipients": 2,
    "cost": "0.01240",
    "refunded": "0.00000",
    "net_cost": "0.01240",
    "currency": "USD",
    "send_at": null,
    "created_at": "2026-11-07T14:02:11.000Z",
    "started_at": "2026-11-07T14:02:11.000Z",
    "finished_at": null,
    "client_ref": "order-batch-17"
  },
  "messages": 2,
  "left_out": []
}

Kampanye

GEThttps://smsbulk.cc/rest/v1/campaigns?limit=25&before={id}

GEThttps://smsbulk.cc/rest/v1/campaigns/{id}

GEThttps://smsbulk.cc/rest/v1/campaigns/{id}/messages?status=failed&limit=100&after={message id}

Satu kampanye mencakup hitungan per status: dalam antrian, terkirim, terkirim, gagal, dan dibatalkan. Halaman daftar pesan dengan after dan has_more; hingga 1.000 per halaman.

Pesan

GEThttps://smsbulk.cc/rest/v1/messages/{id}

GEThttps://smsbulk.cc/rest/v1/messages?to=%2B14155550142&status=delivered&client_ref=order-batch-17&limit=50

{
  "id": "M220947781305",
  "campaign": "C507318264409",
  "to": "+14155550142",
  "country": "US",
  "segments": 1,
  "encoding": "GSM-7",
  "price": "0.00485",
  "status": "delivered",
  "reason": null,
  "reason_text": null,
  "refunded": false,
  "client_ref": "order-batch-17",
  "created_at": "2026-11-07T14:02:11.000Z",
  "sent_at": "2026-11-07T14:02:12.000Z",
  "finished_at": "2026-11-07T14:02:16.000Z"
}

Batalkan kampanye yang dijadwalkan

POSThttps://smsbulk.cc/rest/v1/campaigns/{id}/cancel

Berfungsi hingga waktu mulai. Seluruh biaya kembali ke kredit Anda dalam satu baris buku besar dan status kampanye menjadi dibatalkan.

Webhook

Atur URL endpoint di konsol. Kami POST JSON untuk message.delivered, message.failed, dan campaign.done, plus tes saat Anda menekan Kirim tes acara. Setiap acara membawa empat header, dan jawaban 2xx apa pun dalam 10 detik dianggap diterima.

KolomArti
Smsbulk-EventNama acara, seperti message.delivered.
Smsbulk-DeliveryID pengiriman, sama pada setiap percobaan ulang satu acara.
Smsbulk-TimestampDetik Unix saat percobaan ini ditandatangani.
Smsbulk-Signaturesha256= diikuti oleh base64 HMAC-SHA256 dari timestamp, baris baru, dan badan mentah, dikunci dengan rahasia sbw_ Anda.

Pengiriman dicoba 8 kali: sekaligus, kemudian setelah 1 menit, 5 menit, 15 menit, 1 jam, 3 jam, 6 jam, dan 12 jam. Setiap percobaan ditampilkan di log pengiriman konsol dengan status HTTP dan awal jawaban Anda.

{
  "id": "dlv_3f9a1c07b2e44d58a6c1",
  "event": "message.failed",
  "created": "2026-11-07T14:02:16.000Z",
  "data": {
    "message": "M220947781305",
    "campaign": "C507318264409",
    "to": "+447400123456",
    "country": "GB",
    "status": "failed",
    "reason": "not_in_service",
    "segments": 1,
    "price": "0.00755",
    "client_ref": "order-batch-17"
  }
}

Verifikasi tanda tangan

import crypto from "node:crypto";

// raw = the request body exactly as received (string), secret = your sbw_ signing secret
export function verify(raw, headers, secret) {
  const ts = headers["smsbulk-timestamp"];
  const want = "sha256=" + crypto.createHmac("sha256", secret).update(ts + "\n" + raw).digest("base64");
  const got = headers["smsbulk-signature"] || "";
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && got.length === want.length && crypto.timingSafeEqual(Buffer.from(got), Buffer.from(want));
}

Kesalahan dan batasan

Kesalahan menggunakan status HTTP dan badan JSON: {"error":{"code":"insufficient_credit","message":"..."}}. Tidak ada biaya yang dikenakan saat permintaan gagal.

KolomArti
400 bad_jsonBadan bukan JSON.
401 unauthorizedKunci hilang, salah format, atau dicabut.
402 insufficient_creditTotal melebihi saldo Anda. Tambahkan dana di konsol.
404 not_foundTidak ada endpoint, kampanye, pesan, atau kode ISO seperti itu di akun ini.
409 not_scheduledPembatalan diminta untuk kampanye yang sudah dimulai.
422 text_missing, text_too_long, too_many_segmentsPesan kosong, lebih dari 2,000 karakter, atau lebih dari 10 segmen untuk penerima.
422 no_recipients, too_many, recipients_missingTidak ada nomor yang dapat dikirim, lebih dari 8,000 nomor, atau tidak ada penerima maupun tujuan.
422 schedule_range, bad_send_atsend_at di luar 5 menit hingga 90 hari, atau bukan waktu yang valid.
422 opt_out_unsetopt_out benar tetapi tidak ada teks yang disimpan di Pengaturan.
429 rate_limitedLebih dari 300 permintaan dalam satu menit untuk kunci ini.

Setiap jawaban membawa X-RateLimit-Limit, X-RateLimit-Remaining, dan X-RateLimit-Reset.

Kode yang Ditinggalkan

Nomor yang dihapus sebelum penetapan harga kembali di left_out dengan posisi mereka dalam daftar Anda, nilai yang Anda kirim, kode, dan alasan sederhana.

KolomArti
no_country_codeTidak ada + dan tidak ada negara default.
too_short / too_longKurang dari 8 atau lebih dari 15 digit.
not_a_numberHuruf atau simbol yang bukan bagian dari nomor.
nanp_lengthNomor +1 tanpa sebelas digit.
not_coveredTujuan di luar daftar kami.
duplicateNomor yang sama muncul sebelumnya dalam permintaan.
suppressedNomor tersebut ada di daftar jangan kirim Anda.

Status dan alasan

KolomArti
queuedMenunggu untuk keluar dari antrian kami.
sentDiserahkan ke jaringan, menunggu laporan pengiriman. Kebanyakan laporan tiba dalam beberapa menit; beberapa jaringan membutuhkan hingga 24 jam.
deliveredJaringan mengonfirmasi bahwa ponsel menerimanya.
failedTidak terkirim. Harga telah dikembalikan ke saldo Anda.
canceledTidak dikirim karena Anda membatalkan. Dana dikembalikan.
KolomArti
network_errorKesalahan jaringan
switched_offPonsel mati atau di luar jangkauan
not_in_serviceNomor tidak aktif
blockedDiblokir oleh jaringan atau penerima
landlineTelepon rumah atau nomor yang tidak dapat menerima SMS
content_filterDitolak oleh filter konten jaringan
expiredKedaluwarsa: tidak ada laporan sebelum batas waktu jaringan
unknownRespon jaringan tidak diketahui
canceledDibatalkan sebelum dikirim

Pertanyaan tentang API? Buka tiket di konsol, atau baca FAQ.

Dokumentasi API SMS Massal v1: Kirim, Kutipan, Webhooks | SMSBulk