Довідник API масових SMS

REST API BulkSMSOnline надсилає SMS у 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.
  • Ідентифікатори повідомлень і розсилок мають вигляд 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

Приймає те саме тіло, що й /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

Перша повертає розсилку з кількістю за статусами; друга постачає її повідомлення по сторінках, до 1,000 на сторінку. Розсилки, надіслані з консолі, можна читати так само за ідентифікатором, що показаний на їхній сторінці.

Скасування запланованого надсилання

POST/v1/campaigns/{id}/cancel

Зупиняє розсилку, створену з send_at, яка ще не почалася. Усі повідомлення скасовуються, а повна вартість повертається на баланс. Розсилка, що вже триває, відповідає 409 not_scheduled.

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

Додайте URL HTTPS в розділі API консолі, щоб отримувати кожен кінцевий статус (delivered або failed) як запит 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Невідомий ідентифікатор або кінцева точка.
409not_scheduledСкасувати можна лише заплановану розсилку, яка ще не почалася.
413too_many_recipientsПонад 10,000 номерів в одному запиті.
429rate_limitedПонад 300 запитів за хвилину.
500server_errorПовторіть запит; нічого не списано.

Отримайте ключ API в консолі

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

Створити акаунт
Довідник API масових SMS: кінцеві точки REST і вебхуки | BulkSMSOnline