Пропустить к содержимому
smsbulk

API массовой рассылки SMS v1

Небольшой REST API для отправки массовых SMS из вашего программного обеспечения: JSON на вход и выход, Bearer-ключи, те же цены и проверки, что и в консоли, а также подписанные вебхуки для отчетов о доставке. Базовый URL https://smsbulk.cc/rest/v1

Обзор

Отправляйте до 8,000 номеров в одном запросе, каждый со своими значениями для подстановки, и API рассчитывает стоимость для каждого получателя с его объединенным текстом, точно так же, как и консоль. Сначала запросите расчет с тем же текстом, чтобы узнать стоимость; расчет не отправляет и не списывает средства. Время указывается в формате ISO 8601 в UTC, деньги, строка в долларах США с пятью знаками после запятой.

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

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

Создайте ключ в консоли в разделе API и вебхуки; ключи становятся доступны после первого пополнения баланса. Отправляйте его в каждом запросе как Bearer-токен. Ключ показывается один раз; вы можете хранить до 5 ключей и отозвать любой из них в любой момент.

Authorization: Bearer smsb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Тарифы

Публичный, ключ не требуется. Цена за сегмент SMS для каждого направления или для одного кода 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"
}

Баланс

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

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

Расчет

Рассчитывает стоимость отправки без фактической отправки. Принимает те же данные, что и Send.

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

ПолеЗначение
toОдин номер или список. Международный формат с + наиболее безопасен; локальные номера требуют default_country.
recipientsВместо to: список { to, fields }, где fields заполняют поля слияния, такие как {{name}}.
textСообщение длиной до 2,000 символов и 10 сегментов после слияния.
default_countryКод ISO, используемый для номеров, записанных без +, например GB. Возвращается к значению по умолчанию, сохранённому в Настройках.
opt_outДобавляет сохранённый текст отказа в последнюю строку (сначала сохраните его в Настройках).
{
  "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": []
}

Отправка

Создает кампанию, списывает общую сумму с вашего баланса и ставит сообщения в очередь. Возвращает код 201 с данными кампании. Номера, которые нельзя отправить, перечислены в left_out и не списываются.

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

ПолеЗначение
to / recipients / text / default_country / opt_outКак в Quote.
send_atВремя начала в формате ISO 8601, от 5 минут до 90 дней вперёд. Оставьте пустым, чтобы отправить сейчас.
nameВаша метка для кампании, до 80 символов.
client_refВаш собственный идентификатор, до 64 символов, возвращается в каждом сообщении и вебхуке.
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": []
}

Кампании

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}

Одна кампания включает количество сообщений по статусам: в очереди, отправлено, доставлено, не доставлено и отменено. Списки сообщений страничные с параметрами after и has_more; до 1,000 на странице.

Сообщения

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

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

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

Работает до времени начала. Вся стоимость возвращается на ваш баланс одной строкой в журнале, а статус кампании становится отмененным.

Вебхуки

Укажите URL конечной точки в консоли. Мы отправляем POST JSON для message.delivered, message.failed и campaign.done, а также тестовый запрос при нажатии Send test event. Каждое событие содержит четыре заголовка, и любой ответ 2xx в течение 10 секунд считается полученным.

ПолеЗначение
Smsbulk-EventИмя события, например message.delivered.
Smsbulk-DeliveryID доставки, одинаковый при каждом повторе одного события.
Smsbulk-TimestampСекунды Unix, когда эта попытка была подписана.
Smsbulk-Signaturesha256=, за которым следует base64 HMAC-SHA256 от временной метки, новой строки и исходного тела, зашифрованного вашим секретным ключом sbw_.

Доставка пробуется 8 раз: сразу, затем через 1 минуту, 5 минут, 15 минут, 1 час, 3 часа, 6 часов и 12 часов. Каждая попытка отображается в журнале доставки в консоли с ее HTTP-статусом и началом вашего ответа.

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

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

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

Ошибки и ограничения

Ошибки используют HTTP-статус и тело JSON: {"error":{"code":"insufficient_credit","message":"..."}}. Ничего не списывается при неудачном запросе.

ПолеЗначение
400 bad_jsonТело не является JSON.
401 unauthorizedОтсутствующий, некорректный или отозванный ключ.
402 insufficient_creditОбщая сумма превышает ваш баланс. Пополните средства в консоли.
404 not_foundТакой конечной точки, кампании, сообщения или кода ISO нет в этом аккаунте.
409 not_scheduledЗапрос на отмену был сделан для кампании, которая уже началась.
422 text_missing, text_too_long, too_many_segmentsСообщение пустое, превышает 2,000 символов или 10 сегментов для одного получателя.
422 no_recipients, too_many, recipients_missingНет доступного номера, больше 8,000 номеров или отсутствуют получатели.
422 schedule_range, bad_send_atsend_at выходит за пределы от 5 минут до 90 дней или указано неверное время.
422 opt_out_unsetopt_out установлен в true, но текст для отписки не сохранен в Настройках.
429 rate_limitedБолее 300 запросов в минуту для этого ключа.

Каждый ответ содержит X-RateLimit-Limit, X-RateLimit-Remaining и X-RateLimit-Reset.

Исключенные коды

Номера, удалённые перед расчётом стоимости, возвращаются в left_out с их позицией в вашем списке, значением, которое вы отправили, кодом и простой причиной.

ПолеЗначение
no_country_codeНет + и не указана страна по умолчанию.
too_short / too_longМеньше 8 или больше 15 цифр.
not_a_numberБуквы или символы, которые не являются частью номера.
nanp_lengthНомер +1 без одиннадцати цифр.
not_coveredНаправление за пределами нашего списка.
duplicateЭтот номер уже встречался ранее в запросе.
suppressedНомер находится в вашем списке исключений.

Статусы и причины

ПолеЗначение
queuedОжидание выхода из нашей очереди.
sentПередано в сеть, ожидание отчета о доставке. Большинство отчетов поступают в течение нескольких минут; некоторые сети занимают до 24 часов.
deliveredСеть подтвердила, что телефон получил сообщение.
failedНе доставлено. Стоимость возвращена на ваш баланс.
canceledНе отправлено, так как вы отменили. Возвращено.
ПолеЗначение
network_errorОшибка сети
switched_offТелефон выключен или вне зоны покрытия
not_in_serviceНомер не обслуживается
blockedЗаблокировано сетью или получателем
landlineСтационарный телефон или номер, который не может принимать SMS
content_filterОтклонено фильтром контента сети
expiredИстекло: нет отчета до временного лимита сети
unknownНеизвестный ответ сети
canceledОтменено до отправки

Вопросы по API? Откройте тикет в консоли или прочитайте FAQ.

Документация Bulk SMS API v1: Отправка, Расчёт, Вебхуки | SMSBulk