01Возможности API
Шесть методов охватывают весь продукт.
Все действия из панели доступны и через API.
| Метод | Путь | Назначение |
|---|---|---|
| POST | /v1/messages | Отправьте одно сообщение. Возвращает идентификатор, цену и начальный статус. |
| POST | /v1/messages/batch | Отправляйте до 1000 сообщений за один запрос, каждое со своим текстом и отправителем. |
| GET | /v1/messages/{id} | Текущий статус, код оператора, временные метки и стоимость одного сообщения. |
| GET | /v1/messages | Составляйте список и фильтруйте сообщения: статус, направление, кампания, диапазон дат. Разбивка на страницы. |
| GET | /v1/rates | Полная таблица тарифов в JSON или данные одной страны через /v1/rates/{iso}. |
| GET | /v1/balance | Баланс в долларах США, ожидающие пополнения и установленный вами порог низкого баланса. |
02Жизненный цикл сообщения
Шесть однозначных статусов.
Статус сообщения меняется только вперёд. На этот порядок можно полагаться и при опросе API, и при получении вебхуков.
- Вебхуки сообщают о каждом изменении статуса и передают код оператора, если он есть.
- Срок действия - это 48 часов. После этого срок действия недоставленного сообщения истекает.
- Списание происходит при передаче сообщения оператору. Отклонённые сообщения не оплачиваются.
- В очередиПринято, оценено, ожидание слота маршрута.
- ОтправленоПередано оператору связи. В этот момент списывается плата.
- ДоставленоУстройство получателя подтвердило доставку. Конечный статус.
- ОшибкаОператор связи не смог доставить сообщение. Указан код ошибки. Конечный статус.
- Срок истёкСообщение не доставлено до истечения срока действия. Конечный статус.
- ОтклоненоСообщение отклонено до отправки: неверный номер, запрещённое содержимое или недостаточный баланс. Плата не списывается. Конечный статус.
03Ошибки
Стабильный код, понятное описание и имя проблемного поля.
Все ответы вне диапазона 2xx имеют одинаковую структуру JSON. После 429 и 5xx повторите запрос; при 4xx исправьте данные и отправьте снова.
| HTTP | Код | Значение | Что делать |
|---|---|---|---|
| 400 | invalid_number | Номер получателя не соответствует формату E.164. | Приведите номер к международному формату; в ответе указано проблемное поле. |
| 401 | unauthorized | Ключ отсутствует, отозван или не разрешён для этого IP-адреса. | Проверьте ключ и список разрешённых IP-адресов в панели. |
| 402 | insufficient_balance | После отправки баланс стал бы отрицательным. | Пополните счёт. Чтобы получать предупреждения заранее, настройте вебхук низкого баланса. |
| 409 | idempotency_conflict | Тот же ключ идемпотентности повторно использован с другим телом запроса. | Используйте новый ключ для нового сообщения. |
| 422 | unsupported_destination | Для этой страны или префикса нет маршрута. | Проверьте страницу покрытия направления. |
| 422 | sender_not_allowed | Указанное буквенно-цифровое имя отправителя не разрешено на этом маршруте. | Не передавайте поле from: числовой отправитель будет назначен автоматически. |
| 429 | rate_limited | Превышен лимит 50 запросов в секунду на ключ. | Подождите время из заголовка Retry-After или используйте пакетную отправку. |
| 5xx | internal | Ошибка на стороне сервиса. Сообщение не отправлено. | Повторите попытку с тем же ключом идемпотентности. |
04Примеры
Скопируйте, вставьте и замените ключ.
Один запрос на самых популярных языках. Каждый пример включает ключ идемпотентности, который защитит от повторной отправки при сетевом сбое.
import requests
r = requests.post(
"https://api.smsmeteor.com/v1/messages/batch",
headers={"Authorization": f"Bearer {KEY}",
"Idempotency-Key": "batch-2026-09-21-01"},
json={"messages": [
{"to": "+14155550142", "from": "METEOR", "text": "Заказ №4821 отправлен."},
{"to": "+447700900123", "from": "METEOR", "text": "Заказ №4822 отправлен."},
]},
)
for m in r.json()["messages"]:
print(m["id"], m["status"], m["price"])
const r = await fetch("https://api.smsmeteor.com/v1/messages/batch", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SMSMETEOR_KEY}`,
"Idempotency-Key": "batch-2026-09-21-01",
"Content-Type": "application/json",
},
body: JSON.stringify({ messages: [
{ to: "+14155550142", from: "METEOR", text: "Заказ №4821 отправлен." },
{ to: "+447700900123", from: "METEOR", text: "Заказ №4822 отправлен." },
]}),
});
const { messages } = await r.json();
$ch = curl_init("https://api.smsmeteor.com/v1/messages/batch");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer $key",
"Idempotency-Key: batch-2026-09-21-01", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["messages" => [
["to" => "+14155550142", "from" => "METEOR", "text" => "Заказ №4821 отправлен."],
["to" => "+447700900123", "from" => "METEOR", "text" => "Заказ №4822 отправлен."],
]]),
]);
$res = json_decode(curl_exec($ch), true);
body, _ := json.Marshal(map[string]any{"messages": []map[string]string{
{"to": "+14155550142", "from": "METEOR", "text": "Заказ №4821 отправлен."},
{"to": "+447700900123", "from": "METEOR", "text": "Заказ №4822 отправлен."},
}})
req, _ := http.NewRequest("POST", "https://api.smsmeteor.com/v1/messages/batch", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("SMSMETEOR_KEY"))
req.Header.Set("Idempotency-Key", "batch-2026-09-21-01")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
{ "batch_id": "bat_3Hq9Zr", "accepted": 2, "rejected": 0,
"total_price": "0.0214", "currency": "USD",
"messages": [ { "id": "msg_9Kd2fQ", "status": "queued", "price": "0.0084" },
{ "id": "msg_9Kd2fR", "status": "queued", "price": "0.0130" } ] }
05Вопросы, ответы
Что спрашивают разработчики перед первым запросом.
Как получить ключ API?
Создайте ключ в разделе «Разработчики» панели. Токен показывается один раз; ему можно выдать права на отправку, чтение или оба действия и ограничить список разрешённых IP-адресов. Ключ можно отозвать или заменить в любое время без изменений баланса.
Использует ли API тот же баланс и тарифы, что и панель?
Да. Один аккаунт, общий баланс и единая таблица тарифов. Сообщение из API стоит ровно столько, сколько указано для соответствующего направления, и попадает в те же отчёты.
Каков предел скорости?
50 запросов в секунду на ключ для одиночных отправок. Метод пакетной отправки принимает 1000 сообщений в одном запросе API, поэтому для миллиона сообщений достаточно тысячи запросов. При превышении лимита API возвращает 429 с заголовком Retry-After.
Что делает ключ идемпотентности?
Отправьте тот же ключ идемпотентности с повторным запросом, и API вернёт исходный ответ вместо отправки второго сообщения. Ключи хранятся 24 часа для каждого аккаунта.
Как узнать, доставлено ли сообщение?
Запросите <code>GET /v1/messages/{id}</code> или зарегистрируйте вебхук и получайте события <code>message.delivered</code> и <code>message.failed</code> с кодом оператора. Для любого заметного объёма рекомендуем вебхуки.
Есть ли песочница?
В каждом аккаунте есть тестовый ключ. Запросы с ним проходят проверку и расчёт цены и возвращают статус test, но сообщения не покидают платформу и средства не списываются.
Какие языки вы поддерживаете?
Любой язык, который может выполнить запрос HTTPS. Мы публикуем готовые примеры для cURL, Python, Node, PHP и Go, а также описание OpenAPI, если вы предпочитаете создавать клиента.
Где описаны ошибки?
Каждый ответ об ошибке содержит стабильный код JSON, понятное сообщение и, при необходимости, имя поля, вызвавшего ошибку. Полный список приведён в справочнике API, а самые распространённые ошибки — на этой странице.
06Больше продуктов
Всё остальное в наборе инструментов.
Один аккаунт, общий баланс и единая таблица тарифов. Все перечисленные возможности включены без дополнительной платы.
Посмотреть тарифы- Массовые SMS-кампанииЗагрузите список, напишите один раз, разошлите миллионам.
- ПланированиеОкна доставки по местному времени для каждого направления.
- Идентификатор отправителя и маршрутыБуквенно-цифровые, числовые или общие отправители.
- Отчёты о доставкеСтатус каждого сообщения и экспорт одним нажатием.
- ВебхукиСобытия доставки передаются на адрес вашего обработчика.