# Обработка ответов сервера и коды ошибок SMS шлюза: справочник для разработчиков

- Опубликовано: 2026-05-19T14:46:28+00:00
- Обновлено: 2026-05-19T18:49:48+00:00
- Автор: Кира Астахова
- Канонический URL: https://smsblog.ru/sms-rassylki/obrabotka-otvetov-servera-i-kody-oshibok-sms-shlyuza-spravochnik-dlya/

Коды ответов SMS шлюза указывают, успешно ли доставлено сообщение или возникла проблема на уровне HTTP или API. Основные группы: 2xx — успех, 4xx — ошибки клиента (неверные параметры, авторизация), 5xx — ошибки сервера провайдера. Для отладки [sms api](http://smsblog.ru/obzory-i-sravneniya/polnoe-rukovodstvo-po-sms-api-ot-vybora-provaydera-do-integratsii/) необходимо анализировать статус-код, тело ответа и логировать запрос‑ответ полностью.

## Что такое коды ответов SMS шлюза и HTTP ошибки

SMS шлюз взаимодействует через HTTP/HTTPS, поэтому каждый запрос возвращает стандартный статус-код RFC 7231. Помимо него, провайдер добавляет собственный код в теле JSON, который уточняет причину неудачи (например, invalid destination, insufficient balance). Понимание обеих частей позволяет быстро локализовать проблему.

Для большинства провайдеров структура ответа выглядит так:

```
{
  "http_status": 200,
  "provider_code": 0,
  "message_id": "abc123",
  "status": "queued"
}
```

Если http_status не равно 200, рассматривайте его как HTTP‑ошибку sms; если он 200, но provider_code ≠ 0 — это бизнес‑ошибка шлюза.

### Основные категории кодов

- **2xx (успех)**: 200 OK, 202 Accepted — сообщение принято в очередь.
- **4xx (ошибка клиента)**: 400 Bad Request (неверный формат), 401 Unauthorized (отсутствует или неверный токен), 403 Forbidden (недостаточно прав), 429 Too Many Requests (лимит скорости).
- **5xx (ошибка сервера)**: 500 Internal Server Error (проблема у провайдера), 502 Bad Gateway, 503 Service Unavailable (временная недоступность).

Эти группы покрывают более 95 % реальных случаев при работе с [SMS API](http://smsblog.ru/obzory-i-sravneniya/polnoe-rukovodstvo-po-sms-api-ot-vybora-provaydera-do-integratsii/) в 2025‑2026 гг.

## Как интерпретировать sms api response codes

Первый шаг — проверка http_status. Если он вне диапазона 200‑299, ищите причину в документации провайдера по HTTP‑кодам. Пример: 401 часто означает, что `Authorization` заголовок отсутствует или срок действия токена истек.

Если http_status = 200, переходите к полю provider_code (иногда называется `error_code` или `status`). Ниже типичные значения для популярных шлюзов (варианты могут отличаться):

| provider_code | Описание | Рекомендуемое действие |
| --- | --- | --- |
| 0 | Успех | Никаких действий |
| 1001 | Invalid destination number | Проверьте формат телефона (E.164) |
| 1002 | Insufficient balance | Пополните счёт или проверьте лимит |
| 1003 | Message too long | Уменьшите текст или включите конкатенацию |
| 1004 | Duplicate message ID | Генерируйте уникальный идентификатор каждый запрос |
| 1005 | Sender ID not approved | Согласуйте отправителя в личном кабинете |

При получении不明ного кода обращайтесь к разделу “Error codes” в технической документации провайдера (см. [Техническая документация и основы работы SMS API: полное руководство](http://smsblog.ru/biznes-kommunikacii/tekhnicheskaya-dokumentatsiya-i-osnovy-raboty-sms-api-polnoe-rukovodst/)).

## Типичные ошибки при работе с SMS API и способы отладки

### Ошибки авторизации (401, 403)

Самая частая причина — отсутствие или неправильная передача токена. Проверьте:

- Заголовок `Authorization: Bearer <token>` или `API-Key`.
- Срок жизни токена (обычно 24 ч). При истечении выполните refresh‑запрос.
- IP‑фильтрацию: некоторые провайдеры ограничивают доступ по списку разрешённых адресов.

Пример правильного запроса cURL:

```
curl -X POST https://api.smsprovider.ru/v1/messages
  -H "Authorization: Bearer $TOKEN"
  -H "Content-Type: application/json"
  -d '{"to":"+79001234567","text":"Тест","sender":"Info"}'
```

### Ошибки валидации данных (400)

Код 400 возникает, когда тело запроса не соответствует схеме JSON или обязательные поля пусты. Частые проблемы:

- Отсутствует поле `to` или оно содержит буквы.
- Поле `text` превышает допустимую длину (обычно 160 символов для одного сегмента GSM‑7).
- Неправильный Content-Type (должен быть `application/json`).

Для быстрой диагностики включите вывод тела ответа в логи:

```
response = requests.post(url, json=payload, headers=headers)
if response.status_code != 200:
    logger.error("SMS API error %s: %s", response.status_code, response.text)
```

### Ошибки провайдера (500, 502, 503)

Эти коды указывают на проблемы со стороны шлюза: перегрузка, внутренний сбой или временная недоступность. Рекомендации:

- Повторить запрос с экспоненциальным backoff (например, 1 с, 2 с, 4 с, максимум 5 попыток).
- Проверять статус‑страницу провайдера (часто предоставляет реальное время инцидентов).
- При частых 503 рассмотреть резервный провайдер или очередь сообщений.

Логировать следует не только код, но и заголовок `Retry-After`, если он присутствует.

## Практические примеры запросов и обработки ответов

Ниже показан полный цикл отправки SMS и детальной обработки ответа на Python с использованием библиотеки `requests`. Комментарии поясняют каждый шаг.

```
import requests, time, logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

BASE_URL = "https://api.smsprovider.ru/v1"
TOKEN = "ваш_токен_здесь"

def send_sms(to, text, sender="Info"):
    url = f"{BASE_URL}/messages"
    headers = {
        "Authorization": f"Bearer {TOKEN}",
        "Content-Type": "application/json"
    }
    payload = {
        "to": to,
        "text": text,
        "sender": sender
    }

    for attempt in range(1, 6):  # до 5 попыток
        resp = requests.post(url, json=payload, headers=headers, timeout=10)
        logger.info("Attempt %s: HTTP %s", attempt, resp.status_code)

        if resp.status_code == 200:
            data = resp.json()
            if data.get("provider_code") == 0:
                logger.info("SMS queued, id=%s", data.get("message_id"))
                return data.get("message_id")
            else:
                logger.warning("Provider error %s: %s", data.get("provider_code"), data.get("error_message"))
                # здесь можно поднять исключение или вернуть код ошибки
                return None

        # обработка временных ошибок
        if resp.status_code in (429, 500, 502, 503):
            wait = 2 ** attempt  # экспоненциальный backoff
            logger.warning("Transient error %s, retry in %s sec", resp.status_code, wait)
            time.sleep(wait)
            continue

        # все остальные 4xx — фатальные, не повторяем
        logger.error("Client error %s: %s", resp.status_code, resp.text)
        break
    return None

# пример использования
send_sms("+79001234567", "Привет! Это тестовое сообщение.")
```

При работе на высоких нагрузках рекомендуется вынести логирование в отдельный сервис (например, ELK стек) и использовать асинхронный HTTP‑клиент (`httpx.AsyncClient`) для неблокирующего ввода‑вывода.

## Лучшие практики мониторинга и логирования

Чтобы минимизировать потери доставки и быстро реагировать на инциденты, внедрите следующее:

- **Полный дамп запроса‑ответа** в структурированный лог (JSON). Включайте: timestamp, method, URL, headers (без токена), тело запроса, http_status, provider_code, тело ответа, задержка.
- **Метрики**: счётчики успеха, 4xx, 5xx, среднее время ответа, процент дубликатов. Используйте Prometheus или аналогичную систему.
- **Оповещения**: при превышении порога 5xx (>1 % за 5 мин) или роста 401/403 отправить 알ертирование в Slack/PagerDuty.
- **Идемпотентность**: генерируйте уникальный `message_id` на стороне клиента и проверяйте его наличие в ответе, чтобы избежать двойной отправки при повторных попытках.
- **Регулярный аудит токенов**: автоматически обновляйте токен за 5 минут до истечения срока, храните его в безопасном хранилище (Vault, AWS Secrets Manager).

Следуя этим рекомендациям, вы сократите среднее время восстановления после сбоя шлюза с минут до секунд и повысите доверие клиентов к сервису рассылок.

## FAQ

### Как отличить ошибку провайдера от ошибки моего кода?

Если http_status находится в диапазоне 4xx — проблема в запросе (отсутствуют обязательные поля, неправильный формат, неверные учетные данные). Если http_status = 200, но provider_code ≠ 0 — это бизнес‑логика шлюза (недостаточно средств, неправильный номер). При 5xx — ошибка со стороны провайдера.

### Что делать, если я постоянно получаю 429 Too Many Requests?

Это сигнал превышения лимита запросов в секунду. Снизьте скорость отправки, реализуйте очередь с ограничением скорости (rate limiter) или запросите увеличение лимита у технической поддержки провайдера.

### Нужно ли логировать содержимое SMS‑сообщения?

Логировать тело сообщения допустимо, если оно не содержит персональных данных (ПДН). Если в тексте есть личные сведения — маскируйте или хешируйте их перед записью в лог.

### Можно ли использовать один и тот же message_id для повторной отправки?

Нет. message_id должен быть уникальным для каждой попытки; иначе провайдер может посчитать запрос дубликатом и вернуть ошибку 1004.

### Как быстро проверить, доступен ли шлюз перед массовой рассылкой?

Отправьте тестовое SMS на собственный номер с минимальным текстом и проверьте, что http_status = 200 и provider_code = 0. При любой ошибке отложите массовую рассылку и разберите причину.

### Влияет ли выбор протокола (REST vs SOAP) на коды ошибок?

Коды ошибок остаются теми же, потому что они определены логикой провайдера, а не транспортным протоколом. SOAP оборачивает тот же JSON/XML в конверт, поэтому обработка ответов аналогична.

### Нужно ли проверять сертификат SSL при подключении к [SMS API](http://smsblog.ru/obzory-i-sravneniya/polnoe-rukovodstvo-po-sms-api-ot-vybora-provaydera-do-integratsii/)?

Да. Все современные шлюзы требуют TLS 1.2 или выше. Отключение проверки сертификата делает соединение уязвимым к MITM‑атакам и не рекомендуется в продакшене.

## Источники

- В материале не указаны внешние источники.
