SMS & OTP API

Projelerinizden SMS ve tek kullanımlık doğrulama kodu göndermek için tek bir API. Alıcı GOLOS kullanıyorsa mesaj uygulamaya düşer ve paketinizden düşmez; kullanmıyorsa SMS olarak gider.

Dört adımda kurulum

Bu API'yi kullanmak için Resco Telecom müşterisi olmanız yeterlidir. Her gönderim müşteri panelinizde görünür; ne gönderdiğinizi, hangi kanaldan gittiğini ve paketinizden ne düştüğünü her zaman izleyebilirsiniz.

1 · Üye olunrescotelecom.com üzerinden hesabınızı açın ve güvenli numaranızı doğrulayın.
2 · SMS paketi alınPanelde Siparişler'den bir SMS paketi alın. Paket hemen hesabınıza yüklenir.
3 · Anahtar üretinAPI anahtarları sekmesinde projeniz için bir anahtar üretin. Gizli anahtar yalnız bir kez gösterilir.
4 · İmzalı istek atınAşağıdaki örneklerle ilk isteğinizi gönderin. Kullanım paketinizden düşer, dökümde görünür.
Gizli anahtarınızı kaybettiyseniz panelden yenileyin: yeni gizli 15 dakika boyunca eskisiyle birlikte geçerlidir, kesintisiz geçiş yaparsınız.

Kimlik ve imza

Her istek HTTPS üzerinden gider ve dört başlıkla imzalanır. Gizli anahtar hiçbir istekte gönderilmez; yalnız imzayı üretmek için kullanılır. Sunucu aynı imzayı kendi tarafında hesaplar ve karşılaştırır.

BaşlıkDeğer
X-Resco-AnahtarAnahtar kimliği, rt_<proje>_<8 hex> biçiminde (panelde görünür, gizli değildir).
X-Resco-ZamanUnix zamanı, saniye. Sunucu saatiyle fark en fazla ±300 saniye olabilir.
X-Resco-NonceHer istekte yeni, 16–64 karakterlik rastgele dize (A-Za-z0-9_-). Aynı nonce ikinci kez kabul edilmez.
X-Resco-ImzaAşağıdaki metnin gizli anahtarla HMAC-SHA256 özeti, küçük harf hex.
Content-Typeapplication/json

İmzalanan metin

Beş satır, aralarında \n (LF). Gövde özeti ham JSON'un SHA-256'sıdır; GET isteğinde gövde boş dizedir. Yol sorgu dizesi olmadan yazılır.

zaman
nonce
METHOD              (POST veya GET)
/api/sms/gonder     (yalnız yol, ?sorgu yok)
sha256hex(ham gövde)

imza = hex( HMAC-SHA256( gizli, metin ) )
Uçlar /api/v1/… altında sürümlüdür; /api/… kısa yolu da aynı işi yapar ve en az 12 ay açık kalır. Yeni projede /api/v1/ kullanın; imzaladığınız yol çağırdığınız yolla aynı olmalıdır.
Gövdeyi imzaladıktan sonra aynı baytları gönderin. JSON'u yeniden biçimlendirmek (boşluk, alan sırası) imzayı bozar ve imza_gecersiz döner.

POST/api/sms/gonder

Serbest metinli SMS gönderir. Alıcı GOLOS kullanıcısıysa mesaj uygulamaya düşer (kanal: "golos") ve paketten düşmez; değilse SMS olarak gider ve parça sayısı kadar düşer.

{ "telefon": "0532 999 99 67", "metin": "Siparişiniz yola çıktı.", "gonderici": "ESQUIRE" }   (gonderici isteğe bağlı)

200 → { "ok": true, "kanal": "sms", "parca": 1, "kodlama": "gsm7", "karakter": 22, "paket_kalan": 984 }
200 → { "ok": true, "kanal": "golos", "parca": 0, ... }              (uygulamaya düştü, ücretsiz)
200 → { "ok": false, "error": "ulke_kapali", "engellendi": true }        (SMS Geçidi kuralı)
402 → { "ok": false, "error": "paket_bitti", "parca": 2, "paket_kalan": 1 }

Telefon numarası ülke koduyla ya da 0532… biçiminde yazılabilir; sunucu düzeltir. Metin en fazla 1000 karakterdir.

POST/api/otp/iste

Numaraya tek kullanımlık doğrulama kodu gönderir. Kod cevapta yer almaz; kullanıcı kodu size yazar, siz /api/otp/dogrula ile sorarsınız. Kod varsayılan olarak 6 hanelidir ve 3 dakika geçerlidir.

{ "telefon": "0532 999 99 67", "dil": "tr", "yontem": "sms", "sablon": "giris" }   (yontem, sablon isteğe bağlı)

200 → { "ok": true, "kanal": "sms", "ttl": 180, "parca": 1, "paket_kalan": 983 }
200 → { "ok": true, "kanal": "golos", "ttl": 180, "parca": 0 }
429 → { "ok": false, "error": "sinir_asildi", "sinir": "numara_bekleme", "bekle_sn": 41 }

POST/api/otp/dogrula

Kullanıcının yazdığı kodu doğrular. Kod bir kez doğrulanınca tükenir; yeni kod istenirse eskisi geçersiz olur.

{ "telefon": "0532 999 99 67", "kod": "482913" }

200 → { "ok": true }
401 → { "ok": false, "error": "kod_hatali", "kalan_deneme": 4 }
410 → { "ok": false, "error": "suresi_doldu" }
429 → { "ok": false, "error": "cok_deneme" }

GET/api/sms/durum/:istek_no

Bir gönderimin teslim durumunu sorar. istek_no her cevabın kaydında ve müşteri panelindeki dökümde bulunur. Anlık bildirim için webhook kullanın; bu uç doğrulama ve geriye dönük sorgu içindir.

200 → { "ok": true, "istek_no": "…", "durum": "iletildi", "kanal": "sms", "parca": 1,
        "gonderim_zamani": "2026-09-17T09:12:03.000Z", "teslim_zamani": "2026-09-17T09:12:09.000Z", "hata": null }
404 → { "ok": false, "error": "istek_yok" }
durumAnlamı
gonderildiSağlayıcı kabul etti, teslim raporu henüz gelmedi.
iletildiAlıcının telefonuna ulaştı.
iletilemediŞebeke teslim edemedi (kapalı telefon, geçersiz numara).
golosGOLOS uygulamasına düştü; anında teslim, paketten düşmedi.
engellendiSMS Geçidi kuralı gönderimi durdurdu (kapalı ülke gibi).
hataSağlayıcı reddetti; hata alanında sebep.
testTest anahtarıyla yapıldı, gerçek gönderim yok.

Hata sözlüğü

Her hata cevabı { "ok": false, "error": "<kod>" } biçimindedir. Kodlar sabittir; metne değil koda göre dallanın.

HTTPKodAnlamı ve ne yapmalı
400https_gerekliİstek HTTP ile geldi. Yalnız HTTPS kabul edilir.
400telefon_gecersizNumara 10–15 rakama çözülemedi.
400metin_gecersizMetin boş ya da 1000 karakterden uzun.
400gonderici_gecersizİstekteki gonderici adı bu hesapta onaylı değil ya da yok.
400yontem_gecersizyontem yalnız sms ya da arama olabilir.
400sablon_yokİstekteki sablon kodu bu hesapta tanımlı değil.
400idempotency_gecersizIdempotency-Key 64 karakterden uzun ya da izinsiz karakter içeriyor.
401anahtar_gecersizAnahtar kimliği tanınmadı ya da iptal edilmiş.
401anahtar_askidaAnahtar askıda: anormallik askısı ya da şikâyet; sebep panelde görünür, müşteri hizmetleri açar.
401imza_gecersizİmza tutmadı ya da nonce biçimi hatalı. İmzalanan metni ve gövde baytlarını kontrol edin.
401zaman_asimiZaman farkı 300 saniyeyi aştı. Cevaptaki sunucu_zamani ile saatinizi düzeltin.
401nonce_tekrarAynı nonce daha önce kullanıldı. Her istekte yeni nonce üretin.
401kod_hataliDoğrulama kodu yanlış; kalan_deneme kadar hak kaldı.
402paket_bittiSMS paketiniz bu mesajın parça sayısını karşılamıyor. Panelden paket alın.
403kaynak_yasakİstek, anahtarın IP listesi dışından geldi.
404istek_yokBöyle bir istek numarası bu anahtarda yok.
409idempotency_isleniyorAynı Idempotency-Key ile ilk istek hâlâ sürüyor. Kısa süre sonra tekrar deneyin.
410suresi_dolduKodun süresi geçti ya da yeni kod istendi. Yeniden kod isteyin.
422icerik_reddedildiMetin içerik politikasına takıldı: kara listedeki bir alan adı ya da bağlantıyla birlikte şifre/kart/kimlik isteyen kalıp. sebep ve eslesen alanları neyi söyler.
422idempotency_cakismaAynı Idempotency-Key farklı bir gövdeyle kullanıldı.
429sinir_asildiNumara ya da proje sınırı aşıldı; sinir hangisi olduğunu, bekle_sn ne kadar bekleneceğini söyler.
429cok_denemeKod için deneme hakkı bitti. Yeni kod isteyin.
200<geçit sebebi>Örn. ulke_kapali: istek geçerli ama SMS Geçidi kuralı gönderimi durdurdu; engellendi: true. Paketten düşmez.
503servis_hazir_degilSunucu açılıyor; birkaç saniye sonra tekrar deneyin.

Tekrar güvenliği (Idempotency-Key)

Ağ kesilince aynı SMS'in iki kez gitmesini önlemek için isteğe Idempotency-Key başlığı ekleyin (en fazla 64 karakter, A-Za-z0-9_.:-). Aynı anahtar + aynı key 24 saat boyunca ilk cevabı aynen döndürür ve cevaba Idempotent-Replayed: true başlığı eklenir; ikinci gönderim olmaz, paketten düşmez.

Idempotency-Key: siparis-48812-kargo-bildirimi

Parça sayımı ve paket

SMS uzunluğu şebeke kuralıyla sayılır: yalnız GSM-7 karakterleri kullanan metin 160 karaktere kadar 1 parça, sonrası 153'er; Türkçe karakter (ç ğ ı ö ş ü İ) ya da emoji içeren metin UCS-2 sayılır, 70 karaktere kadar 1 parça, sonrası 67'şer. Her cevap parca, kodlama ve karakter döndürür. Paketten parça sayısı kadar düşer; GOLOS'a düşen mesaj 0 parçadır.

Örnek metinKodlamaParça
Siparisiniz yola cikti. (22 karakter)gsm71
Siparişiniz yola çıktı. (22 karakter)ucs21
Türkçe karakterli 120 karakterlik metinucs22
Yalnız ASCII 320 karakterlik metingsm73

Test modu

Panelde anahtar üretirken Test anahtarı kutusunu işaretleyin; kimliği rt_test_… ile başlar. Test anahtarıyla gelen istekler sağlayıcıya gitmez, paketten düşmez, sınır uygulanmaz. Sonuç numaranın son iki hanesine göre belirlenir; doğrulama kodu her zaman 000000'dır.

Numara sonuSonuç
…01Başarılı, teslim: "edildi"
…02ok: false, error: "gonderilemedi"
…03Gönderildi ama teslim: "edilmedi"
diğerBaşarılı

Test istekleri de dökümde test sonucuyla görünür; canlıya geçerken yalnız anahtarı değiştirirsiniz.

Teslim raporu ve webhook

Panelde anahtarınıza bir HTTPS webhook adresi tanımlarsanız her teslim olayı size anında POST edilir. Webhook gizlisi panelde bir kez gösterilir; gelen isteği bu gizliyle doğrulayın.

OlayNe zaman
sms.gonderildiSağlayıcı mesajı kabul etti.
sms.iletildiTeslim raporu geldi: telefona ulaştı.
sms.iletilemediTeslim raporu geldi: ulaşmadı.
sms.golosMesaj GOLOS uygulamasına düştü (anında).
POST <webhook_url>
X-Resco-Zaman: 1758100323
X-Resco-Imza:  hex( HMAC-SHA256( webhook_gizli, zaman + "\n" + ham gövde ) )

{ "olay": "sms.iletildi", "istek_no": "…", "telefon": "90532*****67", "kanal": "sms",
  "durum": "iletildi", "teslim_zamani": "2026-09-17T09:12:09.000Z", "zaman": "2026-09-17T09:12:10.412Z" }

2xx dışı cevapta 30 saniye ve 5 dakika sonra iki kez daha denenir. Telefon numarası maskeli gelir. Her deneme panelinizde görünür.

Sınırlar

Gönderici adı

Telefonda görünen gönderici adı (örn. ESQUIRE) panelden talep edilir; sağlayıcı kaydı tamamlanınca “onaylı” olur. Onaylı adı ya projeye varsayılan olarak seçin ya da her istekte gonderici alanıyla gönderin. Onaysız ya da bilinmeyen ad 400 gonderici_gecersiz döner. Sağlayıcı o ülkede adı kabul etmezse mesaj varsayılan gönderici ile gider ve dökümde “gönderici düşüldü” görünür; GOLOS'a düşen mesaj onaylı gönderici adının kendi sohbetine düşer (örn. “ESQUIRE” sohbeti, bildirim başlığı ESQUIRE); onay yoksa “Resco” sistem sohbeti.

{ "telefon": "0532 999 99 67", "metin": "Siparişiniz yola çıktı.", "gonderici": "ESQUIRE" }
{ "telefon": "0532 999 99 67", "gonderici": "ESQUIRE" }                      (otp/iste)

Kural: 3–11 karakter, harf/rakam/boşluk, yalnız rakam olamaz. ABD ve Kanada alfanümerik gönderici adını desteklemez; bazı ülkelerde ön kayıt gerekir.

Sesli OTP ve müşteri şablonu

yontem: "arama" ile kod SMS yerine sesli aramayla okunur (sabit hatlar, SMS almayan numaralar); dil dil alanından (tr dahil). Sesli arama o anda yapılamazsa kod SMS olarak gider ve cevapta kanal gerçeği söyler: sms, arama ya da golos. Kod metnini kendiniz yazmak için panelde OTP şablonları bölümünde bir şablon (örn. giris) ve dil tanımlayın; istekte sablon ve dil verin. İstenen dil yoksa şablonun kaynak dili gider. Şablon panelden diğer dillere tek tıkla çevrilebilir.

{ "telefon": "+49 30 1234567", "yontem": "arama", "dil": "de" }
200 → { "ok": true, "kanal": "arama", "ttl": 120, "parca": 1 }

{ "telefon": "0532 999 99 67", "sablon": "giris", "dil": "de" }
200 → { "ok": true, "kanal": "sms", "ttl": 180, "parca": 1, "sablon": "giris", "dil": "de" }
400 → { "ok": false, "error": "sablon_yok" }

Şablon kuralı: {kod} zorunlu, {marka} (proje adı) ve {sure} (dakika) isteğe bağlı; en fazla 320 karakter. Sesli arama da paketten 1 birim düşer.

Güvenlik: kötüye kullanıma karşı

Anahtarınız çalınırsa zarar paketinizle sınırlıdır; ayrıca sistem anormallik askısı uygular: kısa sürede çok sayıda farklı numaraya istek, yüksek başarısızlık oranı ya da art arda içerik reddi anahtarı askıya alır (401 anahtar_askida, sebep ile). Askı panelde sebebiyle görünür; müşteri hizmetleri inceleyip açar. İçerik politikası: bağlantı içeren ve şifre/kart/kimlik isteyen metinler ile kara listedeki alan adları gönderilmez (422). İkinci doğrulama: panelde doğrulayıcı uygulaması bağlarsanız anahtar üretme/yenileme gibi işlemler SMS koduna ek uygulama kodu ister — SIM kopyalama tek başına yetmez; GOLOS kullanan hesaplarda SMS kodu zaten uygulamaya düşer. Her işlem denetim izine (kim, ne, ne zaman, hangi IP) yazılır.

422 → { "ok": false, "error": "icerik_reddedildi", "sebep": "oltalama", "eslesen": "Şifre isteyen metin + bağlantı" }
401 → { "ok": false, "error": "anahtar_askida", "sebep": "pompalama" }

Lisans, sözleşme ve fiyat

Resco Telecom bu hizmeti Almanya · ABD · Estonya lisansları kapsamında ve lisanslı sağlayıcılar üzerinden sunar. Kişisel veriler GDPR'a uygun işlenir: müşteri veri sorumlusu, Resco Telecom veri işleyendir; işlenen veri alıcı numarası (maskeli), mesaj metni (geçici), teslim durumu ve istek kayıtlarıdır. API hizmet sözleşmesi ve veri işleme maddesi ilk proje anahtarı üretilirken panelde onaylanır; onay doğrulama koduyla birlikte kayda geçer (doğrulanmış numara, tarih, sürüm, IP). Metin: rescotelecom.com/sozlesme/sms-api · Fiyatlar: rescotelecom.com/fiyat

Örnek kodlar

Üç örnek de aynı işi yapar: imzayı üretir ve /api/otp/iste çağırır. Anahtarları ortam değişkeninden okuyun; kodun içine yazmayın.

const crypto = require('crypto');
const ANAHTAR = process.env.RESCO_ANAHTAR, GIZLI = process.env.RESCO_GIZLI;

async function resco(yol, govdeObj) {
  const govde = JSON.stringify(govdeObj);
  const zaman = Math.floor(Date.now() / 1000);
  const nonce = crypto.randomBytes(16).toString('hex');
  const metin = [zaman, nonce, 'POST', yol, crypto.createHash('sha256').update(govde).digest('hex')].join('\n');
  const imza  = crypto.createHmac('sha256', GIZLI).update(metin).digest('hex');
  const r = await fetch('https://rescotelecom.com' + yol, {
    method: 'POST', body: govde,
    headers: { 'Content-Type': 'application/json', 'X-Resco-Anahtar': ANAHTAR,
               'X-Resco-Zaman': String(zaman), 'X-Resco-Nonce': nonce, 'X-Resco-Imza': imza }
  });
  return { status: r.status, json: await r.json() };
}

await resco('/api/otp/iste',    { telefon: '0532 999 99 67' });
await resco('/api/v1/otp/dogrula', { telefon: '0532 999 99 67', kod: '482913' });

Resco Telecom · rescotelecom.com · destek@rescotelecom.com · Gizlilik politikası