SMS API Documentation
1sms.az REST API — Azerbaijan-da SMS göndərmək üçün vahid HTTPS interfeysi. Azercell, Bakcell, Nar — tək, toplu, OTP, reklam.
Giriş
1sms.az SMS Gateway REST API — biznes tətbiqlərinizdən birbaşa SMS göndərmək üçün. Bütün endpoint-lər JSON qəbul edir və qaytarır. Autentifikasiya HTTP header üzərində aparılır.
Tipik istifadə halları
- OTP / 2FA — bank/fintech qeydiyyat təsdiqi, login kodları, ödəniş təsdiqi
- Bildiriş SMS-i — sifariş statusu, çatdırılma, randevu xatırlatması
- Reklam SMS-i — kampaniya, endirim, yeni məhsul (brand sender adı tələb olunur)
- Toplu göndəriş — bir sorğuda 10 000 alıcıya qədər
3 dəqiqədə başla
- 1sms.az-da qeydiyyatdan keç (pulsuz, 5 SMS hədiyyə)
- Profil → API → "API açar yarat" bas → key
1sk_xxx...formatında alacaqsan (yalnız 1 dəfə göstərilir — saxla!) - Bu səhifədəki ilk
curlnümunəsini kopyala,YOUR_API_KEY-i öz key-inlə əvəz et
Autentifikasiya
Hər sorğu HTTP header-də API açar göndərməlidir:
REQUEST HEADER
X-API-Key: 1sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
API açar formatı
- Prefix:
1sk_(1 SMS key) - Minimum uzunluq: 90 simvol (server-də format yoxlanır)
- Yalnız HTTPS — HTTP üzərindən göndərilməməlidir
- Hər istifadəçinin 1 aktiv key-i ola bilər. Profil → API → "Regenerate" köhnəni dərhal invalidate edir (60 sn cool-down)
ip_blocked). Düzgün açarla göndər.
Base URL & Format
| Base URL | https://1sms.az/api/v1 |
| Protocol | HTTPS only (HTTP → 301) |
| Format | JSON (Content-Type: application/json) |
| Encoding | UTF-8 |
| Text max | 1530 simvol (~10 SMS part) |
| Bulk recipients max | 10 000 nömrə / sorğu |
Telefon nömrə formatı
Server qəbul etdiyi formatlar (avtomatik +994XXXXXXXXX-ə normallaşdırılır):
+994XXXXXXXXX(məs.+994501234567)994XXXXXXXXX(məs.994501234567)0XXXXXXXXX(məs.0501234567)XXXXXXXXX(9 rəqəm, məs.501234567)
Qadağan: 9940XXX, 00994XXX, boşluqlu nömrələr (səhv nömrəyə SMS riski → strict reject).
Xarici nömrələr (məs. +90..., +7...): yalnız InternationalSmsEnabled icazəsi açıq user-lər üçün; cost = operator multiplier × parts. İcazəsiz user xarici nömrəyə vurarsa invalid_phone_format qaytarılır (məlumat sızması olmasın).
Endpoint: Balans yoxla
curl "https://1sms.az/api/v1/balance" \ -H "X-API-Key: 1sk_YOUR_API_KEY"
const res = await fetch('https://1sms.az/api/v1/balance', { headers: { 'X-API-Key': '1sk_YOUR_API_KEY' } }); const data = await res.json(); console.log(data.balance, data.apis);
$ch = curl_init('https://1sms.az/api/v1/balance'); curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: 1sk_YOUR_API_KEY']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $data = json_decode(curl_exec($ch), true); echo $data['balance'];
import requests r = requests.get('https://1sms.az/api/v1/balance', headers={'X-API-Key': '1sk_YOUR_API_KEY'}) print(r.json())
using var client = new HttpClient(); client.DefaultRequestHeaders.Add("X-API-Key", "1sk_YOUR_API_KEY"); var json = await client.GetStringAsync("https://1sms.az/api/v1/balance"); Console.WriteLine(json);
Cavab
Endpoint: OTP göndər
OTP üçün Notification kanalı sender adı istifadə olunur (Advertising kanalı yox). ApiOtpEnabled icazəsi tələb olunur.
Parametrlər (JSON body)
| Sahə | Tip | Tələb | İzah |
|---|---|---|---|
to | string | REQUIRED | Alıcı nömrəsi (məs. +994551234567). Yuxarıdakı 4 formatdan biri |
text | string | REQUIRED | SMS mətni (max 1530 simvol) |
senderName | string | REQUIRED | Təsdiqlənmiş Notification kanalı sender adı (məs. 1sms.az) |
X-Idempotency-Key (header) | string | opt. | UUID və ya unique string (max 128 simvol) — 24 saat eyni cavab |
curl -X POST "https://1sms.az/api/v1/sms/otp" \ -H "X-API-Key: 1sk_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "X-Idempotency-Key: order-12345" \ -d '{"to":"+994551234567","text":"Kodunuz: 4827. 3 dəqiqə etibarlıdır.","senderName":"1sms.az"}'
const res = await fetch('https://1sms.az/api/v1/sms/otp', { method: 'POST', headers: { 'X-API-Key': '1sk_YOUR_API_KEY', 'Content-Type': 'application/json', 'X-Idempotency-Key': 'order-12345' }, body: JSON.stringify({ to: '+994551234567', text: 'Kodunuz: 4827. 3 dəqiqə etibarlıdır.', senderName: '1sms.az' }) }); const data = await res.json(); console.log(data.messageId);
$ch = curl_init('https://1sms.az/api/v1/sms/otp'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'X-API-Key: 1sk_YOUR_API_KEY', 'Content-Type: application/json', 'X-Idempotency-Key: order-12345' ], CURLOPT_POSTFIELDS => json_encode([ 'to' => '+994551234567', 'text' => 'Kodunuz: 4827. 3 dəqiqə etibarlıdır.', 'senderName' => '1sms.az' ]), CURLOPT_RETURNTRANSFER => true ]); $data = json_decode(curl_exec($ch), true); echo $data['messageId'];
import requests, uuid r = requests.post('https://1sms.az/api/v1/sms/otp', headers={ 'X-API-Key': '1sk_YOUR_API_KEY', 'X-Idempotency-Key': str(uuid.uuid4()) }, json={ 'to': '+994551234567', 'text': 'Kodunuz: 4827. 3 dəqiqə etibarlıdır.', 'senderName': '1sms.az' }) print(r.json())
var req = new HttpRequestMessage(HttpMethod.Post, "https://1sms.az/api/v1/sms/otp"); req.Headers.Add("X-API-Key", "1sk_YOUR_API_KEY"); req.Headers.Add("X-Idempotency-Key", Guid.NewGuid().ToString()); req.Content = JsonContent.Create(new { to = "+994551234567", text = "Kodunuz: 4827. 3 dəqiqə etibarlıdır.", senderName = "1sms.az" }); var res = await httpClient.SendAsync(req); var json = await res.Content.ReadAsStringAsync();
Cavab
Endpoint: Bildiriş SMS (tək + toplu)
Bildiriş kanalı — sifariş statusu, hesabınızda dəyişiklik, çatdırılma bildirişi. ApiBulkEnabled icazəsi tələb olunur.
Parametrlər
| Sahə | Tip | Tələb | İzah |
|---|---|---|---|
recipients | string[] | REQUIRED | Alıcı nömrələri (1–10 000 ədəd). Yanlış format rejected[]-də qaytarılır, dublikatlar avtomatik silinir |
text | string | REQUIRED | SMS mətni (max 1530 simvol) |
senderName | string | REQUIRED | Təsdiqlənmiş Notification kanalı sender adı |
# Tək alıcı curl -X POST "https://1sms.az/api/v1/sms/notification" \ -H "X-API-Key: 1sk_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"recipients":["+994551234567"],"text":"Sifarişiniz #1234 yola düşdü","senderName":"1sms.az"}' # Toplu (3 nömrə) curl -X POST "https://1sms.az/api/v1/sms/notification" \ -H "X-API-Key: 1sk_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"recipients":["+994551111111","+994552222222","+994553333333"],"text":"Mərkəz sabah 14:00-da bağlıdır","senderName":"1sms.az"}'
const recipients = customers.map(c => c.phone); const res = await fetch('https://1sms.az/api/v1/sms/notification', { method: 'POST', headers: { 'X-API-Key': '1sk_YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ recipients, text, senderName: '1sms.az' }) }); const data = await res.json(); console.log(`Sent: ${data.sentCount}, fail: ${data.failedCount}`);
$ch = curl_init('https://1sms.az/api/v1/sms/notification'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'X-API-Key: 1sk_YOUR_API_KEY', 'Content-Type: application/json' ], CURLOPT_POSTFIELDS => json_encode([ 'recipients' => ['+994551111111', '+994552222222'], 'text' => 'Toplu test', 'senderName' => '1sms.az' ]), CURLOPT_RETURNTRANSFER => true ]); $data = json_decode(curl_exec($ch), true); print_r($data);
Cavab — TƏK alıcı (recipients.length == 1)
Cavab — TOPLU (recipients.length >= 2)
messageIds[] tək alıcıda gəlir (status-u /sms/status/{messageId} ilə oxu). taskId toplu (≥2 alıcı) zamanı gəlir (status-u /sms/task-status/{taskId} ilə oxu). refunded — bulk vendor invalid count üçün geri qaytarılan SMS sayı (partial refund).
Endpoint: Reklam SMS
Reklam kanalı — endirim, kampaniya, yeni məhsul reklamı. ApiAdvertisingEnabled icazəsi tələb olunur. Schema və cavab tam olaraq /sms/notification ilə eynidir, fərq yalnız:
- Kanal: sender name Advertising kanalı üçün təsdiqlənmiş olmalıdır
- Sender adı: brend adı tələb olunur (məs.
MyShop) — fiziki müqavilə tələb edir.1sms.azsender ilə də göndərə bilərsən
curl -X POST "https://1sms.az/api/v1/sms/advertising" \ -H "X-API-Key: 1sk_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"recipients":["+994551234567"],"text":"50% endirim — bu həftə!","senderName":"MyShop"}'
Endpoint: SMS status
curl "https://1sms.az/api/v1/sms/status/1484276135" \ -H "X-API-Key: 1sk_YOUR_API_KEY"
Cavab
Status kodları (MSM vendor)
| Kod | Mənası |
|---|---|
0 | Gözləmədə |
1 | Operatora göndərildi |
2 | Çatdırıldı (final) |
3 | Müddəti bitdi (final) |
5 | Çatdırılmadı (final) |
8 | Rədd edildi (final) |
9 | Operatora çatmadı (final) |
messageId-sini bilsəniz belə 404 not_found qaytarılır.
Endpoint: Bulk task status
Bulk göndərişdən qayıdan taskId-ə görə hər nömrənin ayrıca statusu.
Query parametrlər
| Param | Default | İzah |
|---|---|---|
channel | notification | notification və ya advertising. Bulk göndərmə hansı endpoint-dən olubsa, eynisi |
curl "https://1sms.az/api/v1/sms/task-status/3258260524062456?channel=notification" \ -H "X-API-Key: 1sk_YOUR_API_KEY"
taskId-si üçün 404 not_found.
Webhook — status push
SMS-in statusu vendor tərəfindən yeniləndikdə (məs. Sent → Delivered) öz server-inizə avtomatik POST sorğusu gəlir. Polling əvəzinə real-time bildiriş.
Qurulması
- Profil → API → Webhook URL sahəsinə öz endpoint-inizi yazın (məs.
https://yourapp.com/webhooks/sms) — yalnız HTTPS, public domain (loopback, private IP, link-local SSRF qoruması ilə bloklanır) - "Aktiv et" düyməsini basın → status dəyişikliyi olduqda 1sms.az POST göndərəcək
- HMAC-SHA256 signature
X-1sms-Signatureheader-də gəlir — server tərəfdə doğrulayın (key = sizinApiSecret)
Webhook headers
| Header | Dəyər |
|---|---|
X-1sms-Signature | HMAC-SHA256 (hex lowercase) — body üzərində, key = ApiSecret |
X-1sms-Event | sms.status_changed |
User-Agent | 1sms.az-webhook/1.0 |
Content-Type | application/json; charset=utf-8 |
Webhook payload nümunəsi
{
"event": "sms.status_changed",
"messageId": "1484276135",
"statusCode": 2,
"statusText": "Çatdırıldı",
"phone": "994551234567",
"timestamp": "2026-05-24T10:15:23.456Z"
}
Signature doğrulanması (Node.js)
const crypto = require('crypto'); function verify(rawBody, signatureHeader, apiSecret) { const expected = crypto.createHmac('sha256', apiSecret) .update(rawBody, 'utf8').digest('hex'); // timing-safe compare — lengths must match first if (signatureHeader.length !== expected.length) return false; return crypto.timingSafeEqual( Buffer.from(signatureHeader, 'utf8'), Buffer.from(expected, 'utf8') ); }
/sms/status/{id} və ya /sms/task-status/{id} ilə polling istifadə edin.
Xəta kodları
HTTP status
| Kod | Mənası |
|---|---|
200 | Uğurlu |
400 | Bad request — input xətası (məs. missing_to, missing_text, invalid_phone_format, text_too_long, no_valid_recipients, recipients_limit_exceeded, idempotency_mismatch, idempotency_key_too_long) |
401 | API key yoxdur (missing_api_key) və ya keçərsizdir (invalid_api_key) |
402 | insufficient_balance — balans çatmır |
403 | İcazə yoxdur: no_api_permission, otp_api_disabled, bulk_api_disabled, advertising_api_disabled, invalid_sender, phone_not_verified |
404 | not_found — messageId/taskId tapılmadı və ya sənin deyil (IDOR) |
409 | duplicate_in_progress — eyni X-Idempotency-Key ilə paralel sorğu hələ icra olunur |
429 | ip_blocked — brute-force lock (15 dəq) və ya rate limit aşıldı |
502 | Vendor xətası: send_failed, bulk_send_failed, vendor_exception — balans avtomatik refund |
Response field-lər
| Field | İzah |
|---|---|
error | Machine-readable kod (yuxarıdakı siyahıdan) |
message | Human-readable AZ izah |
msmErrno | (OTP send fail) Vendor errno: 20=invalid msisdn, 25=blacklisted, 91=duplicate |
msmErrText | (OTP send fail) Vendor mətn izahı |
code | (Bulk/notification send fail) Vendor errno |
hint | (OTP send fail) AZ düzəliş tövsiyəsi |
acceptedFormats + received | (invalid_phone_format) Düzgün format nümunələri |
required + balance | (insufficient_balance) Lazımi və mövcud SMS sayı |
limit + received | (recipients_limit_exceeded) 10000 limit |
Rate limits
| Layer | Limit |
|---|---|
Per API key (bütün /api/v1/* endpoint-lər) | 60 sorğu / dəq, burst 60 (token bucket) |
| Brute-force (yanlış API key) | 5 cəhd / 15 dəq / IP → 15 dəq lock |
| Bulk recipients | 10 000 alıcı / sorğu |
| Text length | 1530 simvol (~10 SMS part) |
| Idempotency key | 128 simvol max |
| Regenerate API key | 1 dəfə / 60 saniyə |
Idempotency
Eyni əməliyyatın təkrar göndərilməsindən qaçınmaq üçün (network retry, double-click) X-Idempotency-Key header istifadə edilə bilər. Stripe-tipli race-safe pattern:
- Tövsiyə olunan format: UUID və ya
{your_order_id}-{event_type} - Eyni key 24 saat ərzində eyni cavabı qaytarır — SMS yalnız 1 dəfə göndərilir
- Maksimum uzunluq: 128 simvol (aşıldıqda HTTP 400
idempotency_key_too_long) - Eyni key ilə paralel sorğu hələ icra olunursa → HTTP 409
duplicate_in_progress - Eyni key başqa endpoint-də istifadə olunubsa → HTTP 400
idempotency_mismatch - Vendor transient fail (502/exception) halında pending row silinir → eyni key ilə retry edə bilərsiniz
HEADER
X-Idempotency-Key: order-1234-otp
X-API-Key: 1sk_YOUR_API_KEY
Content-Type: application/json
Daha çox kod nümunəsi
GitHub-da rəsmi SDK-lar (planlanır):
- Node.js:
npm install @1sms/sdk— tezliklə - PHP:
composer require 1sms/sdk-php— tezliklə - Python:
pip install onesms-sdk— tezliklə
Hələlik curl və yuxarıdakı manuel kod nümunələri ilə işləyin. Bütün endpoint-lər REST/JSON-dir, hər dildə standart HTTP client kifayətdir.
Əlavə suallar?
info@joinup.az · 050 277 44 29 · @1sms_az