SMS
MonoPbx содержит ядро SMS: конфигурации провайдеров, номера, общие входящие (диалоги и сообщения), отправку с отслеживанием доставки, подписанные входящие webhook и подсчёт использования. Настройка выполняется через API (/sms/...); страницы SMS в веб-консоли пока нет.
:::caution Ваша ответственность Соответствие требованиям SMS (согласие, отказ от рассылки, местное законодательство) — ответственность заказчика. Автоматическая обработка ключевых слов STOP и отказа от рассылки запланирована для Beta и пока не активна: обработчики существуют, но по умолчанию ничего не делают. :::
Модель
provider (kind, settings, sealed credentials, webhook address)
└── number (E.164; where its conversations are routed)
└── conversation (company number + remote number)
└── message (inbound or outbound, status, segments)
Состояния сообщения: queued, затем sent, затем delivered, либо failed. Входящие сообщения имеют состояние received.
Провайдеры

Страница провайдеров SMS.
Доступные виды провайдеров зависят от версии; GET /api/v1/sms/providers перечисляет available_kinds. В основной ветке доступны:
- Twilio (
twilio). - Общий HTTP-шаблон (
http_template): любой HTTP-API для SMS, настроенный без кода. Он не обращается к частным, локальным (loopback) и link-local адресам, а также кhttpбез явного разрешения.
POST /api/v1/sms/providers
{"name": "Twilio", "kind": "twilio",
"config": {"public_base_url": "https://pbx.example.com"},
"credentials": {"account_sid": "AC...", "auth_token": "..."}}
Учётные данные зашифровываются ключом компании и никогда не возвращаются; API показывает только auth_configured: true. Обновление учётных данных заменяет все сохранённые. Маршруты, которые передают учётные данные, игнорируют Idempotency-Key.
У каждого провайдера есть адрес webhook вида /hooks/sms/<key> (он показан как webhook_path у провайдера; POST /sms/providers/{id}/webhook-address меняет его, после чего старый адрес отвечает 404). Укажите его у своего провайдера как URL для входящих сообщений и отчётов о доставке. Для Twilio задайте webhook номера «A message comes in» на https://<your address>/hooks/sms/<key> методом HTTP POST. Отчёты о доставке для Twilio не требуют настройки в консоли, так как status callback отправляется с каждым сообщением.
Сам по себе адрес webhook ничего не аутентифицирует. Каждый webhook проверяется по подписи провайдера (X-Twilio-Signature у Twilio или общий HMAC X-Mpbx-Signature) до разбора. Неудачная проверка возвращает 401 MPBX-SMS-WEBHOOK-UNAUTHORIZED. Компания определяется по записи провайдера, найденной по адресу, а не по запросу.
Номера

Страница номеров SMS.
POST /api/v1/sms/numbers добавляет номер в международном формате (+15550100) к провайдеру и задаёт, куда направляются его диалоги (route: пользователь, внутренний номер, очередь или группа вызова; {"kind":"none"} — никуда). Номер можно выключить через enabled: false. Провайдеров и номера, у которых есть история, нельзя удалить; вместо этого их выключают.
Отправка
POST /api/v1/sms/messages {"from": "+15550100199", "to": "+15550100100", "body": "..."}
Ответ — 202 с сообщением в состоянии queued. from должен быть одним из включённых номеров компании; он же выбирает провайдера. Текст — от 1 до 1600 символов. Сегменты считаются так, как их тарифицируют провайдеры: 160 символов в сегменте GSM-7, 70 в сегменте UCS-2, 153 и 67, когда сообщение разбито.
- Постоянный отказ сразу переводит сообщение в состояние failed с кодом провайдера (
MPBX-SMS-PROVIDER-REJECTED, если провайдер его не передал). - Временная ошибка повторяется с удваивающимися задержками, начиная с 30 секунд, до 5 попыток, после чего сообщение переходит в состояние failed с кодом
MPBX-SMS-PROVIDER-UNAVAILABLE. - Доставка выполняется по схеме «как минимум один раз»: в редких случаях сбоя сообщение может быть отправлено дважды.
Читайте входящие через GET /sms/conversations, GET /sms/conversations/{id}/messages, а отметить диалог прочитанным можно через POST /sms/conversations/{id}/read. GET /sms/usage возвращает ежедневное число сообщений и сегментов по провайдерам и направлениям.
Права доступа
| Операция | Право |
|---|---|
| Провайдеры и номера | integrations:read / integrations:write |
| Диалоги, сообщения, отправка, использование | messaging:read / messaging:write |
Оба права проверяются на уровне всей компании. Владелец права, которое у него есть только для некоторых отделов, получает отказ (403), поскольку у диалогов пока нет отдела.
События и аудит
Каждое изменение состояния порождает событие sms.* (sms.queued, sms.sent, sms.delivered, sms.failed, sms.received). Событие содержит идентификаторы, номера, состояние и число сегментов, но никогда не содержит текст сообщения. Изменения провайдеров и номеров записываются в аудит без учётных данных. См. Активность, история и аудит.
Коды ошибок перечислены в репозитории, в файле docs/errors/sms.md.