Разработчикам

Справочник API

Одна конечная точка для отправки, одна для чтения статуса, вебхуки с HMAC-подписью для уведомлений. Ключи выдаются в момент создания аккаунта — одобрять нечего и писать по почте некому.

v1https://api.worldsms.io/v1

Начало работы

Между новым аккаунтом и доставленным сообщением стоят всего три вещи: токен, средства на балансе и ключ. Ни одна из них не требует участия человека.

  1. Создайте аккаунт — ваш браузер генерирует токен, и этот токен и есть аккаунт.
  2. Пополните его. Минимум $40, любой из монет на страница платежей.
  3. Создайте API-ключ в личном кабинете. Он показывается один раз; мы храним только его хеш, точно так же, как токен.

Ключ с пустым балансом не может отправлять

Создание ключа намеренно заблокировано, пока аккаунт не пополнен. Неиспользуемый ключ, лежащий без дела, — это риск без всякой пользы, поэтому личный кабинет не выдаст его, пока не появится что тратить.

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

Токен доступа при каждом запросе. Ключ идентифицирует аккаунт; нет ни второго фактора, ни подписи запроса, ни списка разрешённых IP-адресов — ключ является единственным учётным данным, так к нему и относитесь.

Authorization
Authorization: Bearer ws_live_9f2c…
ТранспортТолько HTTPS. Запрос по обычному HTTP отклоняется, а не перенаправляется — перенаправление уже раскрыло бы ключ.
ОбластьОдин ключ расходует баланс одного аккаунта. Создавайте отдельный ключ для каждой системы, которая отправляет сообщения, — тогда утечку можно отозвать точечно.
ОтзывМгновенно. Отозванный ключ возвращает 401 при следующем запросе; уже принятые рассылки в процессе отправки всё равно завершатся.
ВосстановлениеНикаких. Мы храним только хеш. Утерянный ключ заменяется, а не восстанавливается.

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

POST/v1/messages

Один вызов, один или несколько получателей, разные направления в одном запросе. Каждый получатель тарифицируется по ставке своего направления и списывается за сегмент. Вызов принимается или отклоняется целиком; частичного списания не бывает.

Тело запроса

ПолеТипЗаметки
tostring[]Обязательно. E.164, до 5 000 за один вызов. Номера, не соответствующие ни одному тарифицируемому направлению, отклоняются до списания средств.
textstringОбязательно. UTF-8. Количество сегментов считается по GSM 03.38 — см. сегменты.
fromstringБуквенно-цифровое имя отправителя, до 11 символов. Передаётся там, где это позволяет маршрут; см. имена отправителя.
varsobject[]Необязательные значения для подстановки, по одному объекту на получателя, вставляются в плейсхолдеры {{name}} до подсчёта сегментов.
callback_urlstringНеобязательное переопределение вебхука аккаунта для отдельного пакета.
referencestringНеобязательно. Возвращается в каждом отчёте, чтобы вы могли сопоставить его со своими записями.

Пример

send.sh
# one call, many recipients, mixed destinations
curl -X POST https://api.worldsms.io/v1/messages \
  -H "Authorization: Bearer $WORLDSMS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "ACME",
    "to":   ["+447700900123", "+33612345678"],
    "text": "Your code is 480913"
  }'
202 Accepted
{
  "batch_id": "b_7Kq2xR9wLm",
  "accepted": 2,
  "rejected": 0,
  "segments": 1,
  "cost_usd": 0.0353
}

0,0137 $ на направление Великобритания плюс 0,0216 $ на направление Франция — тарифы применяются по каждому направлению отдельно, а не как усреднённое значение.

Группировка

Пакет принимается немедленно; количество сообщений в минуту на аккаунт — 200, поэтому при количестве получателей 50 000 время составит около 4 ч 10 мин.

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

GET/v1/messages/{batch_id}

Опрос поддерживается и ограничен по частоте; предполагаемый путь — вебхуки. Ответ сводит пакет воедино и перечисляет статус по каждому получателю.

200 OK
{
  "batch_id":    "b_7Kq2xR9wLm",
  "status":      "done",
  "sending":     0,
  "delivered":   1,
  "undelivered": 1,
  "refund_usd":  0.0216
}

refund_usd рассчитывается один раз, когда рассылка завершается. К моменту, когда вы это увидите, средства уже вернулись на баланс.

Баланс

GET/v1/balance

Проверяйте перед крупной рассылкой. Внутри баланс хранится в целых микродолларах — тарифы указываются с точностью до четырёх знаков, а числу с плавающей точкой не место в журнале операций — а здесь возвращается округлённым до шести знаков.

200 OK
{ "balance_usd": 412.905400, "currency": "USD" }

Отчёты о доставке

Отчёт формируется по каждому получателю по мере поступления данных от оператора. Это единственные четыре состояния; нет никакой скрытой категории «неизвестно», которая на деле означала бы «мы его потеряли».

СтатусЗначениеСписано
queuedПринято и ожидает своей очереди в пакете.Да
sentПередано оператору, подтверждения ещё нет.Да
deliveredТелефон подтвердил получение.Да
undeliveredНомер недействителен, заблокирован, либо отправитель отклонён.Возвращено

Номера, которые не относятся ни к одному тарифицируемому направлению, отклоняются при отправке и вообще не попадают в этот жизненный цикл — они не списываются с последующим возвратом, они просто не списываются.

Вебхуки

Задайте адрес в личном кабинете или для каждого пакета через callback_url. Мы отправляем JSON POST-запросом и ожидаем 2xx в течение 5 секунд. Если код ответа не 2xx, запрос повторяется шесть раз с экспоненциальной задержкой в течение примерно часа, а затем отбрасывается.

Полезная нагрузка

POST на ваш эндпоинт
{
  "event":     "message.delivered",
  "batch_id":  "b_7Kq2xR9wLm",
  "to":        "+447700900123",
  "destination": "gb",
  "segments":  1,
  "cost_usd":  0.0137,
  "reference": "order-4471",
  "ts":        1785312041
}

Проверка подписи

Каждая доставка несёт X-WorldSMS-Signature и X-WorldSMS-Timestamp. Подпись — HMAC-SHA256(timestamp + "." + body) с использованием вашего секрета вебхука. Сравнивайте за постоянное время и отклоняйте метку времени старше пяти минут, чтобы перехваченную доставку нельзя было воспроизвести позже.

verify.php
// $secret is the webhook secret from the dashboard
$raw  = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_WORLDSMS_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_WORLDSMS_SIGNATURE'] ?? '';

// A stale timestamp is a replay, however well it is signed.
if (abs(time() - (int) $ts) > 300) { http_response_code(408); exit; }

$mine = hash_hmac('sha256', $ts . '.' . $raw, $secret);
if (!hash_equals($mine, $sig)) { http_response_code(401); exit; }

http_response_code(204);

Быть идемпотентным

Повторная попытка после тайм-аута вашего эндпоинта выглядит так же, как первая доставка. Используйте ключ batch_id + to + event и обрабатывайте повтор как отсутствие действия.

Ошибки

Каждая ошибка возвращает тело JSON со стабильным идентификатором error. Сверяйтесь по идентификатору, а не по тексту описания — текст может меняться в лучшую сторону.

HTTPСлагЧто делать
400invalid_bodyНекорректный JSON или отсутствует обязательное поле.
401key_rejectedКлюч отсутствует, отозван или введён с опечаткой. Повтор невозможен.
402insufficient_creditПакет стоит больше, чем есть на балансе. Ничего не отправлено; пополните счёт и отправьте заново.
422no_valid_recipientsНи один номер не удалось привязать к тарифицируемому направлению.
422sender_id_invalidfrom длиннее 11 символов или содержит строку только из цифр, которая будет прочитана как число.
429rate_limitedСнизьте частоту запросов. Retry-After содержит число секунд.
503route_unavailableНаправление временно недоступно для маршрутизации. Можно повторить.
402 Payment Required
{
  "error":       "insufficient_credit",
  "message":     "Batch costs $84.20, balance is $12.05.",
  "required_usd": 84.20,
  "balance_usd":  12.05
}

Лимиты

Запросы60 в минуту на ключ, всплеск 20. Сверх этого — 429 с Retry-After.
Получателей за вызов5 000. Разбейте более длинные списки на несколько вызовов либо загрузите файл в личном кабинете.
Размер сообщения2 MB.
Пропускная способность200 сообщений в минуту на аккаунт, независимо от того, сколько ключей отправляет.
КлючиБез ограничений. Предполагаемая схема — один на систему отправки.

Лимиты применяются к вызовам API, а не к сообщениям: один вызов с 5000 получателей расходует один запрос из лимита.

Ключи выдаются мгновенно. Этап одобрения отсутствует.

Пополните аккаунт — и личный кабинет создаст его сразу же.

Задать конкретный вопрос

Создайте аккаунт

Одна кнопка. Ваш браузер генерирует 160-битный токен, и этот токен и есть аккаунт. Больше ничего заполнять не нужно и ждать некого.

РусскийRU · Сменить язык

Язык