🔐 Аутентификация
В каждом запросе необходимо отправлять следующий заголовок:
Authorization: Bearer your_token_here
1. Отправка SMS
https://devsms.uz/api/send_sms.php
Тело запроса:
{
"phone": "998901234567",
"message": "Test SMS xabari",
"from": "4546",
"callback_url": "https://your-domain.com/sms-callback"
}
Параметры:
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
| phone | string | Да | Номер телефона (998901234567) |
| message | string | Да | Текст SMS |
| from | string | Нет | От кого (по умолчанию: 4546) |
| callback_url | string | Нет | URL для отправки результата при изменении статуса SMS (http:// или https://) |
| type | string | Нет | Тип SMS: eskiz (default), simple, universal_otp |
Ответ:
// На узбекский номер
{
"success": true,
"message": "SMS muvaffaqiyatli yuborildi",
"data": {
"sms_id": 123,
"request_id": "uuid-here",
"status": "sent",
"parts_count": 1,
"total_cost": "$0.005",
"balance": "$0.079",
"type": "eskiz"
}
}
1.1 Universal OTP SMS
https://devsms.uz/api/send_sms.php
Отправка кода подтверждения через универсальные OTP шаблоны Eskiz. Название компании проверяется AI модерацией.
Универсальные шаблоны одобрены Eskiz. Вы указываете только название компании и OTP код. Если название компании неприемлемо, SMS не отправляется и баланс НЕ списывается (в ответе charged: false). Защита от злоупотреблений: после 20 отказов ПОДРЯД универсальный OTP отключается на 24 часа — счётчик обнуляется, как только модерация проходит. В каждом ответе возвращаются reject_streak и remaining_attempts.
Тело запроса:
{
"phone": "998901234567",
"type": "universal_otp",
"template_type": 1,
"service_name": "TechShop",
"otp_code": "5678",
"callback_url": "https://your-site.com/callback"
}
Параметры:
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
| phone | string | Да | Номер телефона (998901234567) |
| type | string | Да | "universal_otp" |
| template_type | integer | Да | Тип шаблона: 1=Подтверждение операции, 2=Сброс пароля, 3=Регистрация, 4=Вход в систему |
| service_name | string | Да | Название компании/сервиса (2-50 символов, только буквы, цифры, пробелы, точка, тире) |
| otp_code | string | Да | OTP код подтверждения (4-8 цифр) |
| callback_url | string | Нет | URL для отправки результата при изменении статуса SMS (http:// или https://) |
О callback: статусный callback приходит только если SMS ДЕЙСТВИТЕЛЬНО отправлено в Eskiz. Если название компании не прошло AI модерацию, SMS не отправляется и request_id не создаётся — в этом случае callback НЕ придёт. Именно это означает charged: false в ответе.
Доступные шаблоны:
MyService tizimi: {service_name} xizmatida amaliyotni tasdiqlash kodi: {otp_code}
MyService tizimi: {service_name} xizmatida parolni tiklash uchun tasdiqlash kodi: {otp_code}
MyService tizimi: {service_name} xizmatiga ro'yxatdan o'tish uchun tasdiqlash kodi: {otp_code}
MyService tizimi: {service_name} xizmatiga kirish uchun tasdiqlash kodi: {otp_code}
Ответ:
{
"success": true,
"message": "SMS muvaffaqiyatli yuborildi",
"data": {
"sms_id": 456,
"request_id": "uuid-here",
"status": "sent",
"parts_count": 1,
"total_cost": "$0.005",
"balance": "$0.079",
"type": "universal_otp"
}
}
Ответ для заблокированного SMS:
{
"success": false,
"error": "Korxona nomi nomaqbul deb topildi: ... SMS yuborilmadi, lekin to'lov yechildi."
}
2. Получить Историю SMS
https://devsms.uz/api/get_history.php
Query параметры:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| limit | integer | 50 | Количество SMS (макс: 200) |
| offset | integer | 0 | Смещение |
| status | string | null | Фильтр по статусу (sent, delivered, failed) |
Пример:
GET https://devsms.uz/api/get_history.php?limit=10&offset=0&status=delivered
Ответ:
{
"success": true,
"data": {
"history": [
{
"id": 123,
"phone_number": "998901234567",
"message": "Salom!",
"status": "delivered",
"parts_count": 1,
"total_cost": "$0.005",
"from_number": "4546",
"eskiz_request_id": "uuid-here",
"eskiz_message_id": "msg-id",
"sent_at": "2026-03-09 10:30:00",
"delivered_at": "2026-03-09 10:30:05",
"failed_at": null,
"created_at": "2026-03-09 10:29:58"
}
],
"count": 1,
"limit": 10,
"offset": 0
}
}
Временные метки статуса
| Параметр | Описание |
|---|---|
| created_at | Время создания SMS |
| sent_at | Время отправки SMS |
| delivered_at | Время доставки SMS |
| failed_at | Время неудачной отправки SMS |
3. Получить Баланс
https://devsms.uz/api/get_balance.php
Ответ:
{
"success": true,
"data": {
"balance": "$0.083",
"sms_price": "$0.005",
"statistics": {
"total_sms": 100,
"total_spent": "$0.414",
"today_sms": 10,
"today_spent": "$0.042",
"month_sms": 50,
"month_spent": "$0.207" }
}
}
4. Получить Статус SMS
https://devsms.uz/api/get_status.php
Query параметры:
| Параметр | Тип | Описание |
|---|---|---|
| sms_id | integer | SMS ID (ID в базе данных) |
| request_id | string | Eskiz request ID |
Пример:
GET https://devsms.uz/api/get_status.php?sms_id=123
или
GET https://devsms.uz/api/get_status.php?request_id=uuid-here
Ответ:
{
"success": true,
"data": {
"id": 123,
"phone_number": "998901234567",
"message": "Salom!",
"status": "delivered",
"parts_count": 1,
"total_cost": "$0.005",
"from_number": "4546",
"eskiz_request_id": "uuid-here",
"eskiz_message_id": "msg-id",
"sent_at": "2026-03-09 10:30:00",
"delivered_at": "2026-03-09 10:30:05",
"failed_at": null,
"created_at": "2026-03-09 10:29:58",
"updated_at": "2026-03-09 10:30:05"
}
}
🔔 Callback URL
При добавлении параметра callback_url при отправке SMS, при изменении статуса (отправлено, доставлено, не доставлено) на ваш URL будет отправлен POST запрос.
Когда отправляется callback:
Данные, отправляемые на ваш URL:
{
"sms_id": 123,
"request_id": "uuid-here",
"phone": "998901234567",
"status": "delivered",
"sent_at": "2026-03-09 10:30:00",
"delivered_at": "2026-03-09 10:30:05",
"failed_at": null,
"timestamp": "2026-03-09 10:30:05"
}
Параметры:
| Параметр | Тип | Описание |
|---|---|---|
| sms_id | integer | SMS ID (ID в базе данных) |
| request_id | string | Eskiz request ID |
| phone | string | Номер телефона (998901234567) |
| status | string | Фильтр по статусу (sent, delivered, failed) |
| sent_at | string|null | Время отправки SMS |
| delivered_at | string|null | Время доставки SMS |
| failed_at | string|null | Время неудачной отправки SMS |
| timestamp | string | Время создания SMS |
Примечание: Callback отправляется с таймаутом 5 секунд. Если ваш сервер не ответит, повторная попытка не выполняется.
✅ Требования к callback_url
В целях безопасности callback_url проверяется дважды: при отправке SMS и в момент отправки callback. Отклоняются:
- Протоколы, отличные от http:// и https://
- Внутренние и зарезервированные диапазоны IP (127.0.0.1, 10.x, 172.16-31.x, 192.168.x, 169.254.x, ::1 и другие)
- localhost и тестовые/placeholder домены (example.com, test.com и т.п.)
- Домены, не разрешающиеся через DNS
- URL длиннее 500 символов
В момент отправки домен проверяется повторно и жёстко привязывается к подтверждённому IP (защита от DNS-rebinding). Редиректы не отслеживаются, ответ ограничен 10 КБ и вам не возвращается.
🔐 Проверка подлинности callback (подпись)
Каждый callback отправляется с двумя дополнительными заголовками. Они доказывают, что запрос действительно пришёл от DevSMS — без этого любой, кто знает ваш callback URL, мог бы отправить поддельный статус.
X-DevSMS-Timestamp: 1786500000
X-DevSMS-Signature: sha256=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Ключ подписи находится в вашем кабинете: Настройки → API. Никому его не передавайте.
Порядок проверки:
- Убедитесь, что X-DevSMS-Timestamp отличается от текущего времени не более чем на 5 минут (защита от replay).
- Вычислите HMAC-SHA256: ключ — ваш webhook-ключ, строка — "{timestamp}.{сырое_тело}".
- Сравните результат с X-DevSMS-Signature через hash_equals.
<?php
// XOM body — json_decode qilmasdan!
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_DEVSMS_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_DEVSMS_TIMESTAMP'] ?? '';
$secret = 'whsec_...'; // kabinetdagi kalitingiz
if (!is_numeric($timestamp) || abs(time() - (int)$timestamp) > 300) {
http_response_code(403); exit('stale');
}
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(403); exit('bad signature');
}
// Imzo to'g'ri — endi ma'lumotga ishonish mumkin
$data = json_decode($rawBody, true);
ВАЖНО: подпись считается по СЫРОМУ телу запроса. Не парсите JSON и не кодируйте его заново — порядок символов изменится и подпись не совпадёт.
Для существующих интеграций ничего не изменилось: тело запроса прежнее, заголовки — дополнительные. Проверку можно добавить в любой момент.
📝 Статусы SMS
| Статус | Описание |
|---|---|
| pending | SMS ещё не отправлено (в ожидании) |
| sent | SMS отправлено (Eskiz принял) |
| delivered | SMS доставлено получателю |
| failed | SMS не доставлено (отклонено или не доставлено) |
❌ Ошибки
При возникновении ошибки возвращается следующий формат:
{
"success": false,
"error": "Xatolik xabari"
}
HTTP коды статуса:
| Код | Описание |
|---|---|
| 200 | Успешно |
| 400 | Неверный запрос |
| 401 | Ошибка аутентификации |
| 403 | Доступ запрещен |
| 404 | Не найдено |
| 500 | Ошибка сервера |
Совет:
Для тестирования API можно использовать Postman или cURL.
🔧 Примеры cURL
Отправка SMS:
curl -X POST https://devsms.uz/api/send_sms.php \
-H "Authorization: Bearer your_token" \
-H "Content-Type: application/json" \
-d '{
"phone": "998901234567",
"message": "Test SMS"
}'
Получить Баланс:
curl -X GET https://devsms.uz/api/get_balance.php \
-H "Authorization: Bearer your_token"
💻 Примеры Кода
Выберите язык программирования:
<?php
// DevSMS API - PHP Example
$token = "your_api_token_here";
$baseUrl = "https://devsms.uz/api";
// SMS Yuborish
function sendSMS($token, $baseUrl, $phone, $message) {
$ch = curl_init("$baseUrl/send_sms.php");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $token",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode([
"phone" => $phone,
"message" => $message
])
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
// Balansni olish
function getBalance($token, $baseUrl) {
$ch = curl_init("$baseUrl/get_balance.php");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $token"
]
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
// Ishlatish
$result = sendSMS($token, $baseUrl, "998901234567", "Salom!");
print_r($result);
$balance = getBalance($token, $baseUrl);
print_r($balance);
?>