İYS API, hizmet sağlayıcıların kendi yazılımlarından İleti Yönetim Sistemi'ne (İYS) ticari elektronik ileti onaylarını ve retlerini kaydetmesini, bu izinleri sorgulamasını ve alıcıların İYS üzerinden yaptığı değişiklikleri geri çekmesini sağlayan REST arayüzüdür. Kısaca akış şöyledir: /oauth2/token ile jeton alırsınız, /sps/{iysCode}/brands/{brandCode}/consents ile izin eklersiniz, consents/status ile sorgularsınız, consents/changes ile değişiklikleri çekersiniz.
Bu yazı yazılımcılar için hazırlandı. Ortamları, IP kısıtlamasını, OAuth2 jetonunu, izin alanlarını, tekil ve toplu eklemeyi, sorgulamayı, pull ve push yöntemlerini ve istek limitlerini resmî dokümandaki alan adlarıyla anlatıyoruz. İYS'nin ne olduğunu ve onay kuralını bilmiyorsanız önce İYS nedir rehberine, hata mesajları için İYS API hata kodları yazısına bakın.
Başlamadan önce: API'ye kim, nasıl erişir?

Burada iki terim geçecek. Hizmet sağlayıcı, ticari ileti gönderen işletmedir. Entegratör ise İYS Entegratörleri Hakkında Tebliğ ile Bakanlıkça yetkilendirilen ve hizmet sağlayıcı adına İYS işlemlerini yapan şirkettir. İYS'nin kurumsal hizmetler sayfasına göre İLETİ paketlerinde hizmet sağlayıcı entegrasyonunu ancak bir entegratör üzerinden yapabilir; iletişim adresi sayısı 250.000'den az olan hizmet sağlayıcılar İLETİ hizmetlerine yalnızca yetkilendirdikleri entegratörler üzerinden erişir. Yani kendi kodunuzu yazsanız bile canlı erişim çoğu işletme için yetkili bir entegratörün altyapısından geçer. Entegratör seçimi ve yetkilendirme adımları için İYS entegratörü nedir yazısına bakın.
- Entegratör yetkilendirme: İLETİ+ paketi tanımlı hizmet sağlayıcı, İYS Web (hs.iys.org.tr) üzerinde Marka Yönetimi sekmesindeki "Entegratör Ekle" butonuyla yetki verir. Birden fazla entegratör yetkilendirilebilir.
- Test hesabı: Hesap sahibi veya hesap yöneticisi e-Devlet ile İYS Web'e girip "API Test Hesabı" sekmesinden sandbox bilgilerini oluşturur.
- Kodlar:
iysCodehizmet sağlayıcının,brandCodemarkanın İYS numarasıdır. Ana markanınbrandCodedeğeriiysCodeile aynıdır. Bu değerler test ve canlı ortamda farklıdır. - Şifre: İYS SSS'ye göre API erişim şifresi güvenlik politikası gereği 6 ayda bir güncellenmelidir.
Ortamlar ve IP kısıtlaması
| Ortam | Adres | Not |
|---|---|---|
| Test (sandbox) | https://api.sandbox.iys.org.tr | Yalnızca entegrasyon testi; gerçek veri, yük testi veya simülasyon yapılmaz |
| Canlı | https://api.iys.org.tr | Sözleşme sürecini tamamlamış hizmet sağlayıcılar ve iş ortakları; IP whitelist zorunlu |
- Canlı ortamda yalnızca İYS'de tanımlı IP adreslerinden istek kabul edilir; alan adı (domain) üzerinden erişim tanımlanamaz. Çıkış IP'nizi myip.iys.org.tr ile görebilir, İYS Web'deki API Erişim sekmesinden tanımlı olup olmadığını kontrol edebilirsiniz.
- Test ortamında da 16 Şubat 2022'den beri IP kısıtlaması var: subnet en düşük /29 olacak şekilde en fazla 5 IP, API Destek Platformu'na kayıtlı e-posta adresinden destek@iys.org.tr adresine bildirilir.
- Bulut ortamında çok sayıda çıkış IP'niz varsa İYS SSS, isteklerin tek bir IP'den çıkması için proxy kullanılmasını öneriyor.
- Bağlantı TLS 1.2 veya TLS 1.3 ile kurulmalıdır. İYS SSS'ye göre servislerin zaman aşımı süresi 60 saniyedir.
Kimlik doğrulama: OAuth2 jetonu
İYS, OAuth2'nin parola (Resource Owner Password) ve yenileme (refresh token) akışlarını kullanır. POST /oauth2/token uç noktası grant_type olarak yalnızca password veya refresh_token kabul eder; gövde JSON ya da form-urlencoded olabilir. Access token 2 saat (expires_in: 7200), refresh token 4 saat (refresh_expires_in: 14400) geçerlidir. Yenileme isteğinde yeni bir refresh token da döner; sonraki yenilemede yenisini kullanmalısınız. Korumalı çağrılarda başlık Authorization: Bearer <jeton> biçimindedir. Admin rolündeki kullanıcıyla API jetonu alınamaz. OAuth2 akışlarının genel mantığı için OAuth2 ve OIDC rehberimize bakabilirsiniz.
# Kimlik bilgileri ortam değişkenlerinde durur, koda yazılmaz.
curl -X POST "https://api.sandbox.iys.org.tr/oauth2/token" \
-H "Content-Type: application/json" \
-d "{\"username\":\"$IYS_USERNAME\",\"password\":\"$IYS_PASSWORD\",\"grant_type\":\"password\"}"
# Yanıt (kısaltılmış):
# {"access_token":"...","refresh_token":"...","expires_in":7200,"refresh_expires_in":14400,"token_type":"bearer"}Jeton yenileme isteğinin gövdesi:
{
"grant_type": "refresh_token",
"refresh_token": "<REFRESH_TOKEN>"
}Kullanıcı adı ve şifreyi kaynak koda yazmayın; ortam değişkeni ya da gizli anahtar yöneticisi kullanın. Bunun pratik yolları .env dosyası ve en iyi pratikler yazısında.
İzin alanları: hangi değer ne anlama gelir?
| Alan | Değerler | Kural |
|---|---|---|
| recipient | +905XXXXXXXXX veya e-posta | Telefon E.164 biçiminde, en fazla 15 karakter; e-posta 6-265 karakter, İYS'de küçük harfe çevrilir |
| type | ARAMA, MESAJ, EPOSTA | MESAJ için recipient telefon olmalı |
| recipientType | BIREYSEL, TACIR | Varsayılan BIREYSEL; aynı adres için iki tür ayrı kayıt olabilir |
| status | ONAY, RET | İlk kayıt RET olamaz; aynı durum tekrar gönderilemez |
| consentDate | YYYY-MM-DD HH:mm:ss | Türkiye saati; BIREYSEL için zorunlu, TACIR güncellemesinde zorunlu |
| source | HS_WEB, HS_MOBIL vb. | İznin nerede alındığı; TACIR güncellemesinde zorunlu |
| retailerCode | 8 haneli bayi İYS no | İsteğe bağlı; izne aracılık eden bayi |
Hizmet sağlayıcının API ile gönderebileceği source değerleri şunlardır: HS_FIZIKSEL_ORTAM, HS_ISLAK_IMZA, HS_WEB, HS_CAGRI_MERKEZI, HS_SOSYAL_MEDYA, HS_EPOSTA, HS_MESAJ, HS_MOBIL, HS_EORTAM, HS_ETKINLIK, HS_2015, HS_ATM, HS_KARAR. HS_2015 yalnızca 1 Mayıs 2015 öncesi onaylar içindir ve tarihi sadece 2015-05-01 00:00:00 olabilir. HS_KARAR hizmet sağlayıcının kendi kararıyla verdiği RET içindir ve ilk kayıtta kullanılamaz. IYS_ ile başlayan kaynaklar (ör. IYS_KISAMESAJ, IYS_MOBIL) yalnızca İYS tarafından atanır; bunları pull ve push yanıtlarında görürsünüz.
Tekil izin ekleme
POST /sps/{iysCode}/brands/{brandCode}/consents tek bir izni senkron olarak kaydeder ve başarıda transactionId ile creationDate döner. Zorunlu alanlar recipient, type, source, status ve consentDate değerleridir (TACIR ilk kayıtta source ve consentDate isteğe bağlıdır). Ticari Elektronik İletiler Yönetmeliği m.7/11 gereği İYS dışında alınan onay üç iş günü içinde İYS'ye kaydedilmelidir; API bu kuralı H467 hatasıyla uygular. Onay toplama tarafını ticari elektronik ileti onayı nasıl alınır yazısında anlattık.
curl -X POST "https://api.sandbox.iys.org.tr/sps/<IYS_CODE>/brands/<BRAND_CODE>/consents" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"recipient": "+905XXXXXXXXX",
"type": "MESAJ",
"recipientType": "BIREYSEL",
"status": "ONAY",
"source": "HS_WEB",
"consentDate": "2026-11-04 10:15:00"
}'
# Başarılı yanıt (200):
# {"transactionId":"162cc155...","creationDate":"2020-08-06 15:50:23"}Örnekteki consentDate yerine onayın gerçekten alındığı anı yazın; gelecek tarih (H162) ve 1 Mayıs 2015 öncesi tarih (H156) kabul edilmez. 21/08/2025 tarihli 3.1.1 sürümüyle gelen /v2/sps/{iysCode}/brands/{brandCode}/consents metodu aynı gövdeyi kullanır; fark şu: aynı istek gövde ve parametreleri değiştirilmeden tekrar gönderilirse aynı transactionId döner. Ağ hatasından sonra güvenle tekrar denemek istiyorsanız V2 daha uygundur.
Node.js örneği: jeton önbelleği ve izin ekleme
Aşağıdaki örnek, jetonu süresi dolana kadar bellekte tutar, gerekirse refresh token ile yeniler, tarihi Türkiye saatinde üretir ve hata durumunda HTTP durumunu, İYS hata kodunu ve X-Trace-Id başlığını loglar. REST istemcisi kurmanın genel kuralları için Node.js REST API geliştirme yazısına bakabilirsiniz.
// Node.js 18+ (yerleşik fetch). Bilgiler ortam değişkenlerinden okunur.
const BASE = process.env.IYS_BASE_URL || 'https://api.sandbox.iys.org.tr';
const IYS_CODE = process.env.IYS_CODE; // <IYS_CODE>
const BRAND_CODE = process.env.IYS_BRAND_CODE; // <BRAND_CODE>
let jeton = null; // { access, refresh, accessBitis, refreshBitis }
async function jetonIste(govde) {
const res = await fetch(`${BASE}/oauth2/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(govde),
});
if (!res.ok) throw new Error(`Jeton alınamadı: HTTP ${res.status}`);
const j = await res.json();
const simdi = Date.now();
jeton = {
access: j.access_token,
refresh: j.refresh_token, // yenilemede yeni refresh_token döner, onu saklayın
accessBitis: simdi + (j.expires_in - 60) * 1000,
refreshBitis: simdi + (j.refresh_expires_in - 60) * 1000,
};
}
async function gecerliJeton() {
if (jeton && Date.now() < jeton.accessBitis) return jeton.access;
if (jeton && Date.now() < jeton.refreshBitis) {
await jetonIste({ grant_type: 'refresh_token', refresh_token: jeton.refresh });
} else {
await jetonIste({
grant_type: 'password',
username: process.env.IYS_USERNAME,
password: process.env.IYS_PASSWORD,
});
}
return jeton.access;
}
// "YYYY-MM-DD HH:mm:ss" biçiminde Türkiye saati
function iysTarihi(d = new Date()) {
return d.toLocaleString('sv-SE', { timeZone: 'Europe/Istanbul', hour12: false });
}
async function izinEkle({ recipient, type, source, status, consentDate, retailerCode }) {
const govde = { recipient, type, source, status, consentDate, recipientType: 'BIREYSEL' };
if (retailerCode) govde.retailerCode = retailerCode; // boşsa alanı hiç göndermeyin
const res = await fetch(`${BASE}/sps/${IYS_CODE}/brands/${BRAND_CODE}/consents`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${await gecerliJeton()}`,
},
body: JSON.stringify(govde),
});
const yanit = await res.json().catch(() => ({}));
if (!res.ok) {
const kod = yanit.errors?.[0]?.code;
console.error('İYS hatası', res.status, kod, 'X-Trace-Id:', res.headers.get('x-trace-id'));
throw Object.assign(new Error(kod || `HTTP ${res.status}`), { status: res.status, kod });
}
return yanit; // { transactionId, creationDate }
}
// Örnek kullanım
izinEkle({
recipient: '+905XXXXXXXXX',
type: 'MESAJ',
source: 'HS_WEB',
status: 'ONAY',
consentDate: iysTarihi(),
}).then(console.log).catch(() => process.exit(1));Toplu (asenkron) izin ekleme ve sonucu sorgulama

Çok sayıda izni tek tek göndermek yerine POST .../consents/request ile bir seferde en fazla 1000 izin içeren bir dizi gönderebilirsiniz. Liste içinde aynı recipientType + type + recipient üçlüsü tekrar edemez (H194).
POST /sps/<IYS_CODE>/brands/<BRAND_CODE>/consents/request
[
{ "type": "EPOSTA", "source": "HS_WEB", "recipient": "ornek@alanadi.com",
"status": "ONAY", "consentDate": "2026-11-03 09:40:00", "recipientType": "BIREYSEL" },
{ "type": "MESAJ", "source": "HS_MOBIL", "recipient": "+905XXXXXXXXX",
"status": "ONAY", "consentDate": "2026-11-03 09:55:00", "recipientType": "BIREYSEL" }
]
202 yanıtı: { "requestId": "...", "subRequests": [ ... ] }
En az 300 sn sonra: GET /sps/<IYS_CODE>/brands/<BRAND_CODE>/consents/request/<REQUEST_ID>- 202 yanıtı izin eklendi demek değildir. Yalnızca listenin kuyruğa alındığını gösterir.
- Sonucu en az 300 saniye sonra
GET .../consents/request/{requestId}ile sorgulayın. Son 60 gün içindeki requestId değerleri sorgulanabilir. - Her alt istek
success(eklendi, transactionId döner),enqueue(kuyrukta) veyafailure(hata kodu ile) durumundadır. Boş yanıt, işlemin henüz bitmediği anlamına gelir. - Aynı adrese ait birden fazla hareketi (ör. önce ONAY sonra RET) aynı listede göndermeyin; bunları tekil izin ekleme ile sırayla gönderin. Aynı alıcı ve tür için aynı saniyede iki hareket gönderilmemelidir.
İzin sorgulama
Gönderimden önce bir adresin durumunu görmek ya da kendi kayıtlarınızı doğrulamak için üç metot var:
| Metot | Yol | Limit ve not |
|---|---|---|
| Tekil izin durumu | POST .../consents/status | IP başına saatte 1000 istek |
| Çoklu izin durumu | POST .../consents/{recipientType}/status/{type} | Tek istekte en fazla 1000 adres; yanıtta yalnızca ONAY olanlar listelenir |
| İzin geçmişi | POST .../consents/history | IP başına saatte 100 istek; limit en fazla 100 |
curl -X POST "https://api.sandbox.iys.org.tr/sps/<IYS_CODE>/brands/<BRAND_CODE>/consents/status" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"recipient":"+905XXXXXXXXX","recipientType":"BIREYSEL","type":"MESAJ"}'
# Yanıtta status (ONAY/RET), consentDate, source, creationDate ve transactionId döner.Değişiklikleri çekme (pull) ve anlık bildirim (push)

Alıcı, onayını İYS web sitesi, mobil uygulaması veya 3338 kısa numarası üzerinden reddedebilir. Bu değişikliği kendi sisteminize yansıtmazsanız reddeden kişiye ileti göndermeye devam etme riskiniz doğar. Bunun için iki yol var.
Pull: consents/changes
GET .../consents/changes;sourceparametresiIYS(alıcının İYS üzerinden yaptığı hareketler, varsayılan) veyaHS(sizin gönderdikleriniz) olabilir.limitvarsayılan ve en fazla 1000.- Kapsam: istek anından geriye 7 takvim günü, ancak son 60 dakika hariç. Yeni eklenen bir izni hemen göremezseniz sebep budur.
- Yanıttaki
afterdeğerini saklayın ve bir sonraki istekte gönderin; böylece kaldığınız yerden devam edersiniz. Kayıt yoksa 204 döner.
# İlk çağrı: alıcının İYS üzerinden yaptığı değişiklikler (source=IYS varsayılandır)
curl "https://api.sandbox.iys.org.tr/sps/<IYS_CODE>/brands/<BRAND_CODE>/consents/changes?source=IYS&limit=1000" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
# Sonraki çağrı: önceki yanıttaki "after" değerini saklayıp gönderin
curl "https://api.sandbox.iys.org.tr/sps/<IYS_CODE>/brands/<BRAND_CODE>/consents/changes?source=IYS&limit=1000&after=<AFTER>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Pull işini zamanlanmış bir görevle düzenli çalıştırın ve 7 günlük pencereyi kaçırmayacak sıklıkta ayarlayın. Zamanlanmış görev kurmak için cron job rehberine bakabilirsiniz.
Push: push/registration
Push, alıcının İYS üzerinden yaptığı değişiklikleri (IYS_ kaynaklı hareketler) sizin adresinize POST eder. Kullanmadan önce API Destek Platformu üzerinden İYS ile iletişime geçmeniz gerekir. Hedef adres https olmalı, POST kabul etmeli ve Basic Authentication ile korunmalıdır; 5 saniye içinde yanıt vermezse zaman aşımı sayılır. Her type için en fazla 2 aktif bağlantı tanımlanabilir. Bağlantı kurulunca İYS bir test verisi gönderir.
POST /sps/<IYS_CODE>/brands/<BRAND_CODE>/push/registration
{
"connection": [
{
"url": "https://ornek-alanadi.com/iys/push",
"type": "MESAJ",
"username": "<PUSH_KULLANICI>",
"password": "<PUSH_SIFRE>"
}
]
}İstek limitleri ve başarı oranı kuralı
| Kapsam | Limit (canlı ortam) | Aşımda |
|---|---|---|
| Tüm istekler | IP başına saniyede 10 istek | 429, H124 veya H083 |
| Tekil izin durumu sorgulama | IP başına saatte 1000 istek | 429, H086 |
| İzin geçmişi listeleme | IP başına saatte 100 istek | 429, H089 |
| Jeton alma | IP başına saatte 100 istek (metot açıklamasında 10) | 429, H084 |
Bir kural daha var: canlı ortamda son 24 saatte 20.000 ve üzeri istek yapılırsa ve başarılı istek oranı %70'in altına düşerse bildirim yapılır. Bildirimden sonraki 96 saat içinde oran %70'in üzerine çıkmazsa hatalı istek gönderen IP whitelist'ten çıkarılır. Hesaba katılan hatalar istemci kaynaklı HTTP 400, 401, 403, 404 ve 422 yanıtlarıdır. Bu yüzden hatalı veriyi körü körüne tekrar göndermek tehlikelidir. İstek sıklığını sınırlama yöntemleri için API rate limiting stratejileri yazısına bakın.
Canlıya geçiş kontrol listesi
- Entegratör yetkilendirmesi ve canlı erişim bilgileri hazır, çıkış IP'si İYS'de tanımlı.
- Jeton önbellekte tutuluyor, refresh token ile yenileniyor, şifre ortam değişkeninde.
- Telefonlar
+905XXXXXXXXXbiçimine normalize ediliyor, e-postalar doğrulanıyor. - Boş alanlar gövdeden çıkarılıyor; null veya boş string gönderilmiyor.
- İYS dışında alınan onaylar üç iş günü içinde gönderiliyor; kuyruk birikirse alarm üretiliyor.
- Toplu gönderimlerin sonucu requestId ile sorgulanıyor; failure satırları ayrıca işleniyor.
- Pull ya da push ile retler kendi sisteminize düzenli işleniyor.
- Her istek ve yanıt
X-Trace-Idile birlikte loglanıyor (jeton ve şifre loglanmıyor).
İstemci güvenliğiyle ilgili genel öneriler için REST API güvenlik rehberine de göz atabilirsiniz.
Sık Sorulan Sorular
İYS API'yi entegratör olmadan doğrudan kullanabilir miyim?
İYS kurumsal hizmetler sayfasına göre İLETİ paketlerinde entegrasyon ancak bir entegratör üzerinden yapılabilir ve 250.000'den az iletişim adresi olan hizmet sağlayıcılar İLETİ hizmetlerine yalnızca yetkilendirdikleri entegratörler üzerinden erişir. Daha büyük hizmet sağlayıcılar için İYS ile iletişime geçmek gerekir. Ayrıntılar entegratör yazımızda.
Pull servisinde yeni eklediğim izni neden göremiyorum?
Pull servisi son 60 dakikayı kapsamaz. İYS SSS de son 1 saat içinde eklenen izinlerin pull servisinde listelenmediğini belirtiyor. Bir saat sonra tekrar deneyin ya da durumu tekil sorgu ile kontrol edin.
Sandbox ile canlıda aynı iysCode değerini kullanabilir miyim?
Hayır. İYS SSS'ye göre iysCode ve brandCode test ve canlı ortam için farklıdır. Bu değerleri yapılandırma dosyasında ortama göre ayrı tutun.
İzin silinebilir mi?
Spesifikasyonda izin silme metodu yoktur. İzin silinmez; durumu RET olarak güncellenir. Reddin kurallarını İYS ret bildirimi yazısında anlattık.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: İYS nedir · İYS API hata kodları · İYS entegratörü nedir · ViA ile İYS üzerinden onay toplama · Ticari ileti onayı nasıl alınır · Onay kaydı saklama ve ispat · Entegrasyon nedir