Tài liệu tham khảo API SMS hàng loạt

REST API của BulkSMSOnline gửi tin nhắn văn bản đến 227 quốc gia từ phần mềm của riêng bạn, với cùng giá cả, quy tắc phân đoạn, lập lịch và hoàn tiền như bảng điều khiển. Yêu cầu và phản hồi là JSON qua HTTPS, và mọi trạng thái giao hàng cuối cùng có thể được đẩy đến máy chủ của bạn dưới dạng webhook đã ký.

URL cơ sởhttps://bulksmsonline.cc/api/v1

Tổng quan

Sử dụng API khi tin nhắn được kích hoạt bởi hệ thống của bạn: cập nhật đơn hàng từ cửa hàng, mã từ biểu mẫu đăng nhập, nhắc nhở từ công cụ đặt chỗ. Một yêu cầu POST /v1/messages với tối đa 10,000 số sẽ tạo một chiến dịch, trừ tiền từ số dư và xếp hàng mỗi tin nhắn. Các chiến dịch tạo bởi API cũng xuất hiện trong bảng điều khiển cùng với báo cáo gửi thành công của chúng.

  • Tất cả số tiền đều là đô la Mỹ dưới dạng chuỗi với năm chữ số thập phân, ví dụ "0.00534".
  • Số điện thoại là quốc tế, có hoặc không có dấu + ở đầu; khoảng trắng và dấu gạch ngang sẽ bị loại bỏ.
  • Thời gian theo chuẩn ISO 8601 và múi giờ UTC, ví dụ 2026-12-01T09:00:00Z.
  • ID tin nhắn và chiến dịch có dạng MSG-XXXX-XXXX-XXXX và CMP-XXXX-XXXX-XXXX.

Xác thực

Tạo một khóa API trong mục API trên bảng điều khiển (khóa sẽ mở sau khi bạn nạp tiền lần đầu). Gửi khóa này trong tiêu đề Authorization của mỗi yêu cầu. Một khóa có dạng bso_api_ theo sau bởi 36 ký tự; nó chỉ hiển thị một lần, vì vậy hãy lưu trữ nó như một bí mật trên máy chủ của bạn. Tạo khóa mới sẽ thay thế khóa cũ ngay lập tức.

Authorization: Bearer bso_api_0123456789abcdef0123456789abcdef0123
Content-Type: application/json

Giới hạn

Yêu cầu300 mỗi phút trên mỗi khóa; nhiều hơn sẽ nhận phản hồi 429 rate_limited
Số lượng số mỗi yêu cầu10,000
Nội dung tin nhắn2,000 ký tự như đã viết, tối đa 10 phân đoạn
Lập lịchsend_at từ 5 phút đến 60 ngày sau
Tốc độ gửi400 tin nhắn mỗi phút trên mỗi hàng đợi
Thử lại webhook9 lần thử trong khoảng 22 giờ

Gửi tin nhắn

POST/v1/messages

Gửi một tin nhắn đến một hoặc nhiều số. Toàn bộ chi phí được trừ từ số dư khi yêu cầu được chấp nhận; mỗi tin nhắn không thể gửi được sẽ được hoàn tiền sau. Phản hồi có trạng thái 201 và chiến dịch cùng với từng tin nhắn.

TrườngMô tả
tobắt buộcMột số hoặc một mảng tối đa 10,000 số theo định dạng quốc tế. Các số lặp lại chỉ được gửi một lần; các số không đọc được sẽ liệt kê trong skipped.
textbắt buộcTin nhắn, tối đa 2,000 ký tự và 10 phân đoạn. Văn bản GSM-7 chứa 160 ký tự mỗi SMS, Unicode 70.
send_attùy chọnThời gian ISO 8601 để lên lịch gửi, từ 5 phút đến 60 ngày sau. Bỏ trống để gửi ngay.
opt_outtùy chọntrue thêm dòng từ chối nhận từ cài đặt console vào một dòng mới ở cuối.
client_reftùy chọnTham chiếu riêng của bạn, tối đa 64 chữ cái, chữ số và _ . : -. Nó được trả về trong báo cáo và webhooks.
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" }
  ]
}

Báo giá gửi

POST/v1/quote

Lấy cùng nội dung như /v1/messages và trả về chi phí chính xác, phân đoạn và mã hóa mà không gửi hoặc tính phí. Sử dụng để hiển thị giá cho người dùng của bạn trước khi họ xác nhận.

{
  "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" } ]
}

Số dư

GET/v1/balance

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

Biểu phí

GET/v1/rates

GET/v1/rates/{country}

Giá của một phân đoạn SMS cho mọi điểm đến, hoặc cho một mã quốc gia ISO hai chữ cái. Hai endpoint này là công khai và không cần khóa.

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

Trạng thái tin nhắn

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"
}

Chiến dịch

GET/v1/campaigns/{id}

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

Đầu tiên trả về chiến dịch với số lượng theo trạng thái; thứ hai phân trang qua các tin nhắn, tối đa 1.000 mỗi trang. Chiến dịch gửi từ console có thể đọc theo cách tương tự với id hiển thị trên trang của chúng.

Hủy lịch gửi đã đặt

POST/v1/campaigns/{id}/cancel

Dừng một chiến dịch được tạo với send_at và chưa bắt đầu. Mọi tin nhắn bị hủy và toàn bộ chi phí trả về số dư. Chiến dịch đang gửi trả lời 409 not_scheduled.

Webhook giao tin

Thêm một URL HTTPS trong mục API trên console để nhận mỗi trạng thái cuối (đã gửi hoặc thất bại) dưới dạng yêu cầu POST. Trả lời với bất kỳ trạng thái 2xx nào trong vòng 8 giây. Các phản hồi khác và timeouts được thử lại sau 20 giây, 1, 5 và 15 phút, sau đó 1, 3, 6 và 12 giờ, tổng cộng 9 lần thử. Sự kiện tương tự có thể đến hai lần, vì vậy hãy sử dụng event_id để xử lý một lần.

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"
  }
}

Xác minh chữ ký

Header chứa thời gian Unix t và chữ ký v1 = HMAC-SHA256 của chuỗi "t.raw_body" với webhook secret của bạn, ở dạng hex. Tính toán nó trên raw body trước khi phân tích JSON, so sánh trong thời gian không đổi và từ chối các sự kiện cũ hơn năm phút.

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]));
}

Trạng thái

queuedĐã chấp nhận và đang chờ rời hàng đợi
submittedĐã chuyển đến mạng đích
deliveredĐã xác nhận bởi thiết bị (cuối cùng)
failedKhông thể gửi; giá được hoàn lại (cuối cùng)
canceledMột phần của chiến dịch đã lên lịch bị hủy trước khi gửi (cuối cùng)

Trạng thái chiến dịch là scheduled, sending, complete hoặc canceled.

Lỗi

Lỗi trả lời với trạng thái HTTP và nội dung JSON: { "error": { "code": "insufficient_balance", "message": "..." } }. Không tính phí khi yêu cầu trả lời với lỗi.

HTTPMãÝ nghĩa
400invalid_requestThiếu một trường hoặc không hợp lệ; tin nhắn cho biết trường nào.
400invalid_jsonNội dung không phải là JSON.
400no_valid_numbersKhông thể đọc được số điện thoại nào.
401unauthorizedKhóa bị thiếu, sai định dạng hoặc đã bị thay thế.
402insufficient_balanceSố dư không đủ để thanh toán; nạp tiền và gửi lại.
404not_foundID hoặc endpoint không xác định.
409not_scheduledChỉ có thể hủy một chiến dịch đã lên lịch nhưng chưa bắt đầu.
413too_many_recipientsNhiều hơn 10,000 số trong một yêu cầu.
429rate_limitedNhiều hơn 300 yêu cầu trong một phút.
500server_errorThử lại yêu cầu; không có gì bị tính phí.

Lấy khóa API trong bảng điều khiển

Tạo tài khoản, thêm lần nạp tiền đầu tiên và tạo khóa trong mục API. Yêu cầu đầu tiên của bạn có thể được gửi đi sau một phút.

Tạo tài khoản
Tài liệu tham khảo API SMS hàng loạt: REST Endpoints và Webhooks | BulkSMSOnline