Документация SMS API для отправки из вашего кода

Небольшой REST API на том же аккаунте, с теми же ценами и балансом, что и в рабочем пространстве: отправляйте сообщение или пакет до 5,000 номеров, сначала оцените стоимость, отслеживайте каждое сообщение и получайте события доставки по вашему URL вебхука.

Базовый URL: https://sendsmsonline.cc/api/v1

Быстрый старт

  1. 1. Создайте ключ. В рабочем пространстве откройте API и вебхуки. Ключи становятся доступны после первого пополнения баланса; каждый ключ показывается один раз, поэтому скопируйте его или сохраните как текстовый файл.
  2. 2. Проверьте стоимость. Отправьте POST с тем же телом на /costs, чтобы увидеть получателей, сегменты и общую стоимость без отправки.
  3. 3. Отправьте. Отправьте POST на /sends. В ответе будет идентификатор рассылки; сообщения отправляются сразу или в send_at.
curl https://sendsmsonline.cc/api/v1/sends \
  -H "Authorization: Bearer $SSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "recipients": [ { "to": "+447700900461", "fields": { "first_name": "Tom" } }, { "to": "+12015550142", "fields": { "first_name": "Ava" } } ], "text": "Hi {{first_name}}, your table is ready at 7:30.", "name": "Friday bookings", "client_ref": "bookings-1107" }'

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

Отправьте ваш ключ в заголовке Authorization: Authorization: Bearer sso_live_.... Ключи состоят из 49 символов и начинаются с sso_live_. До 5 ключей на аккаунт; отзовите один в рабочем пространстве, и он перестанет работать сразу. Прайс-лист публичный и не требует ключа.

Ошибки

Ошибки используют HTTP статус-коды и JSON тело с устойчивым кодом и предложением, которое можно показать человеку. Ничего не списывается, если запрос завершается ошибкой.

HTTP/1.1 402 Payment Required
{ "error": { "code": "insufficient_credit", "message": "Short by $3.20. Add funds to send.", "total": "8.62480", "credit": "5.42000" } }
ПолеЗначение
400Запрос требует изменений.
401Отсутствующий, неправильный или отозванный ключ.
402Недостаточно средств на балансе для общей суммы.
404Нет такой рассылки, сообщения, страны или конечной точки.
409Отправка уже началась.
429Более 240 запросов в минуту.

Лимиты

  • 240 запросов в минуту на ключ, отображается в X-RateLimit-Limit, X-RateLimit-Remaining и X-RateLimit-Reset (в секундах Unix).
  • 5,000 номеров на запрос, 2,000 символов на текст, 10 сегментов на сообщение.
  • Сообщения отправляются до 300 в минуту на аккаунт.
  • send_at от 10 минут до 30 дней вперед.

Цены

GET/api/v1/prices

GET/api/v1/prices/{country}

Цена за сообщение (один сегмент) для каждой страны, в USD с 5 знаками после запятой. Ключ не требуется.

{ "price": { "country": "GB", "name": "United Kingdom", "dial_code": "+44", "price_usd": "0.00868" }, "updated": "2026-11-07" }

Баланс аккаунта

GET/api/v1/account

{ "account": "SO8K2M4Q7X9TBA", "credit_usd": "41.27660", "currency": "USD" }

Оценить стоимость

POST/api/v1/costs

Принимает те же данные, что и отправка, и возвращает стоимость, не отправляя и не списывая средства. Текст каждого получателя определяет количество сегментов, поэтому сумма точна.

{
  "recipients": 2, "segments_min": 1, "segments_max": 1, "encoding": "gsm7", "messages_billed": 2,
  "total_usd": "0.01426", "credit_usd": "41.27660", "enough_credit": true,
  "countries": [ { "country": "GB", "recipients": 1, "price_usd": "0.00868", "subtotal_usd": "0.00868" },
                 { "country": "US", "recipients": 1, "price_usd": "0.00558", "subtotal_usd": "0.00558" } ],
  "dropped": [], "too_long": null
}

Создать рассылку

POST/api/v1/sends

Один текст на один или несколько номеров. Средства за всю отправку списываются при ее принятии; неудачные сообщения возвращаются по одному.

ПолеЗначение
toНомера в международном формате (+447700900461). Используйте это или получателей.
recipientsОбъекты с to и fields, для полей слияния: { "to": "+1...", "fields": { "first_name": "Ava" } }.
textСообщение длиной до 2,000 символов. {{field}} заменяется для каждого получателя; отсутствующие значения становятся пустыми.
send_atНеобязательное время в формате ISO 8601 со смещением или Z. Без него отправка начинается сразу.
nameНеобязательная метка, отображаемая в рабочем пространстве (80 символов).
client_refНеобязательная ссылка, возвращаемая в вебхуках (64 символа).
opt_outДобавляет строку отказа от подписки, сохраненную в Настройках, в конец текста.
default_countryКод ISO используется для номеров, написанных без кода страны.
HTTP/1.1 201 Created
{
  "send": { "id": "CA7Q29XMAB4DFK", "status": "queued", "source": "api", "recipients": 2, "segments_max": 1,
            "encoding": "gsm7", "cost_usd": "0.01426", "refunded_usd": "0.00000", "client_ref": "bookings-1107",
            "send_at": null, "created_at": "2026-11-07T10:12:03.120Z", "started_at": null, "finished_at": null },
  "dropped": [ { "value": "+4412", "code": "too_short", "message": "Too short" } ]
}

Номера, которые нельзя отправить, перечислены в dropped и никогда не списываются. Коды: no_country_code, too_short, too_long, not_a_number, wrong_length, not_covered, duplicate и suppressed (в вашем списке запрещенных для отправки).

Получить или список рассылок

GET/api/v1/sends/{id}

GET/api/v1/sends?limit=25&before={id}

Одна отправка включает counts по статусу сообщения. Списки отсортированы от новых к старым; передайте next_before как before для следующей страницы. Отправки из рабочего пространства также отображаются здесь с source: "web".

Сообщения

GET/api/v1/sends/{id}/messages?status=failed&limit=100

GET/api/v1/messages/{id}

{ "message": { "id": "MS3D8RW0K2QJ7N", "send_id": "CA7Q29XMAB4DFK", "to": "+447700900461", "country": "GB",
  "segments": 1, "price_usd": "0.00868", "status": "delivered", "reason": null, "reason_text": null,
  "created_at": "2026-11-07T10:12:03.120Z", "sent_at": "2026-11-07T10:12:04.010Z", "done_at": "2026-11-07T10:12:09.400Z" } }

Отменить рассылку

POST/api/v1/sends/{id}/cancel

Только запланированные отправки, которые еще не начались, могут быть отменены. Полная стоимость возвращается на ваш баланс, и ответ включает refunded_usd.

Вебхуки

Установите HTTPS URL в рабочем пространстве (API и вебхуки). Мы отправляем POST-запрос с событием, когда сообщение доставлено или не доставлено, для отправок как через API, так и через рабочее пространство. Ответьте с любым статусом 2xx в течение 10 секунд. Неудачные доставки повторяются до 7 раз: сразу, затем через 1 минуту, 5 минут, 30 минут, 1 час, 2 часа и 3 часа. Рабочее пространство показывает каждую попытку с ее статусом и ответом.

POST https://your-server.example/sms-events
X-SSO-Event: message.delivered
X-SSO-Delivery: evt_5a0c9e31d2b7f4a68c
X-SSO-Timestamp: 1794132729
X-SSO-Signature: sha256=8f1c...e42a

{ "id": "evt_5a0c9e31d2b7f4a68c", "event": "message.delivered", "created": "2026-11-07T10:12:09.000Z",
  "data": { "message": { "id": "MS3D8RW0K2QJ7N", "send_id": "CA7Q29XMAB4DFK", "to": "+447700900461", "country": "GB",
  "segments": 1, "price_usd": "0.00868", "status": "delivered", "reason": null, "reason_text": null,
  "client_ref": "bookings-1107", "created_at": "...", "sent_at": "...", "done_at": "..." } } }

Подпись, это HMAC-SHA256 от timestamp + "." + raw body с вашим секретным ключом подписи (он начинается с sso_whk_). Проверьте ее на сыром теле перед разбором, отклоните временные метки старше 5 минут и используйте идентификатор доставки, чтобы игнорировать повторы.

import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string), before JSON.parse
export function verify(rawBody, headers, secret) {
  const ts = headers["x-sso-timestamp"];
  const sig = headers["x-sso-signature"] || "";
  const want = "sha256=" + crypto.createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && sig.length === want.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(want));
}

События: message.delivered, message.failed и test с кнопки Отправить тестовое событие.

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

ПолеЗначение
queuedОжидание выхода из нашей очереди.
sentПередано оператору, ожидается отчет о доставке. Большинство отчетов приходят в течение нескольких минут; некоторые операторы могут задерживать до 24 часов.
deliveredОператор подтвердил получение сообщения на телефон.
failedНе доставлено. Стоимость возвращена на ваш баланс.
canceledНе отправлено, так как вы отменили. Возвращено.

Причины неудачи (поле reason):

ПолеЗначение
network_errorОшибка сети
absentТелефон выключен или вне зоны покрытия
not_in_serviceНомер не обслуживается
blockedЗаблокировано оператором или получателем
landlineСтационарный телефон или номер, не принимающий SMS
content_filterОтклонено фильтром контента оператора
expiredИстекло: отчет не получен в срок оператора
canceledОтменено до отправки
unknownНеизвестный ответ оператора

Проверки сервиса на странице статуса, изменения API в истории обновлений.

Получить API-ключ

Создайте аккаунт, пополните баланс один раз и откройте доступ к API и вебхукам в рабочем пространстве. Один ключ работает для всех стран.

Создать бесплатный аккаунт
Документация SMS API: Отправка массовых SMS из вашего кода | SendSMSOnline