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.

REST · JSON HTTPS only v1 5 dil kod nümunəsi

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

  1. 1sms.az-da qeydiyyatdan keç (pulsuz, 5 SMS hədiyyə)
  2. Profil → API → "API açar yarat" bas → key 1sk_xxx... formatında alacaqsan (yalnız 1 dəfə göstərilir — saxla!)
  3. Bu səhifədəki ilk curl nümunəsini kopyala, YOUR_API_KEY-i öz key-inlə əvəz et
Tələblər: API endpoint-lərini istifadə etmək üçün admin tərəfdən hesabınızın API icazəsi (OTP / Bulk / Advertising) açılmalıdır. Profilinizdə hansı icazələrin aktiv olduğunu görə bilərsiniz. Telefon nömrəsiz qeydiyyatlı user-lər (Google ilə qoşulan, telefon təsdiqi olmayan) API üzərindən SMS göndərə bilməz — əvvəl profilə telefon əlavə edib təsdiqləməlisiniz.

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)
Təhlükəsizlik: API key plaintext yalnız yaradıldığı an göstərilir. DB-də SHA-256 hash saxlanır. Key-i client-side kod-da (browser JS, mobil app-da bundle edilmiş) heç vaxt qoyma — yalnız server-tərəfi backend-ində istifadə et.
Brute-force qoruması: 15 dəqiqədə 5 dəfə yanlış API key göndərsən, IP-niz 15 dəqiqəyə kilidlənir (HTTP 429 ip_blocked). Düzgün açarla göndər.

Base URL & Format

Base URLhttps://1sms.az/api/v1
ProtocolHTTPS only (HTTP → 301)
FormatJSON (Content-Type: application/json)
EncodingUTF-8
Text max1530 simvol (~10 SMS part)
Bulk recipients max10 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

GET /api/v1/balance Cari SMS balansı + aktiv API icazələri
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

200 OK
{ "balance": 2500, "apis": { "otp": true, "bulk": true, "advertising": false } }
403 — heç bir API icazəsi aktiv deyil
{ "error": "no_api_permission", "message": "API icazəniz aktiv deyil. Admin ilə əlaqə saxlayın." }

Endpoint: OTP göndər

POST /api/v1/sms/otp Tək nömrəyə dərhal kod, idempotency dəstəyi

OTP üçün Notification kanalı sender adı istifadə olunur (Advertising kanalı yox). ApiOtpEnabled icazəsi tələb olunur.

Parametrlər (JSON body)

SahəTipTələbİzah
tostringREQUIREDAlıcı nömrəsi (məs. +994551234567). Yuxarıdakı 4 formatdan biri
textstringREQUIREDSMS mətni (max 1530 simvol)
senderNamestringREQUIREDTəsdiqlənmiş Notification kanalı sender adı (məs. 1sms.az)
X-Idempotency-Key (header)stringopt.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

200 OK
{ "success": true, "messageId": "1484276135", "cost": 1, "balance": 2499 }
402 — balans çatmır
{ "error": "insufficient_balance", "message": "Balans kifayət etmir. Lazım: 1, Var: 0", "required": 1, "balance": 0 }
502 — vendor uğursuz (balans avtomatik refund)
{ "error": "send_failed", "message": "SMS göndərilmədi, balans qaytarıldı", "msmErrno": 20, "msmErrText": "Invalid msisdn", "hint": "Telefon nömrəsi formatı yanlışdır..." }

Endpoint: Bildiriş SMS (tək + toplu)

POST /api/v1/sms/notification recipients massivində 1-10000 alıcı

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əTipTələbİzah
recipientsstring[]REQUIREDAlıcı nömrələri (1–10 000 ədəd). Yanlış format rejected[]-də qaytarılır, dublikatlar avtomatik silinir
textstringREQUIREDSMS mətni (max 1530 simvol)
senderNamestringREQUIREDTə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)

200 OK
{ "success": true, "requestedCount": 1, "sentCount": 1, "failedCount": 0, "messageIds": ["1484276135"], "cost": 1, "balance": 2499, "rejected": [] }

Cavab — TOPLU (recipients.length >= 2)

200 OK
{ "success": true, "requestedCount": 3, "sentCount": 3, "failedCount": 0, "taskId": "3258260524062456", "cost": 3, "refunded": 0, "balance": 2497, "rejected": [ { "number": "abc", "reason": "invalid_format" } ] }
Fərq: 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

POST /api/v1/sms/advertising Reklam, kampaniya — eyni schema

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.az sender ilə də göndərə bilərsən
Qeyd: External API üzərindən göndərilən reklam SMS-lərində saat məhdudiyyəti və AI mətn moderasiyası tətbiq olunmur — bu məhdudiyyətlər yalnız 1sms.az web/mobil paneldən göndərmələrdə fəaldır. API istifadəçisi məzmunun reklam qaydalarına uyğunluğundan özü cavabdehdir.
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

GET /api/v1/sms/status/{messageId} Tək SMS-in delivery statusu (vendor)
curl "https://1sms.az/api/v1/sms/status/1484276135" \
  -H "X-API-Key: 1sk_YOUR_API_KEY"

Cavab

200 OK
{ "messageId": "1484276135", "statusCode": 2, "statusText": "Çatdırıldı", "date": "2026-05-24T10:15:23" }

Status kodları (MSM vendor)

KodMənası
0Gözləmədə
1Operatora göndərildi
2Çatdırıldı (final)
3Müddəti bitdi (final)
5Çatdırılmadı (final)
8Rədd edildi (final)
9Operatora çatmadı (final)
IDOR qoruması: Yalnız öz hesabınızdan göndərilmiş SMS-in statusunu sorğulaya bilərsiniz. Başqa user-in messageId-sini bilsəniz belə 404 not_found qaytarılır.

Endpoint: Bulk task status

GET /api/v1/sms/task-status/{taskId}?channel=notification Toplu göndərişin hər alıcı üçün statusu

Bulk göndərişdən qayıdan taskId-ə görə hər nömrənin ayrıca statusu.

Query parametrlər

ParamDefaultİzah
channelnotificationnotification 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"
IDOR qoruması: Yalnız öz hesabınızın bulk task-ının statusunu sorğulaya bilərsiniz. Başqasının 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ı

  1. 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)
  2. "Aktiv et" düyməsini basın → status dəyişikliyi olduqda 1sms.az POST göndərəcək
  3. HMAC-SHA256 signature X-1sms-Signature header-də gəlir — server tərəfdə doğrulayın (key = sizin ApiSecret)

Webhook headers

HeaderDəyər
X-1sms-SignatureHMAC-SHA256 (hex lowercase) — body üzərində, key = ApiSecret
X-1sms-Eventsms.status_changed
User-Agent1sms.az-webhook/1.0
Content-Typeapplication/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')
  );
}
Retry yoxdur: Webhook fire-and-forget göndərilir (timeout 5 saniyə, no retry). Əgər server-iniz down olsa və ya 5 saniyədən gec cavab versə, həmin event itir. Backup mexanizmi olaraq /sms/status/{id} və ya /sms/task-status/{id} ilə polling istifadə edin.

Xəta kodları

HTTP status

KodMənası
200Uğurlu
400Bad 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)
401API key yoxdur (missing_api_key) və ya keçərsizdir (invalid_api_key)
402insufficient_balance — balans çatmır
403İcazə yoxdur: no_api_permission, otp_api_disabled, bulk_api_disabled, advertising_api_disabled, invalid_sender, phone_not_verified
404not_found — messageId/taskId tapılmadı və ya sənin deyil (IDOR)
409duplicate_in_progress — eyni X-Idempotency-Key ilə paralel sorğu hələ icra olunur
429ip_blocked — brute-force lock (15 dəq) və ya rate limit aşıldı
502Vendor xətası: send_failed, bulk_send_failed, vendor_exception — balans avtomatik refund

Response field-lər

Fieldİzah
errorMachine-readable kod (yuxarıdakı siyahıdan)
messageHuman-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

LayerLimit
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 recipients10 000 alıcı / sorğu
Text length1530 simvol (~10 SMS part)
Idempotency key128 simvol max
Regenerate API key1 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