smsyaz API v1
Taban adres: https://api.smsyaz.com. Tüm istek ve yanıtlar JSON (UTF-8). Tarih/saatler UTC (ISO 8601).
Kimlik doğrulama (HMAC imza)
API anahtarınızı panelde Geliştirici sayfasında (yalnızca bir kez) görürsünüz. Her istekte şu başlıklar zorunludur:
| Başlık | Açıklama |
|---|---|
x-api-key | API anahtarınız (sy_live_...) |
x-timestamp | Unix zamanı, milisaniye (saniye de kabul edilir). Sunucu saatinden en fazla ±5 dakika. |
x-nonce | Her istekte yeni, 16-64 karakter rastgele değer (ör. 32 hex). Aynı nonce 10 dakika içinde ikinci kez kabul edilmez. |
x-signature | hex(HMAC_SHA256(apiKey, timestamp + "." + nonce + "." + METHOD + "." + path + "." + body)) - küçük harf hex. GET isteklerinde body boş dizedir; path sorgu dizesini de içerir. |
C# örneği
var body = JsonSerializer.Serialize(new { message = "Merhaba", recipients = new[] { "05xxxxxxxxx" } });
var ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
var nonce = Convert.ToHexStringLower(RandomNumberGenerator.GetBytes(16));
var sig = Convert.ToHexStringLower(HMACSHA256.HashData(Encoding.UTF8.GetBytes(apiKey),
Encoding.UTF8.GetBytes($"{ts}.{nonce}.POST./v1/sms/send.{body}")));
var req = new HttpRequestMessage(HttpMethod.Post, "https://api.smsyaz.com/v1/sms/send") { Content = new StringContent(body, Encoding.UTF8, "application/json") };
req.Headers.Add("x-api-key", apiKey); req.Headers.Add("x-timestamp", ts);
req.Headers.Add("x-nonce", nonce); req.Headers.Add("x-signature", sig);
Node.js örneği
const crypto = require("crypto");
const body = JSON.stringify({ message: "Merhaba", recipients: ["05xxxxxxxxx"] });
const ts = Date.now().toString(), nonce = crypto.randomBytes(16).toString("hex");
const signature = crypto.createHmac("sha256", apiKey).update(`${ts}.${nonce}.POST./v1/sms/send.${body}`).digest("hex");
await fetch("https://api.smsyaz.com/v1/sms/send", { method: "POST", body,
headers: { "content-type": "application/json", "x-api-key": apiKey, "x-timestamp": ts, "x-nonce": nonce, "x-signature": signature } });
İmza, gönderdiğiniz gövdenin birebir aynısı üzerinden hesaplanmalıdır (JSON'u imzaladıktan sonra yeniden biçimlendirmeyin).
SMS gönder - POST /v1/sms/send
| Alan | Açıklama |
|---|---|
message | Metin, en fazla 1600 karakter. (text da kabul edilir.) |
recipients | Numara dizisi, tek istekte en fazla 100.000 (limit numara sayısıdır, mesajın kaç boy olduğu etkilemez; istek gövdesi en fazla 4 MB). Panelden tek gönderim en fazla 10.000. 05xx..., 5xx..., +905xx... biçimleri kabul edilir; tekrarlar ayıklanır. Tek numara için to. |
type | informational (varsayılan) ya da commercial (İYS marka kodu tanımlı olmalı). |
senderName | İsteğe bağlı başlık; operatör hesaplarınızdan birinde tanımlı olmalı. Boşsa öncelik sırasındaki operatörün başlığı. |
clientReference | İsteğe bağlı, en fazla 100 karakter. Aynı referansla gelen ikinci istek yeni gönderim yapmaz; ilk sonucu duplicate: true ile döner (güvenle tekrar deneyebilirsiniz). Aynı referans farklı metin/alıcı ile gelirse 409 REFERENCE_CONFLICT. |
Yanıt 202 (tümü kuyrukta) ya da 207 (bazı numaralar geçersiz). SMS'ler hemen kuyruğa alınır, operatöre gönderim arka planda yapılır:
{ "queued": true, "message": "2 SMS kuyruğa alındı.", "duplicate": false, "batchId": "0199...", "count": 2, "segments": 1, "encoding": "turkish",
"cost": 2.00, "balance": 998.00,
"messages": [ { "id": "0199...", "recipient": "+905xxxxxxxxx" } ],
"sent": ["+905xxxxxxxxx"], "failedCount": 1, "failed": [ { "recipient": "123", "reason": "INVALID_NUMBER" } ] }
messages ve sent yalnızca 1.000 ve altı alıcıda döner; failed en fazla ilk 1.000 geçersiz numarayı içerir (toplamı failedCount). Büyük gönderimi batchId ile takip edin (aşağıda).
Ücret kabul anında bakiyeden düşülür; hiçbir operatörün kabul etmediği mesajın ücreti otomatik iade edilir.
Bakiye yetmezse hiçbir SMS kuyruğa alınmaz (kısmi gönderim yok), 402 döner; yanıtta bakiyenizin kaç alıcıya yettiği de bulunur:
{ "error": { "code": "INSUFFICIENT_BALANCE", "message": "Bakiye yetersiz: bu gönderim 1.200,00 TL, bakiyeniz 700,00 TL. Bakiyeniz en fazla 7.000 alıcıya yetiyor.",
"required": 1200.00, "balance": 700.00, "maxRecipients": 7000 } }
Durum sorgula
GET /v1/sms/{messageId} - tek mesaj. GET /v1/sms/batches/{batchId} - gönderimin duruma göre sayıları
(örn. { "status": { "queued": 40000, "submitted": 60000 } }; büyük gönderimde birkaç saniyede bir sorgulayabilirsiniz).
Mesaj bazında bildirim için webhook kullanın.
| Durum | Anlamı |
|---|---|
queued / sending | Kuyrukta / operatöre gönderiliyor. |
submitted | Operatör kabul etti (ücret kesinleşti). |
failed | Hiçbir operatör kabul etmedi; ücret iade edildi. |
unknown | Operatör zaman aşımına uğradı - gitmiş olabilir. Çift SMS olmaması için yedeğe geçilmez. |
Bakiye - GET /v1/balance
{ "balance": 998.00, "currency": "TRY", "pricePerSegment": 1.00 }
OTP (doğrulama kodu)
POST /v1/otp/send - { "recipient": "05xx...", "length": 6, "ttlSeconds": 180, "text": "Kodunuz: {code}" } (length 4-8, ttl 60-900 sn, text isteğe bağlı ve {code} içermeli). Yanıt: { "otpId", "expiresAt", "messageId" }. Aynı numaraya 10 dakikada en fazla 3 kod.
POST /v1/otp/verify - { "otpId": "...", "code": "123456" } → { "valid": true }. Kod tek kullanımlıktır, en fazla 5 deneme.
Webhook
Panelde https adresinizi ekleyin; imza sırrı bir kez gösterilir. Olaylar: message.status, balance.low, apikey.rotated. Başlıklar: x-smsyaz-event, x-smsyaz-delivery, x-smsyaz-timestamp, x-smsyaz-signature = hex(HMAC_SHA256(sır, timestamp + "." + body)). 2xx dışındaki yanıtlarda 1 dk, 5 dk, 30 dk, 2 sa, 6 sa, 12 sa aralıklarla yeniden denenir.
{ "event": "message.status", "messageId": "0199...", "batchId": "0199...", "recipient": "+905xxxxxxxxx",
"status": "submitted", "error": null, "occurredAt": "2026-09-25T10:00:00Z" }
Hatalar
{ "error": { "code": "INSUFFICIENT_BALANCE", "message": "Bakiye yetersiz (gerekli: 12.00 TL)." } }
| HTTP | Kodlar |
|---|---|
| 401 | UNAUTHORIZED, BAD_SIGNATURE, BAD_TIMESTAMP, REPLAYED, KEY_INACTIVE |
| 402 | INSUFFICIENT_BALANCE |
| 403 | CUSTOMER_PASSIVE |
| 409 | REFERENCE_CONFLICT |
| 422 | EMPTY_MESSAGE, MESSAGE_TOO_LONG, NO_RECIPIENTS, NO_VALID_RECIPIENTS, TOO_MANY_RECIPIENTS, NO_PROVIDER, UNKNOWN_HEADER, IYS_REQUIRED, VALIDATION |
| 429 | RATE_LIMITED, OTP_RATE_LIMIT |
Kurallar
- SMS boyu: standart karakterlerde 160 (çok parçada 153), Türkçe karakterli metinde 155 (150), emoji/diğer alfabelerde 70 (67). Ücret = boy × alıcı × SMS boyu ücretiniz.
- Anahtar başına saniyede varsayılan 50 istek.
- API anahtarınızın süresi dolmadan yenisi otomatik üretilir ve bildirilir; eski anahtar bitiş tarihine kadar çalışır.
- Anahtar değişikliği için panelden talep oluşturun; anahtar üretme/iptal yönetici tarafından yapılır.