Перейти к основному содержимому

Customer.io

Customer.io — платформа автоматизации маркетинговых коммуникаций. Готового SMS-канала для AlphaSMS в ней нет, но на любом тарифе Customer.io умеет вызывать внешний API действием Send and receive data (в рассылках тот же механизм называется каналом Webhook).

В этой инструкции — как отправлять SMS из кампании, рассылки или транзакционного сообщения Customer.io через API AlphaSMS и как получать отчёты о доставке.

НаправлениеКак работает
Customer.io → AlphaSMSPOST-вебхук с телом JSON, где type равен sms
AlphaSMS → ваша системаОтчёт о доставке на адрес из параметра hook

Что нужно перед началом

  1. Активный аккаунт AlphaSMS с включённой опцией Активировать API — см. Настройки API.
  2. API-ключ (шаг 1 ниже).
  3. Имя отправителя — буквенно-цифровая подпись, которую абонент видит вместо номера (от 3 до 11 латинских букв и цифр). Телефонный номер в качестве отправителя AlphaSMS не использует.
  4. Профили в Customer.io с телефоном в международном формате (например, +380971234567 или 380971234567).

Шаг 1. Создайте API-ключ

В кабинете AlphaSMS откройте Настройки → API. В таблице перечислены ключи с датой создания, сроком действия, состоянием, комментарием и списком разрешённых IP.

image1

Customer.io - фото 1

Нажмите ADD, укажите комментарий (например, Customer.io), отметьте Active и нажмите EXECUTE.

image2

Customer.io - фото 2

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

image3

Customer.io - фото 3

внимание

Для ключа, который используется в Customer.io, оставьте поле IP whitelisting пустым. Customer.io отправляет вебхуки с большого и меняющегося пула адресов, поэтому фиксированный список IP рано или поздно начнёт отбивать трафик ошибкой Access denied. Лучше завести для Customer.io отдельный ключ — его можно отозвать, не задев другие интеграции.

Шаг 2. Выберите имя отправителя

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

Ограничения приходят только со стороны сети получателя: часть операторов и стран принимает буквенно-цифровые имена лишь после регистрации и может отклонить или подменить незнакомое имя. Уточните у поддержки направления, на которые вы планируете слать.

Имена, которые уже используются на аккаунте, видны в кабинете — см. Имя отправителя.

Шаг 3. Добавьте вебхук в Customer.io

  • Кампания (journey) — откройте workflow, перетащите блок Send and receive data и нажмите Add Request.
  • Рассылка (broadcast) — на шаге Content выберите канал Webhook и нажмите Add content.

image4

Customer.io - фото 4

Настройки запроса:

ПолеЗначение
MethodPOST
Request URLhttps://api-async.alphasms.ua/v1/json
HeaderContent-Type: application/json
внимание

Используйте именно этот адрес для всех сообщений из Customer.io. Эндпоинт асинхронный: он принимает запрос в очередь и отвечает мгновенно — ровно это и нужно рассыльщику, потому что Customer.io делает по вебхуку на каждый профиль и кампания легко порождает сотни параллельных запросов.

Заголовки X-CIO-Idempotency-Key и X-CIO-Signature Customer.io добавляет сам. Отдельный заголовок авторизации не нужен — API AlphaSMS авторизует запрос по полю auth в теле.

Шаг 4. Соберите тело запроса

Вставьте payload ниже в редактор тела и замените YOUR_API_KEY и YOUR_SENDER_ID. Панель Preview справа подставляет данные тестового профиля, поэтому видно точный JSON, который уйдёт в API.

image5

Customer.io - фото 5

{% capture sms_text %}Привет, {{ customer.first_name | default: 'друг' }}! Ваш заказ уже в пути.{% endcapture %}
{
"auth": "YOUR_API_KEY",
"data": [
{
"type": "sms",
"id": "{{delivery_id}}",
"phone": "{{ customer.phone | default: '' | remove: '+' | remove: ' ' | remove: '-' }}",
"sms_signature": "YOUR_SENDER_ID",
"sms_message": {{ sms_text | strip_newlines | json }},
"hook": "https://your-app.example.com/dlr"
}
]
}
ПараметрОбязательныйОписание
authдаВаш API-ключ
typeдаsms. Другие значения включают Viber, RCS, WhatsApp и мультиканальную отправку
idнетВаш идентификатор сообщения, возвращается в каждом отчёте о доставке. {{delivery_id}} — идентификатор конкретной отправки в Customer.io
phoneдаНомер получателя в международном формате, только цифры
sms_signatureдаИмя отправителя
sms_messageдаТекст сообщения
hookнетАдрес, на который придут отчёты о доставке этого сообщения
sms_lifetimeнетСрок жизни сообщения в секундах, от 60 до 259200 (3 суток)
short_linkнетtrue — сокращать и отслеживать ссылки в тексте (согласно тарифу)
unsubscribe_linkнетtrue — добавить ссылку отписки (согласно тарифу)

Полный список параметров — в разделе Отправка SMS.

Про Liquid
  • {{delivery_id}} в предпросмотре пустой (показывается unsent) и подставляется в момент отправки. Оставьте его: значение должно быть уникальным для каждого сообщения — повтор воспринимается как дубликат, и сообщение не отправляется.
  • Оборачивайте текст в блок capture и выводите фильтром json. Фильтр сам ставит кавычки и экранирует кавычки, слэши и управляющие символы, поэтому эмодзи, апострофы и переносы строк из данных клиента не сломают JSON.
  • Не применяйте к тексту фильтр escape — в Customer.io он делает percent-кодирование (@ превращается в %40), и абонент получит закодированный текст.
  • К атрибутам, которых может не быть в профиле, всегда добавляйте | default: ''. Неопределённая переменная для Customer.io — ошибка композера (undefined variable: customer.phone), запрос уходит с испорченным телом, и API его отклоняет.
  • Переменные {{event.*}} существуют только в кампаниях по событию. В рассылке и в кампании по сегменту они дают ту же ошибку неопределённой переменной.
  • Одно сообщение на профиль. Если нужно отправить сразу на несколько номеров, добавьте объекты в массив data.

Шаг 5. Обработайте ответ

Эндпоинт подтверждает, что пакет принят в очередь, и возвращает идентификатор запроса:

{
"request_id": "cf-ray-1234567890-ABC",
"success": true
}

Идентификаторов отдельных сообщений в этом ответе нет — сообщение ещё идёт к шлюзу. request_id повторяется в каждом отчёте о доставке, поэтому его стоит сохранить. В разделе Response действия нажмите Add attributes и сопоставьте:

Атрибут journeyЗначение
sms_request_idresponse.request_id
sms_queuedresponse.success

Проблемы с самим запросом возвращаются настоящими HTTP-кодами:

КодЧто означает
400Невалидный JSON или пустой/некорректный массив data
401Не передан, пуст или не принят auth
405Метод отличается от POST
413Слишком большое тело запроса
415Content-Type не application/json
503Очередь временно недоступна

Customer.io повторяет запросы с кодами 408, 409, 429 и 5xx до 11 раз примерно в течение часа, так что короткий 503 лечится сам. 400, 401 и 415 — ошибки конфигурации, они не повторяются: следите за ними в метриках кампании после запуска.

Принятое сообщение всё ещё может быть отклонено, когда его обработает шлюз. Причина приходит в отчёте о доставке и видна в кабинете в разделе Отчёты → API:

ПричинаЧто означает
Error in Alpha-nameИмя отправителя недопустимо на этом маршруте или у этого оператора
Not enough moneyНедостаточно средств на балансе
Duplicate IDЗначение id уже использовалось на аккаунте — оно должно быть уникальным
Please enter valid receiver phone numberПустой или некорректный phone
Receiver blacklistedНомер в вашем чёрном списке или отписался
SMS is too longТекст превышает максимальную длину
Operator not supportedНет маршрута к этому оператору

Шаг 6. Принимайте отчёты о доставке

Каждое сообщение с параметром hook порождает POST-запрос на этот адрес при каждой смене статуса. Именно там виден итоговый результат отправки, поэтому настройте приём отчётов до запуска кампании.

{
"id": "01HB…",
"msg_id": 123456789,
"type": "sms",
"status": "DELIVERED",
"updated": "2026-08-10T12:34:56+03:00",
"request_id": "cf-ray-1234567890-ABC"
}
  • id — значение, которое вы передали в запросе (в примере выше это delivery_id из Customer.io); по нему отчёт сопоставляется с сообщением.
  • msg_id — идентификатор, присвоенный шлюзом.
  • updated — момент смены статуса, формат YYYY-MM-DDThh:mm:ss±hh:mm.
  • request_id — идентификатор запроса, в котором пришло сообщение (асинхронный эндпоинт).

Запрос подписан: в заголовке X-Signature лежит sha256(json_body + api_key), посчитанный тем же ключом, которым отправлялось сообщение. Запросы с несовпавшей подписью отбрасывайте.

$body = file_get_contents('php://input');
if (!hash_equals(hash('sha256', $body . $apiKey), $_SERVER['HTTP_X_SIGNATURE'] ?? '')) {
http_response_code(403);
exit;
}

Отвечайте кодом 200. Статусы перечислены в справочнике Статусы сообщений; чаще всего встречаются ACCEPTED, QUEUED, DELIVERED, UNDELIVERABLE, EXPIRED, REJECTED.

Общий для аккаунта адрес отчётов можно указать в Настройки → API → URL для отчётов о доставке: он действует на все сообщения аккаунта. Подробнее: Webhook.

Шаг 7. Тест и запуск

  1. Нажмите Send test… в редакторе и подтвердите запрос. Ответ появится в панели Preview — это настоящий запрос, поэтому с боевым ключом SMS действительно уйдёт.
  2. Проверьте результат в кабинете: Отчёты → API показывают сообщение, его цену и статус.
  3. Переключите действие в режим Send automatically (кампании) или завершите мастер рассылки.
Объёмы и аудитория
  • Жёсткого лимита запросов в секунду нет. Если планируются всплески в десятки тысяч сообщений, предупредите поддержку заранее — пропускную способность аккаунта пересмотрят.
  • Customer.io обрывает вебхук через 16 секунд. Наш API отвечает заведомо быстрее.
  • Добавьте в триггер или аудиторию кампании условие по телефону (например, phone exists), чтобы профили без номера вообще не доходили до вебхука.

Другие каналы

Тем же вебхуком отправляются Viber, RCS, WhatsApp и голосовые звонки, в том числе каскадом: например, сначала Viber, а SMS — только если Viber не доставлен. Меняется type и добавляются параметры канала:

typeРезультат
viberViber-сообщение
viber+smsViber с досылкой SMS
rcs+smsRCS с досылкой SMS
voiceГолосовой звонок
hlrПроверка номера — оператор, роуминг и переносимость, без отправки сообщения