Customer.io
Customer.io — платформа автоматизації маркетингових комунікацій. Готового SMS-каналу для AlphaSMS у ній немає, але на будь-якому тарифі Customer.io вміє викликати зовнішній API дією Send and receive data (у розсилках той самий механізм називається каналом Webhook).
У цій інструкції — як надсилати SMS з кампанії, розсилки або транзакційного повідомлення Customer.io через API AlphaSMS і як отримувати звіти про доставку.
| Напрямок | Як працює |
|---|---|
| Customer.io → AlphaSMS | POST-вебхук із тілом JSON, де type дорівнює sms |
| AlphaSMS → ваша система | Звіт про доставку на адресу з параметра hook |
Що потрібно перед початком
- Активний акаунт AlphaSMS з увімкненою опцією Активувати API — див. Налаштування API.
- API-ключ (крок 1 нижче).
- Ім'я відправника — буквено-цифровий підпис, який абонент бачить замість номера (від 3 до 11 латинських літер і цифр). Телефонний номер як відправника AlphaSMS не використовує.
- Профілі в Customer.io з телефоном у міжнародному форматі
(наприклад,
+380971234567або380971234567).
Крок 1. Створіть API-ключ
У кабінеті AlphaSMS відкрийте Налаштування → API. У таблиці перелічені ключі з датою створення, терміном дії, станом, коментарем і списком дозволених IP.
Натисніть ADD, вкажіть коментар (наприклад, Customer.io), позначте Active і натисніть
EXECUTE.
Повне значення ключа показується один раз — одразу після створення. Скопіюйте його відразу: у таблиці згодом видно лише перші символи.
Для ключа, який використовується в 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.
Налаштування запиту:
| Поле | Значення |
|---|---|
| Method | POST |
| Request URL | https://api-async.alphasms.ua/v1/json |
| Header | Content-Type: application/json |
Використовуйте саме цю адресу для всіх повідомлень із Customer.io. Endpoint асинхронний: він приймає запит у чергу і відповідає миттєво — саме це й потрібно розсильнику, адже 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.
{% 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.
{{delivery_id}}у попередньому перегляді порожній (показуєтьсяunsent) і підставляється в момент відправки. Залиште його: значення має бути унікальним для кожного повідомлення — повтор сприймається як дублікат, і повідомлення не надсилається.- Загортайте текст у блок
captureі виводьте фільтромjson. Фільтр сам ставить лапки та екранує лапки, слеші й керуючі символи, тому емодзі, апострофи та переноси рядків з даних клієнта не зламають JSON. - Не застосовуйте до тексту фільтр
escape— у Customer.io він робить percent-кодування (@перетворюється на%40), і абонент отримає закодований текст. - До атрибутів, яких може не бути в профілі, завжди додавайте
| default: ''. Невизначена змінна для Customer.io — помилка композера (undefined variable: customer.phone), запит іде зі зіпсованим тілом, і API його відхиляє. - Змінні
{{event.*}}існують лише в кампаніях за подією. У розсилці та в кампанії за сегментом вони дають ту саму помилку невизначеної змінної. - Одне повідомлення на профіль. Якщо потрібно надіслати одразу на кілька номерів, додайте об'єкти
в масив
data.
Крок 5. Обробіть відповідь
Endpoint підтверджує, що пакет прийнято в чергу, і повертає ідентифікатор запиту:
{
"request_id": "cf-ray-1234567890-ABC",
"success": true
}
Ідентифікаторів окремих повідомлень у цій відповіді немає — повідомлення ще йде до шлюзу.
request_id повторюється в кожному звіті про доставку, тому його варто зберегти. У розділі
Response дії натисніть Add attributes і зіставте:
| Атрибут journey | Значення |
|---|---|
sms_request_id | response.request_id |
sms_queued | response.success |
Проблеми із самим запитом повертаються справжніми HTTP-кодами:
| Код | Що означає |
|---|---|
400 | Невалідний JSON або порожній/некоректний масив data |
401 | Не передано, порожній або не прийнято auth |
405 | Метод відмінний від POST |
413 | Завелике тіло запиту |
415 | Content-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— ідентифікатор запиту, у якому надійшло повідомлення (асинхронний endpoint).
Запит підписаний: у заголовку 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. Тест і запуск
- Натисніть Send test… у редакторі та підтвердіть запит. Відповідь з'явиться в панелі Preview — це справжній запит, тому з бойовим ключем SMS дійсно піде.
- Перевірте результат у кабінеті: Звіти → API показують повідомлення, його ціну та статус.
- Перемкніть дію в режим Send automatically (кампанії) або завершіть майстер розсилки.
- Жорсткого ліміту запитів на секунду немає. Якщо плануються сплески в десятки тисяч повідомлень, попередьте підтримку заздалегідь — пропускну здатність акаунта переглянуть.
- Customer.io обриває вебхук через 16 секунд. Наш API відповідає завідомо швидше.
- Додайте в тригер або аудиторію кампанії умову за телефоном (наприклад, phone exists), щоб профілі без номера взагалі не доходили до вебхука.
Інші канали
Тим самим вебхуком надсилаються Viber, RCS, WhatsApp і голосові дзвінки, зокрема каскадом:
наприклад, спочатку Viber, а SMS — тільки якщо Viber не доставлено. Змінюється type і додаються
параметри каналу:
type | Результат |
|---|---|
viber | Viber-повідомлення |
viber+sms | Viber з досилкою SMS |
rcs+sms | RCS з досилкою SMS |
voice | Голосовий дзвінок |
hlr | Перевірка номера — оператор, роумінг і переносимість, без відправки повідомлення |