Справочник API массовых SMS

REST API BulkSMSOnline отправляет текстовые сообщения в 227 стран из вашего ПО с теми же ценами, правилами сегментов, планированием и возвратами, что и консоль. Запросы и ответы, JSON по HTTPS, а каждый финальный статус доставки может отправляться на ваш сервер через подписанный вебхук.

Базовый URLhttps://bulksmsonline.cc/api/v1

Обзор

Используйте API, когда сообщения запускаются вашими системами: уведомления о заказах из магазина, коды из формы входа, напоминания из инструмента бронирования. Запрос POST /v1/messages с до 10,000 номерами создаёт одну кампанию, списывает средства с баланса и ставит каждое сообщение в очередь. Кампании, созданные через API, также отображаются в консоли с отчётами о доставке.

  • Все суммы указаны в долларах США в виде строк с пятью знаками после запятой, например "0.00534".
  • Номера телефонов указываются в международном формате, с начальным + или без; пробелы и дефисы удаляются.
  • Время указывается в формате ISO 8601 по UTC, например 2026-12-01T09:00:00Z.
  • ID сообщений и кампаний выглядят как MSG-XXXX-XXXX-XXXX и CMP-XXXX-XXXX-XXXX.

Аутентификация

Создайте ключ API в разделе API в консоли (ключи становятся доступны после первого пополнения). Передавайте его в заголовке Authorization каждого запроса. Ключ выглядит как bso_api_ и 36 символов; он показывается один раз, поэтому сохраните его как секрет на вашем сервере. Создание нового ключа немедленно заменяет предыдущий.

Authorization: Bearer bso_api_0123456789abcdef0123456789abcdef0123
Content-Type: application/json

Лимиты

Запросы300 в минуту на ключ; при превышении, ответ 429 rate_limited
Номеров в запросе10,000
Текст сообщения2,000 символов как написано, до 10 сегментов
Планированиеsend_at от 5 минут до 60 дней вперёд
Скорость отправки400 сообщений в минуту на очередь
Повторы вебхуков9 попыток в течение примерно 22 часов

Отправка сообщений

POST/v1/messages

Отправляет один текст на один или несколько номеров. Полная стоимость списывается с баланса при принятии запроса; за каждое сообщение, которое не удалось доставить, средства возвращаются позже. Ответ имеет статус 201 и содержит кампанию с каждым сообщением.

ПолеОписание
toобязательноОдин номер или массив до 10,000 номеров в международном формате. Повторяющиеся номера отправляются один раз; нечитаемые указываются в skipped.
textобязательноСообщение длиной до 2,000 символов и 10 сегментов. Текст в GSM-7 содержит 160 символов на SMS, в Unicode, 70.
send_atопциональноВремя по ISO 8601 для планирования отправки, от 5 минут до 60 дней вперед. Оставьте пустым для отправки сейчас.
opt_outопциональноtrue добавляет вашу строку отписки из настроек консоли на новой строке в конце.
client_refопциональноВаш собственный идентификатор, до 64 букв, цифр и _ . : -. Возвращается в отчетах и вебхуках.
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" }
  ]
}

Рассчитать отправку

POST/v1/quote

Принимает тот же body, что и /v1/messages, и возвращает точную стоимость, сегменты и кодировку без отправки или списания средств. Используйте для показа цены вашим пользователям до подтверждения.

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

Баланс

GET/v1/balance

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

Тарифы

GET/v1/rates

GET/v1/rates/{country}

Цена одного сегмента SMS для каждого направления или для одного двухбуквенного кода страны ISO. Эти эндпоинты публичны и не требуют ключа.

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

Статус сообщения

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

Кампании

GET/v1/campaigns/{id}

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

Первый возвращает кампанию с количеством сообщений по статусам; второй пролистывает сообщения, до 1000 на страницу. Кампании, отправленные из консоли, можно читать так же, используя id, указанный на их странице.

Отменить запланированную отправку

POST/v1/campaigns/{id}/cancel

Останавливает кампанию, созданную с send_at и еще не начатую. Все сообщения отменяются, полная стоимость возвращается на баланс. Кампания, которая уже отправляется, отвечает 409 not_scheduled.

Вебхуки доставки

Добавьте HTTPS URL в разделе API в консоли для получения каждого финального статуса (доставлено или не доставлено) как POST запроса. Отвечайте любым статусом 2xx в течение 8 секунд. Другие ответы и таймауты повторяются через 20 секунд, 1, 5 и 15 минут, затем 1, 3, 6 и 12 часов, всего 9 попыток. Одно и то же событие может прийти дважды, поэтому используйте event_id для однократной обработки.

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

Проверьте подпись

Заголовок содержит Unix время t и подпись v1 = HMAC-SHA256 строки "t.raw_body" с вашим секретом вебхука в hex. Вычисляйте ее над сырым телом до парсинга JSON, сравнивайте за постоянное время и отклоняйте события старше пяти минут.

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

Статусы

queuedПринято и ожидает выхода из очереди
submittedПередано в сеть назначения
deliveredПодтверждено устройством (финально)
failedНе удалось доставить; стоимость возвращена (финально)
canceledЧасть запланированной кампании отменена до отправки (финально)

Статус кампании: scheduled, sending, complete или canceled.

Ошибки

Ошибки отвечают HTTP статусом и JSON телом: { "error": { "code": "insufficient_balance", "message": "..." } }. При ответе с ошибкой ничего не списывается.

HTTPКодЗначение
400invalid_requestОтсутствует или неверное поле; сообщение указывает, какое.
400invalid_jsonТело запроса не является JSON.
400no_valid_numbersНе удалось прочитать ни одного номера.
401unauthorizedКлюч отсутствует, некорректен или заменён.
402insufficient_balanceБаланс недостаточен для оплаты; пополните и отправьте снова.
404not_foundНеизвестный id или эндпоинт.
409not_scheduledОтменить можно только запланированную, но ещё не начатую рассылку.
413too_many_recipientsБолее 10,000 номеров в одном запросе.
429rate_limitedБолее 300 запросов в минуту.
500server_errorПовторите запрос; списаний не было.

Получите API-ключ в консоли

Создайте аккаунт, пополните баланс и сгенерируйте ключ в разделе API. Ваш первый запрос можно отправить уже через минуту.

Создать аккаунт
Справочник API Bulk SMS: REST-эндпоинты и вебхуки | BulkSMSOnline