Storex API v2.1

Storex

Giriş

Storex API, sipariş yönetimi, ürün kataloğu, stok/fiyat güncelleme ve webhook bildirimleri ile tam entegrasyon sağlar.

ℹ️
Tüm API isteklerinizde API anahtarınızı X-API-KEY başlığında göndermelisiniz.
🌐
API Yolu: https://siteniz.com/api/{endpoint}
📋
Tüm yanıtlar Content-Type: application/json; charset=utf-8 formatındadır. Her yanıtta durum, mesaj ve başarılı isteklerde veri alanı bulunur.
🔒
API sadece HTTPS üzerinden erişilebilir. HTTP istekleri otomatik olarak reddedilir. Yanıt header'larında X-API-Version ile mevcut API versiyonu döner.

Kimlik Doğrulama

API'ye erişim için bir API anahtarı gereklidir. Anahtarınızı her istekte X-API-KEY header'ı ile gönderin.

  1. Yönetici panelinize giriş yapın
  2. Sağ üst köşedeki 🔑 API anahtarı ikonuna tıklayın
  3. API anahtarınızı kopyalayın
// Her istekte gönderilmesi gereken header
X-API-KEY: sizin-api-anahtariniz

// Veya programatik olarak /api/yonetimGiris endpoint'i ile anahtar alabilirsiniz
⚠️
API anahtarınız 1 yıl geçerlidir ve her başarılı istekte otomatik yenilenir. Anahtarınızı güvenli saklayın, paylaşmayın.

Rate Limiting

Kötüye kullanımı önlemek için istek sınırlaması uygulanmaktadır.

Her IP adresi için dakikada maksimum 60 istek gönderilebilir.

Her yanıtta rate limit bilgileri header olarak döner:

X-RateLimit-Limit: 60          // Maksimum istek sayısı
X-RateLimit-Remaining: 55      // Kalan istek hakkı
X-RateLimit-Reset: 1709712345  // Limitin sıfırlanacağı Unix timestamp
❌ Limit Aşıldığında (429)
{
  "durum": false,
  "mesaj": "Çok fazla istek gönderdiniz. Lütfen 60 saniye sonra tekrar deneyin."
}

HTTP Durum Kodları

API'nin döndürdüğü HTTP durum kodları ve anlamları:

200 Başarılı
201 Oluşturuldu
400 Geçersiz İstek
401 Yetkisiz
404 Bulunamadı
405 Method Hatası
429 Çok Fazla İstek
500 Sunucu Hatası

Sayfalama (Pagination)

Liste dönen endpoint'lerde sayfalama bilgileri hem yanıt gövdesinde hem de HTTP header'larında döner.

// Yanıt Header'ları
X-Total-Count: 150    // Toplam kayıt sayısı
X-Page: 1             // Mevcut sayfa
X-Per-Page: 10        // Sayfa başına kayıt
X-Total-Pages: 15     // Toplam sayfa sayısı

// Yanıt Gövdesi
{
  "veri": {
    "siparisler": [...],
    "toplamSiparis": 150,
    "sayfaSayisi": 15,
    "mevcutSayfa": 1
  }
}

// Kullanım: ?limit=20&sayfa=2 (maksimum limit: 100)

Yönetim Kimlik

POST /api/yonetimGiris Yönetim paneli girişi & API anahtarı alma

Yönetim paneli kullanıcısının giriş bilgilerini doğrular ve API anahtarı oluşturur. Bu endpoint sadece panel yöneticileri içindir.

⚠️
Bu endpoint yönetim paneli girişi içindir. Son kullanıcı (müşteri) girişi için /api/musteriGiris endpoint'ini kullanın.
📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
kullaniciAdistringZorunluPanel kullanıcı adı
sifrestringZorunluPanel kullanıcı şifresi
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Giriş başarılı",
  "veri": {
    "kullanici": {
      "id": 1,
      "kullaniciAdi": "admin",
      "tip": 1,
      "telefon": "5551234567"
    },
    "apiAnahtari": {
      "anahtar": "e5fb6cde8a7542c889bc73160aed26e9...",
      "sonKullanim": "2027-03-06 15:30:42"
    }
  }
}
❌ Başarısız Yanıt (401)
{
  "durum": false,
  "mesaj": "Kullanıcı adı veya şifre hatalı"
}

Sipariş Yönetimi

Sipariş listeleme, detay görüntüleme, filtreleme, durum güncelleme ve istatistik işlemleri.

GET /api/siparisler Siparişleri listele

Sistemdeki siparişleri sayfalı olarak listeler. Ödeme yöntemi, kupon, fatura bilgileri dahil.

📥 Parametreler (Query String)
ParametreTürDurumAçıklama
limitintOpsiyonelSayfa başına sipariş (varsayılan: 10, maks: 100)
sayfaintOpsiyonelSayfa numarası (varsayılan: 1)
durumintOpsiyonelSipariş durum kodu ile filtrele
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Siparişler başarıyla alındı",
  "veri": {
    "siparisler": [
      {
        "id": "999",
        "sipID": "123456789012",
        "ad": "Ali",
        "soyad": "Veli",
        "telefon": "05551234567",
        "email": "ornek@example.com",
        "adres": "Örnek Mahallesi No: 123",
        "il": "Ankara",
        "ilce": "Çankaya",
        "siparis_tarihi": "1623456789",
        "urun_tutar": "500.00",
        "kargo_tutar": "10.00",
        "kdv_tutar": "90.00",
        "toplam_tutar": "600.00",
        "kargo_adi": "Örnek Kargo",
        "kargo_kodu": "KRG123456",
        "durum": "1",
        "siparis_notu": "Örnek not",
        "odeme_yontemi": "1",
        "odeme_yontemi_metni": "Kredi Kartı",
        "kupon_kodu": "INDIRIM10",
        "kupon_indirimi": "50.00",
        "premium_indirim": "0.00",
        "vergi_dairesi": "Çankaya VD",
        "vergi_numarasi": "1234567890",
        "fatura_adres": "Fatura adresi...",
        "fatura": "1",
        "kredi_karti_odendi": "1",
        "cihaz_tipi": "desktop",
        "bayi_tipi": "",
        "yonetici_notu": "",
        "siparis_tarihi_formati": "01.01.2025 12:00:00",
        "durum_metni": "Ödeme Bekliyor"
      }
    ],
    "toplamSiparis": 25,
    "sayfaSayisi": 3,
    "mevcutSayfa": 1
  }
}
GET /api/siparis Sipariş detayı getir

Sipariş detayını, ürünlerini (varyant ve kampanya bilgileri dahil), kargo takip bilgilerini getirir.

📥 Parametreler
ParametreTürDurumAçıklama
idintZorunluSipariş ID'si
📦
Sipariş detayında her ürün için varyant bilgileri (renk, beden vb.), kampanya bilgileri (indirim oranı/tutarı) ve ürün görseli de döner.
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Sipariş detayı başarıyla alındı",
  "veri": {
    "siparis": {
      "id": "145",
      "sipID": "987654321012",
      "ad": "Ahmet",
      "soyad": "Yılmaz",
      "telefon": "05553334455",
      "email": "ahmet@example.com",
      "adres": "Atatürk Caddesi No: 10",
      "il": "Ankara",
      "ilce": "Çankaya",
      "siparis_tarihi": "1743623490",
      "urun_tutar": "1500.00",
      "kargo_tutar": "10.00",
      "kdv_tutar": "150.00",
      "toplam_tutar": "1660.00",
      "durum": "1",
      "odeme_yontemi": "1",
      "odeme_yontemi_metni": "Kredi Kartı",
      "kupon_kodu": "",
      "kupon_indirimi": "0.00",
      "premium_indirim": "0.00",
      "kredi_karti_odendi": "1",
      "vergi_dairesi": "",
      "vergi_numarasi": "",
      "fatura_adres": "",
      "fatura": "0",
      "tc": "",
      "cihaz_tipi": "mobile",
      "bayi_tipi": "",
      "yonetici_notu": "",
      "MagazadanTeslimat": "0",
      "siparis_notu": "Lütfen akşam teslim edin",
      "siparis_tarihi_formati": "03.05.2025 15:30:00",
      "durum_metni": "Ödeme Bekliyor"
    },
    "urunler": [
      {
        "id": "300",
        "siparis_id": "145",
        "urun_id": "700",
        "fiyat": "750.00",
        "adet": "2",
        "secenek": "0",
        "kargo_fiyati": "5.00",
        "hediye": "0",
        "magaza_id": "0",
        "urun_adi": "Mavi Kot Pantolon",
        "urun_aciklama": "Ürün açıklaması...",
        "barkod": "8680001234567",
        "stok_kodu": "MKP-001",
        "kdv_orani": "20",
        "urun_gorsel": "upload/urunler/mavi-kot.jpg",
        "varyantlar": [
          {
            "SecenekBaslik": "Beden",
            "SecenekAltBaslik": "M",
            "SecenekFiyat": "0.00"
          },
          {
            "SecenekBaslik": "Renk",
            "SecenekAltBaslik": "Mavi",
            "SecenekFiyat": "0.00"
          }
        ],
        "kampanya": {
          "KampanyaAdi": "Yaz İndirimi",
          "IndirimTutari": "75.00",
          "IndirimOrani": "10"
        }
      }
    ],
    "kargo_bilgisi_var": true,
    "kargoTakip": [
      {
        "id": "90",
        "kargo_adi": "Yurtiçi Kargo",
        "kargo_no": "22222",
        "link": "yurticikargo.com"
      }
    ]
  }
}
GET /api/siparisFiltrele Siparişleri filtrele

Çeşitli kriterlere göre siparişleri filtrelemenizi sağlar. Ödeme yöntemi, tutar aralığı ve il bazlı filtreleme desteği.

📥 Parametreler
ParametreTürDurumAçıklama
limitintOpsiyonelSayfa başına sipariş (varsayılan: 10, maks: 100)
sayfaintOpsiyonelSayfa numarası (varsayılan: 1)
durumintOpsiyonelSipariş durum kodu
baslangicTarihistringOpsiyonelBaşlangıç tarihi (YYYY-AA-GG)
bitisTarihistringOpsiyonelBitiş tarihi (YYYY-AA-GG)
aramastringOpsiyonelSipariş ID, ad, telefon veya e-posta ile arama
odemeYontemiintOpsiyonelÖdeme yöntemi kodu (1-7)
minTutarfloatOpsiyonelMinimum sipariş tutarı
maxTutarfloatOpsiyonelMaksimum sipariş tutarı
ilstringOpsiyonelİl bazlı filtreleme
✅ Başarılı Yanıt (200)
// Örnek: /api/siparisFiltrele?durum=4&baslangicTarihi=2025-01-01&odemeYontemi=1&minTutar=100
{
  "durum": true,
  "mesaj": "Siparişler başarıyla filtrelendi",
  "veri": {
    "siparisler": [ ... ],
    "toplamSiparis": 8,
    "sayfaSayisi": 1,
    "mevcutSayfa": 1
  }
}
POST /api/siparisDurumGuncelle Sipariş durumunu güncelle

Belirtilen siparişin durumunu günceller. Kargo bilgisi eklenebilir. Kayıtlı webhook'lara otomatik bildirim gönderilir.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
siparisIdintZorunluSipariş ID'si
durumintZorunluYeni durum kodu (bkz. Sipariş Durumları)
kargoAdistringOpsiyonelKargo firma adı
kargoKodustringOpsiyonelKargo takip numarası
🔔
Durum güncellendiğinde, kayıtlı tüm webhook URL'lerine siparis.durum_degisti olayı ile bildirim gönderilir.
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Sipariş durumu güncellendi",
  "veri": {
    "eskiDurum": 1,
    "yeniDurum": 4,
    "durumMetni": "Kargoda"
  }
}
GET /api/siparisIstatistikleri Sipariş istatistikleri

Toplam sipariş sayısı, ciro, bugünkü ve bu ayki sipariş özeti ile durum dağılımını getirir.

✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Sipariş istatistikleri",
  "veri": {
    "toplamSiparis": 1250,
    "toplamCiro": "485000.00",
    "bugun": {
      "siparisSayisi": 12,
      "ciro": "4500.00"
    },
    "buAy": {
      "siparisSayisi": 180,
      "ciro": "72000.00"
    },
    "durumDagilimi": [
      { "durumKodu": 1, "durumMetni": "Ödeme Bekliyor", "adet": 15, "toplamTutar": "6000.00" },
      { "durumKodu": 4, "durumMetni": "Kargoda", "adet": 42, "toplamTutar": "18500.00" },
      { "durumKodu": 5, "durumMetni": "Tamamlandı", "adet": 980, "toplamTutar": "390000.00" }
    ]
  }
}

Ürün Yönetimi

Ürün listeleme, detay, arama, stok kontrol ve güncelleme işlemleri.

GET /api/urunler Ürünleri listele

Aktif ürünleri sayfalı olarak listeler. Kategori, marka ve arama ile filtrelenebilir.

📥 Parametreler
ParametreTürDurumAçıklama
limitintOpsiyonelSayfa başına ürün (varsayılan: 10, maks: 100)
sayfaintOpsiyonelSayfa numarası
kategoriintOpsiyonelKategori ID ile filtrele
markaintOpsiyonelMarka ID ile filtrele
aramastringOpsiyonelÜrün adı, barkod veya stok kodu ile arama
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "veri": {
    "urunler": [
      {
        "UrunId": 100,
        "UrunAdi": "Mavi Kot Pantolon",
        "SefLink": "mavi-kot-pantolon",
        "KisaAciklama": "Slim fit erkek kot pantolon",
        "Fiyat": "299.90",
        "EskiFiyat": "399.90",
        "Stok": 45,
        "StokKodu": "MKP-001",
        "Barkod": "8680001234567",
        "Kdv": "20",
        "KargoFiyati": "0.00",
        "MarkaId": 5,
        "MarkaAdi": "Levi's",
        "Mensei": "Türkiye",
        "Durum": "1",
        "OlusturmaTarihi": "2025-01-15 10:30:00",
        "GuncellemeTarihi": "2025-03-01 14:20:00",
        "AnaGorsel": "upload/urunler/mavi-kot.jpg",
        "Kategoriler": [
          { "id": 10, "baslik": "Erkek Giyim" },
          { "id": 15, "baslik": "Pantolonlar" }
        ]
      }
    ],
    "toplamUrun": 350,
    "sayfaSayisi": 35,
    "mevcutSayfa": 1
  }
}
GET /api/urun Ürün detayı getir

Ürünün tüm detaylarını, görsellerini, kategorilerini, varyant gruplarını ve kombinasyonlarını getirir.

📥 Parametreler
ParametreTürDurumAçıklama
idintZorunluÜrün ID'si
✅ Başarılı Yanıt (200) - Kısaltılmış
{
  "durum": true,
  "veri": {
    "urun": {
      "UrunId": 100,
      "UrunAdi": "Mavi Kot Pantolon",
      "Fiyat": "299.90",
      "EskiFiyat": "399.90",
      "Stok": 45,
      "Kdv": "20",
      "Barkod": "8680001234567",
      "StokKodu": "MKP-001",
      "UrunDesi": "3",
      "AsgariAdet": "1",
      "UrunPuan": "4.5",
      "Goruntulenme": "1250",
      "KampanyaBaslangic": "2025-01-01",
      "KampanyaBitis": "2025-12-31",
      "Durum": "1",
      "...": "diğer alanlar"
    },
    "gorseller": [
      { "id": 1, "Resim": "upload/urunler/mavi-kot-1.jpg", "Sira": 1 },
      { "id": 2, "Resim": "upload/urunler/mavi-kot-2.jpg", "Sira": 2 }
    ],
    "kategoriler": [
      { "id": 10, "baslik": "Erkek Giyim", "sef": "erkek-giyim" }
    ],
    "varyantlar": [
      {
        "grupId": 1,
        "grupAdi": "Beden",
        "secenekler": [
          { "Id": 1, "SecenekAdi": "S", "RenkKodu": null, "Sira": 1 },
          { "Id": 2, "SecenekAdi": "M", "RenkKodu": null, "Sira": 2 },
          { "Id": 3, "SecenekAdi": "L", "RenkKodu": null, "Sira": 3 }
        ]
      },
      {
        "grupId": 2,
        "grupAdi": "Renk",
        "secenekler": [
          { "Id": 10, "SecenekAdi": "Mavi", "RenkKodu": "#0066CC", "Sira": 1 },
          { "Id": 11, "SecenekAdi": "Siyah", "RenkKodu": "#000000", "Sira": 2 }
        ]
      }
    ],
    "kombinasyonlar": [
      {
        "Id": 50,
        "StokKodu": "MKP-001-M-MAVI",
        "Barkod": "8680001234568",
        "Stok": 15,
        "EkFiyat": "0.00",
        "VaryantResim": "",
        "secenekler": [
          { "GrupId": 1, "GrupAdi": "Beden", "SecenekId": 2, "SecenekAdi": "M" },
          { "GrupId": 2, "GrupAdi": "Renk", "SecenekId": 10, "SecenekAdi": "Mavi" }
        ]
      }
    ]
  }
}
GET /api/urunAra Ürün arama

Ürün adı, barkod veya stok kodu ile hızlı arama yapar.

📥 Parametreler
ParametreTürDurumAçıklama
aramastringZorunluArama kelimesi
limitintOpsiyonelSonuç limiti (varsayılan: 20, maks: 50)
GET /api/stokKontrol Stok kontrol

Ürün veya kombinasyon bazında stok bilgisini sorgular.

📥 Parametreler
ParametreTürDurumAçıklama
urunIdintZorunluÜrün ID'si
kombinasyonIdintOpsiyonelVaryant kombinasyon ID'si
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Stok bilgisi",
  "veri": {
    "stok": 45,
    "stokKodu": "MKP-001",
    "barkod": "8680001234567",
    "stokVar": true
  }
}
POST /api/stokGuncelle Stok güncelle

Ürün veya kombinasyon bazında stok miktarını günceller.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
urunIdintZorunluÜrün ID'si
stokintZorunluYeni stok miktarı (0 veya üzeri)
kombinasyonIdintOpsiyonelVaryant kombinasyon ID'si
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Ürün stoğu güncellendi",
  "veri": { "yeniStok": 100 }
}
POST /api/fiyatGuncelle Fiyat güncelle

Ürün veya kombinasyon bazında fiyat günceller. Eski fiyat (üstü çizili fiyat) da ayarlanabilir.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
urunIdintZorunluÜrün ID'si
fiyatfloatZorunluYeni satış fiyatı
eskiFiyatfloatOpsiyonelEski fiyat (üstü çizili gösterim)
kombinasyonIdintOpsiyonelVaryant kombinasyon ID'si (ek fiyat günceller)
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Ürün fiyatı güncellendi",
  "veri": {
    "oncekiFiyat": "299.90",
    "yeniFiyat": 249.90
  }
}

Katalog

GET /api/kategoriler Kategorileri listele

Aktif kategorileri listeler. Üst kategori ID ile alt kategoriler filtrelenebilir.

📥 Parametreler
ParametreTürDurumAçıklama
ustKategoriintOpsiyonelÜst kategori ID (alt kategorileri getir)
GET /api/markalar Markaları listele

Aktif markaları ve her markadaki ürün sayısını listeler.

Müşteri / Mobil Uygulama İşlemleri

Mobil uygulama ve müşteri tarafı işlemleri için kullanılan endpoint'ler.

📱
Kimlik Doğrulama:
musteriGiris, musteriKayit, musteriOturumDogrula, musteriOturumYenile, musteriCikis → Kimlik doğrulama gerektirmez
• Diğer müşteri endpoint'leri iki yöntemle çalışır:
  1. Bearer Token (Mobil Uygulama): Authorization: Bearer <oturum_token> — kullanıcı ID otomatik belirlenir
  2. API Anahtarı (Entegrasyon): X-API-KEY: <anahtar>kullaniciId parametresi gerekir
POST /api/musteriGiris Müşteri girişi (e-posta veya telefon)

Müşteri e-posta veya telefon numarası ile giriş yapar. API anahtarı gerektirmez. Başarılı girişte oturum token'ı döner.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
emailTelefonstringZorunluE-posta adresi veya telefon numarası
sifrestringZorunluMüşteri şifresi
beniHatirlaboolOpsiyoneltrue = 30 gün, false = 5 gün oturum süresi
📱
Dönen oturum.token değerini mobil uygulamada saklayın. Sonraki isteklerde musteriOturumDogrula ile oturumu kontrol edin. Süre dolmadan musteriOturumYenile ile uzatın.
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Giriş başarılı",
  "veri": {
    "kullanici": {
      "id": 42,
      "ad": "Ali",
      "soyad": "Yılmaz",
      "email": "ornek@example.com",
      "telefon": "05551234567",
      "il": "İstanbul",
      "ilce": "Kadıköy",
      "bakiye": "150.00",
      "kayitTarihi": "15.01.2024 10:30"
    },
    "oturum": {
      "token": "a1b2c3d4e5f6...",
      "sureSaat": 120,
      "bitisTarihi": "2026-03-11 15:30:00"
    }
  }
}
❌ Başarısız Yanıt (401)
{
  "durum": false,
  "mesaj": "E-posta/telefon veya şifre hatalı"
}
POST /api/musteriKayit Yeni müşteri kaydı

Yeni müşteri hesabı oluşturur. API anahtarı gerektirmez.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
adstringZorunluMüşteri adı
soyadstringOpsiyonelMüşteri soyadı
emailstringZorunluE-posta adresi
telefonstringOpsiyonelTelefon numarası
sifrestringZorunluŞifre (min 6 karakter)
✅ Başarılı Yanıt (201)
{
  "durum": true,
  "mesaj": "Kayıt başarılı",
  "veri": {
    "kullaniciId": 43,
    "oturum": {
      "token": "f7e8d9c0b1a2...",
      "sureSaat": 120,
      "bitisTarihi": "2026-03-11 15:30:00"
    }
  }
}
❌ Başarısız Yanıt (400)
{
  "durum": false,
  "mesaj": "Bu e-posta adresi zaten kayıtlı"
}
POST /api/musteriOturumDogrula Oturum token doğrulama

Mobil uygulamada saklanan oturum token'ının hâlâ geçerli olup olmadığını kontrol eder. Uygulama açılışında çağırın.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
tokenstringZorunluGiriş sırasında alınan oturum token'ı
✅ Geçerli Oturum (200)
{
  "durum": true,
  "mesaj": "Oturum geçerli",
  "veri": {
    "kullanici": { "id": 42, "ad": "Ali", "soyad": "Yılmaz", ... }
  }
}
❌ Süresi Dolmuş (401)
{
  "durum": false,
  "mesaj": "Oturum süresi dolmuş veya geçersiz token"
}
POST /api/musteriOturumYenile Oturum süresini uzat

Mevcut oturum token'ını yenisiyle değiştirir ve süreyi 5 gün daha uzatır. Eski token geçersiz olur.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
tokenstringZorunluMevcut oturum token'ı
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Oturum yenilendi",
  "veri": {
    "oturum": {
      "token": "yeni-token-degeri...",
      "sureSaat": 120,
      "bitisTarihi": "2026-03-16 15:30:00"
    }
  }
}
POST /api/musteriCikis Çıkış yap

Oturum token'ını geçersiz kılar. Mobil uygulamada çıkış yapıldığında çağırın.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
tokenstringZorunluGeçersiz kılınacak oturum token'ı
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Çıkış yapıldı"
}
GET /api/musteriProfil Müşteri profil bilgileri

Müşterinin profil bilgilerini getirir.

🔐
Bearer token ile çağrıldığında kullaniciId parametresi gerekmez, token'dan otomatik belirlenir.
📥 Parametreler (Query String)
ParametreTürDurumAçıklama
kullaniciIdintAPI Key ile zorunluMüşteri ID (Bearer token ile opsiyonel)
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Profil bilgileri",
  "veri": {
    "kullanici": {
      "id": 42,
      "ad": "Ali",
      "soyad": "Yılmaz",
      "email": "ornek@example.com",
      "telefon": "05551234567",
      "il": "İstanbul",
      "ilce": "Kadıköy",
      "adres": "Örnek Mah. No:5",
      "tc": "",
      "dogum_yili": "1990",
      "vergi_dairesi": "",
      "vergi_numarasi": "",
      "bakiye": "150.00",
      "kayit_tarihi": "2024-01-15"
    }
  }
}
POST /api/musteriProfilGuncelle Profil bilgilerini güncelle

Müşterinin profil bilgilerini günceller. Sadece gönderilen alanlar güncellenir.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
adstringOpsiyonelAd
soyadstringOpsiyonelSoyad
telefonstringOpsiyonelTelefon
emailstringOpsiyonelE-posta
tcstringOpsiyonelTC Kimlik No
ilstringOpsiyonelİl
ilcestringOpsiyonelİlçe
adresstringOpsiyonelAdres
dogum_yilistringOpsiyonelDoğum yılı
vergi_dairesistringOpsiyonelVergi dairesi
vergi_numarasistringOpsiyonelVergi numarası
fatura_adresstringOpsiyonelFatura adresi
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Profil güncellendi",
  "veri": {
    "kullanici": {
      "id": 42,
      "ad": "Ali",
      "soyad": "Yılmaz",
      "email": "ornek@example.com",
      "telefon": "05559998877"
    }
  }
}
POST /api/musteriSifreDegistir Şifre değiştir

Müşterinin şifresini değiştirir. Eski şifre doğrulaması yapılır.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
eskiSifrestringZorunluMevcut şifre
yeniSifrestringZorunluYeni şifre (min 6 karakter)
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Şifre başarıyla değiştirildi"
}
GET /api/musteriAdresler Adres listesi

Müşterinin kayıtlı adreslerini listeler. Tip parametresi ile teslimat/fatura adresleri filtrelenebilir.

📥 Parametreler (Query String)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
tipintOpsiyonel1=Teslimat, 2=Fatura
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Adres listesi",
  "veri": {
    "adresler": [
      {
        "id": 10,
        "baslik": "Ev Adresim",
        "ad": "Ali",
        "soyad": "Yılmaz",
        "telefon": "05551234567",
        "acik_adres": "Örnek Mah. Atatürk Cad. No:5",
        "il": "İstanbul",
        "ilce": "Kadıköy",
        "tip": 1,
        "varsayilan": 1,
        "kurumsal_tip": 0,
        "firma_adi": "",
        "vergi_dairesi": "",
        "vergi_numarasi": ""
      }
    ]
  }
}
POST /api/musteriAdresEkle Yeni adres ekle

Müşteriye yeni adres ekler. Bireysel ve kurumsal adres tipleri desteklenir.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
adstringZorunluAlıcı adı
soyadstringOpsiyonelAlıcı soyadı
epostastringOpsiyonelE-posta
telefonstringOpsiyonelTelefon
baslikstringOpsiyonelAdres başlığı (Ev, İş vb.)
acik_adresstringZorunluAçık adres
ilstringZorunluİl
ilcestringOpsiyonelİlçe
tipintOpsiyonel1=Teslimat, 2=Fatura (varsayılan: 1)
tckimlikstringOpsiyonelTC Kimlik No
firma_adistringOpsiyonelFirma adı (kurumsal)
vergi_dairesistringOpsiyonelVergi dairesi (kurumsal)
vergi_numarasistringOpsiyonelVergi numarası (kurumsal)
varsayilanintOpsiyonel1=Varsayılan adres yap
kurumsal_tipintOpsiyonel0=Bireysel, 1=Kurumsal
✅ Başarılı Yanıt (201)
{
  "durum": true,
  "mesaj": "Adres başarıyla eklendi",
  "veri": {
    "adresId": 15
  }
}
POST /api/musteriAdresGuncelle Adres güncelle

Mevcut bir adresi günceller. Sadece gönderilen alanlar güncellenir.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
adresIdintZorunluAdres ID
Diğer parametreler Adres Ekle ile aynıdır (hepsi opsiyonel)
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Adres başarıyla güncellendi",
  "veri": {
    "adres": { "id": 10, "baslik": "Ev Adresim", "acik_adres": "Yeni adres..." }
  }
}
POST /api/musteriAdresSil Adres sil

Müşterinin bir adresini siler. Adres müşteriye ait olmalıdır.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
adresIdintZorunluSilinecek adres ID
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Adres başarıyla silindi"
}
GET /api/musteriSiparisler Müşterinin siparişleri

Müşterinin sipariş geçmişini sayfalı olarak listeler. Her sipariş için ürün detayları dahildir.

📥 Parametreler (Query String)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
limitintOpsiyonelSayfa başına sipariş (varsayılan: 10, maks: 50)
sayfaintOpsiyonelSayfa numarası (varsayılan: 1)
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Siparişler listelendi",
  "veri": {
    "siparisler": [
      {
        "id": "145",
        "sipID": "987654321012",
        "toplam_tutar": "1660.00",
        "durum_metni": "Kargoya Verildi",
        "siparis_tarihi_formati": "03.05.2025 15:30:00",
        "urunler": [
          {
            "urun_adi": "Mavi Kot Pantolon",
            "adet": "2",
            "fiyat": "750.00",
            "urun_gorsel": "upload/urunler/mavi-kot.jpg"
          }
        ]
      }
    ],
    "toplam": 12,
    "sayfaSayisi": 2,
    "mevcutSayfa": 1
  }
}
GET /api/musteriFavoriler Favori ürünler

Müşterinin favori listesindeki ürünleri getirir.

📥 Parametreler (Query String)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Favori listesi",
  "veri": {
    "favoriler": [
      {
        "urun_id": 700,
        "urun_adi": "Mavi Kot Pantolon",
        "fiyat": "750.00",
        "eski_fiyat": "900.00",
        "gorsel": "upload/urunler/mavi-kot.jpg",
        "stok": 25
      }
    ]
  }
}
POST /api/musteriFavoriToggle Favori ekle/çıkar

Ürünü favorilere ekler veya favorilerden çıkarır (toggle). Ürün favorilerdeyse çıkarır, değilse ekler.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
urunIdintZorunluÜrün ID
✅ Başarılı Yanıt (200)
// Favoriye eklendi
{
  "durum": true,
  "mesaj": "Ürün favorilere eklendi",
  "veri": { "islem": "eklendi" }
}

// Favoriden çıkarıldı
{
  "durum": true,
  "mesaj": "Ürün favorilerden çıkarıldı",
  "veri": { "islem": "cikarildi" }
}
GET /api/musteriBakiye Bakiye sorgula

Müşterinin mevcut bakiye bilgisini getirir.

📥 Parametreler (Query String)
ParametreTürDurumAçıklama
kullaniciIdintZorunluMüşteri ID
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Bakiye bilgisi",
  "veri": {
    "bakiye": "150.00",
    "paraFormatli": "₺150,00"
  }
}

Webhook Yönetimi

Webhook'lar sayesinde sipariş, stok ve fiyat değişikliklerinde otomatik olarak sizin belirlediğiniz URL'ye bildirim gönderilir.

🔔
Webhook Nasıl Çalışır?
1. /api/webhookKaydet ile HTTPS URL'nizi ve dinlemek istediğiniz olayları kaydedin
2. İlgili olay gerçekleştiğinde URL'nize POST isteği gönderilir
3. İstek header'ında X-Webhook-Signature ile HMAC-SHA256 imzası bulunur
4. Başarısız teslimatlar otomatik olarak 3 kez tekrar denenir (exponential backoff)
5. 9 ardışık başarısız teslimat sonrası webhook otomatik devre dışı bırakılır
📋
Desteklenen Olaylar: siparis.olusturuldu, siparis.durum_degisti, siparis.iptal, siparis.iade, siparis.kargolandi, siparis.tamamlandi, stok.guncellendi, fiyat.guncellendi
POST /api/webhookKaydet Webhook URL kaydet

Bildirim alacağınız HTTPS URL'yi ve dinlemek istediğiniz olayları kaydeder. Maksimum 10 webhook kaydedilebilir.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
urlstringZorunluBildirim alacak HTTPS URL
olaylarstring/arrayOpsiyonelVirgülle ayrılmış olay listesi. Boş bırakılırsa tüm olaylar dinlenir
✅ Başarılı Yanıt (201)
{
  "durum": true,
  "mesaj": "Webhook başarıyla kaydedildi",
  "veri": {
    "webhookId": 1,
    "url": "https://sizin-siteniz.com/webhook",
    "gizliAnahtar": "a1b2c3d4e5f6...",
    "olaylar": ["siparis.durum_degisti", "siparis.olusturuldu"],
    "bilgi": "Gizli anahtarınızı güvenli saklayın. Tekrar gösterilmeyecektir."
  }
}
📤 Webhook Payload Örneği
// Sizin URL'nize gönderilen POST isteği:
// Header: X-Webhook-Id: 1
// Header: X-Webhook-Event: siparis.durum_degisti
// Header: X-Webhook-Delivery: abc123def456
// Header: X-Webhook-Signature: sha256=hmac_imza
// Header: X-Webhook-Timestamp: 1709712345
// Header: X-Webhook-Retry: 0
// Header: User-Agent: Storex-Webhook/2.1

{
  "olay": "siparis.durum_degisti",
  "teslimId": "abc123def456",
  "zaman": "2026-03-06T15:30:00+03:00",
  "zamanDamgasi": 1709712345,
  "denemeNo": 1,
  "veri": {
    "siparisId": 145,
    "eskiDurum": 1,
    "yeniDurum": 4,
    "durumMetni": "Kargoda"
  }
}
🔐
İmza Doğrulama: $imzaVerisi = $timestamp . '.' . $payload; ardından hash_hmac('sha256', $imzaVerisi, $gizliAnahtar) sonucunu X-Webhook-Signature header'ındaki sha256= sonrasıyla karşılaştırın. Ayrıca timestamp'ın 5 dakikadan eski olmadığını kontrol edin (replay attack koruması).
GET /api/webhookListele Webhook'ları listele (istatistiklerle)

Kayıtlı webhook URL'lerinizi teslimat istatistikleriyle birlikte listeler.

✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Webhook listesi",
  "veri": {
    "webhooklar": [
      {
        "id": 1,
        "url": "https://sizin-siteniz.com/webhook",
        "olaylar": ["siparis.durum_degisti"],
        "aktif": 1,
        "toplam_teslimat": 45,
        "basarili_teslimat": 43,
        "basari_orani": "95.6%",
        "son_yanit_kodu": 200,
        "son_teslimat": "06.03.2026 15:30",
        "olusturma_tarihi_formati": "01.01.2026 10:00"
      }
    ]
  }
}
POST /api/webhookGuncelle Webhook ayarlarını güncelle

Webhook URL'sini, olay filtrelerini veya aktif/pasif durumunu günceller.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
webhookIdintZorunluWebhook ID
urlstringOpsiyonelYeni HTTPS URL
aktifintOpsiyonel1=Aktif, 0=Pasif
olaylarstringOpsiyonelYeni olay listesi
POST /api/webhookTest Test bildirimi gönder

Webhook URL'nize test bildirimi gönderir. Entegrasyonunuzu doğrulamak için kullanın.

📥 İstek Gövdesi (JSON)
ParametreTürDurumAçıklama
webhookIdintZorunluTest edilecek webhook ID
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Test başarılı",
  "veri": {
    "basarili": true,
    "httpKod": 200,
    "sureMilisaniye": 245,
    "teslimId": "test-a1b2c3d4"
  }
}
GET /api/webhookLoglar Teslimat loglarını görüntüle

Webhook teslimat geçmişini sayfalı olarak listeler. Hata ayıklama için kullanın.

📥 Parametreler (Query String)
ParametreTürDurumAçıklama
webhookIdintZorunluWebhook ID
limitintOpsiyonelSayfa başına log (varsayılan: 20, maks: 50)
sayfaintOpsiyonelSayfa numarası
✅ Başarılı Yanıt (200)
{
  "durum": true,
  "mesaj": "Webhook logları",
  "veri": {
    "loglar": [
      {
        "id": 100,
        "olay": "siparis.durum_degisti",
        "teslim_id": "abc123",
        "yanit_kodu": 200,
        "sure_ms": 245,
        "deneme_no": 1,
        "basarili": true,
        "zaman_formati": "06.03.2026 15:30:42"
      }
    ],
    "toplam": 45,
    "sayfaSayisi": 3,
    "mevcutSayfa": 1
  }
}

Sipariş Durum Kodları

0 Onay Bekliyor
1 Ödeme Bekliyor
2 Ödeme Alındı
3 Onaylandı
4 Kargoda
5 Tamamlandı
6 İptal Edildi
8 Paketleniyor
9 Tedarik Ediliyor
10 İade Edildi
11 Silinmiş
12 İade Talebi Alındı
13 İade Ulaştı Ödeme Yapılacak
14 İade Ödemesi Yapıldı
15 Teslimat Öncesi İptal Talebi
16 İptal Talebi
17 Kısmi İade Talebi
18 Kısmi İade Yapıldı
19 Teslim Edilemedi
20 Mağazaya Gönderildi
21 Mağazaya Ulaştı
22 Mağazada Teslim Bekliyor
23 Cari Hesap

Ödeme Yöntemleri

1 Kredi Kartı
2 Havale/EFT
3 Kapıda Ödeme
4 Havale Bildirimi
5 Cari Hesap
6 POS Nakit
7 POS Kredi Kartı

Kod Örnekleri

Farklı programlama dilleri ile API kullanım örnekleri.

<?php
$apiUrl = 'https://siteniz.com/api/';
$apiKey = 'sizin-api-anahtariniz';

// Siparişleri listele
$ch = curl_init($apiUrl . 'siparisler?limit=20&sayfa=1');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'X-API-KEY: ' . $apiKey,
        'Content-Type: application/json'
    ]
]);
$yanit = json_decode(curl_exec($ch), true);
curl_close($ch);

// Sipariş durumu güncelle
$ch = curl_init($apiUrl . 'siparisDurumGuncelle');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'X-API-KEY: ' . $apiKey,
        'Content-Type: application/json'
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'siparisId' => 145,
        'durum' => 4,
        'kargoAdi' => 'Yurtiçi Kargo',
        'kargoKodu' => 'YK123456789'
    ])
]);
$yanit = json_decode(curl_exec($ch), true);
curl_close($ch);

// Stok güncelle
$ch = curl_init($apiUrl . 'stokGuncelle');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'X-API-KEY: ' . $apiKey,
        'Content-Type: application/json'
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'urunId' => 100,
        'stok' => 50
    ])
]);
$yanit = json_decode(curl_exec($ch), true);
curl_close($ch);
const API_URL = 'https://siteniz.com/api/';
const API_KEY = 'sizin-api-anahtariniz';

const headers = {
  'X-API-KEY': API_KEY,
  'Content-Type': 'application/json'
};

// Siparişleri listele
const siparisler = await fetch(API_URL + 'siparisler?limit=20', { headers })
  .then(r => r.json());

// Sipariş durumu güncelle
const guncelle = await fetch(API_URL + 'siparisDurumGuncelle', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    siparisId: 145,
    durum: 4,
    kargoAdi: 'Yurtiçi Kargo',
    kargoKodu: 'YK123456789'
  })
}).then(r => r.json());

// Stok güncelle
const stok = await fetch(API_URL + 'stokGuncelle', {
  method: 'POST',
  headers,
  body: JSON.stringify({ urunId: 100, stok: 50 })
}).then(r => r.json());

// Fiyat güncelle
const fiyat = await fetch(API_URL + 'fiyatGuncelle', {
  method: 'POST',
  headers,
  body: JSON.stringify({ urunId: 100, fiyat: 249.90, eskiFiyat: 299.90 })
}).then(r => r.json());
import requests

API_URL = 'https://siteniz.com/api/'
API_KEY = 'sizin-api-anahtariniz'
headers = {'X-API-KEY': API_KEY, 'Content-Type': 'application/json'}

# Siparişleri listele
siparisler = requests.get(f'{API_URL}siparisler?limit=20', headers=headers).json()

# Sipariş durumu güncelle
guncelle = requests.post(f'{API_URL}siparisDurumGuncelle', headers=headers, json={
    'siparisId': 145,
    'durum': 4,
    'kargoAdi': 'Yurtiçi Kargo',
    'kargoKodu': 'YK123456789'
}).json()

# Stok güncelle
stok = requests.post(f'{API_URL}stokGuncelle', headers=headers, json={
    'urunId': 100,
    'stok': 50
}).json()

# Webhook kaydet
webhook = requests.post(f'{API_URL}webhookKaydet', headers=headers, json={
    'url': 'https://sizin-siteniz.com/webhook'
}).json()
print(f"Gizli Anahtar: {webhook['veri']['gizliAnahtar']}")
# Yönetim girişi yapıp API anahtarı al
curl -X POST https://siteniz.com/api/yonetimGiris \
  -H "Content-Type: application/json" \
  -d '{"kullaniciAdi": "admin", "sifre": "sifreniz"}'

# Siparişleri listele
curl -H "X-API-KEY: sizin-api-anahtariniz" \
  "https://siteniz.com/api/siparisler?limit=20&sayfa=1"

# Sipariş detayı
curl -H "X-API-KEY: sizin-api-anahtariniz" \
  "https://siteniz.com/api/siparis?id=145"

# Sipariş durumu güncelle
curl -X POST https://siteniz.com/api/siparisDurumGuncelle \
  -H "X-API-KEY: sizin-api-anahtariniz" \
  -H "Content-Type: application/json" \
  -d '{"siparisId": 145, "durum": 4, "kargoAdi": "Yurtiçi Kargo", "kargoKodu": "YK123456789"}'

# Stok güncelle
curl -X POST https://siteniz.com/api/stokGuncelle \
  -H "X-API-KEY: sizin-api-anahtariniz" \
  -H "Content-Type: application/json" \
  -d '{"urunId": 100, "stok": 50}'

# Fiyat güncelle
curl -X POST https://siteniz.com/api/fiyatGuncelle \
  -H "X-API-KEY: sizin-api-anahtariniz" \
  -H "Content-Type: application/json" \
  -d '{"urunId": 100, "fiyat": 249.90, "eskiFiyat": 299.90}'

# Webhook kaydet
curl -X POST https://siteniz.com/api/webhookKaydet \
  -H "X-API-KEY: sizin-api-anahtariniz" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://sizin-siteniz.com/webhook"}'
using System.Net.Http;
using System.Text;
using System.Text.Json;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-KEY", "sizin-api-anahtariniz");

// Siparişleri listele
var siparisler = await client.GetStringAsync(
    "https://siteniz.com/api/siparisler?limit=20");

// Sipariş durumu güncelle
var icerik = new StringContent(
    JsonSerializer.Serialize(new {
        siparisId = 145,
        durum = 4,
        kargoAdi = "Yurtiçi Kargo",
        kargoKodu = "YK123456789"
    }),
    Encoding.UTF8, "application/json");
var yanit = await client.PostAsync(
    "https://siteniz.com/api/siparisDurumGuncelle", icerik);

// Stok güncelle
var stokIcerik = new StringContent(
    JsonSerializer.Serialize(new { urunId = 100, stok = 50 }),
    Encoding.UTF8, "application/json");
var stokYanit = await client.PostAsync(
    "https://siteniz.com/api/stokGuncelle", stokIcerik);
// === Mobil Uygulama: Bearer Token ile Kullanım ===
// Tüm müşteri endpoint'leri Bearer token ile çalışır
// kullaniciId parametresi gerekmez, token'dan otomatik belirlenir

const API_URL = 'https://siteniz.com/api/';
let oturumToken = '';

// 1. Giriş yap ve token al
async function girisYap(email, sifre) {
  const yanit = await fetch(API_URL + 'musteriGiris', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ emailVeyaTelefon: email, sifre, beniHatirla: true })
  }).then(r => r.json());
  
  if (yanit.durum) {
    oturumToken = yanit.veri.oturum.token;
    // Token'ı güvenli depolayın (SecureStorage, Keychain vb.)
  }
  return yanit;
}

// 2. Bearer token ile profil getir (kullaniciId gerekmez)
async function profilGetir() {
  return fetch(API_URL + 'musteriProfil', {
    headers: { 'Authorization': 'Bearer ' + oturumToken }
  }).then(r => r.json());
}

// 3. Adres listesi (kullaniciId gerekmez)
async function adreslerGetir() {
  return fetch(API_URL + 'musteriAdresler', {
    headers: { 'Authorization': 'Bearer ' + oturumToken }
  }).then(r => r.json());
}

// 4. Favori ekle/çıkar (kullaniciId gerekmez)
async function favoriToggle(urunId) {
  return fetch(API_URL + 'musteriFavoriToggle', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + oturumToken,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ urunId })
  }).then(r => r.json());
}

// 5. Oturum token yenile
async function tokenYenile() {
  const yanit = await fetch(API_URL + 'musteriOturumYenile', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token: oturumToken })
  }).then(r => r.json());
  
  if (yanit.durum) {
    oturumToken = yanit.veri.yeniToken;
  }
  return yanit;
}

// 6. Çıkış yap
async function cikisYap() {
  return fetch(API_URL + 'musteriCikis', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token: oturumToken })
  }).then(r => r.json());
}
// === PHP: Webhook İmza Doğrulama ===
<?php
$payload = file_get_contents('php://input');
$imzaHeader = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$zamanDamgasi = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$teslimId = $_SERVER['HTTP_X_WEBHOOK_DELIVERY'] ?? '';
$gizliAnahtar = 'webhook-kayit-sirasinda-alinan-gizli-anahtar';

// sha256= prefix'ini kaldır
$imza = str_replace('sha256=', '', $imzaHeader);

// İmzayı doğrula (timestamp.payload formatı)
$imzaVerisi = $zamanDamgasi . '.' . $payload;
$beklenenImza = hash_hmac('sha256', $imzaVerisi, $gizliAnahtar);

if (!hash_equals($beklenenImza, $imza)) {
    http_response_code(401);
    die('Geçersiz imza');
}

// Replay attack koruması: 5 dakikadan eski istekleri reddet
if (abs(time() - intval($zamanDamgasi)) > 300) {
    http_response_code(403);
    die('İstek zaman aşımına uğradı');
}

// Payload'ı işle
$veri = json_decode($payload, true);
$olay = $veri['olay'];        // "siparis.durum_degisti"
$siparisId = $veri['veri']['siparisId'];
$yeniDurum = $veri['veri']['yeniDurum'];
$durumMetni = $veri['veri']['durumMetni'];

// Kendi iş mantığınızı burada uygulayın
// Örn: ERP'ye bildir, müşteriye SMS gönder, stok güncelle vb.

http_response_code(200);
echo json_encode(['ok' => true]);

// === Node.js: Webhook İmza Doğrulama ===
const crypto = require('crypto');

app.post('/webhook', (req, res) => {
  const payload = JSON.stringify(req.body);
  const imzaHeader = req.headers['x-webhook-signature'] || '';
  const zamanDamgasi = req.headers['x-webhook-timestamp'] || '';
  const gizliAnahtar = 'webhook-kayit-sirasinda-alinan-gizli-anahtar';
  
  // sha256= prefix'ini kaldır
  const imza = imzaHeader.replace('sha256=', '');
  
  // timestamp.payload formatında doğrula
  const imzaVerisi = zamanDamgasi + '.' + payload;
  const beklenen = crypto.createHmac('sha256', gizliAnahtar)
    .update(imzaVerisi).digest('hex');
  
  if (imza !== beklenen) {
    return res.status(401).json({ hata: 'Geçersiz imza' });
  }
  
  // Replay attack koruması
  if (Math.abs(Date.now() / 1000 - parseInt(zamanDamgasi)) > 300) {
    return res.status(403).json({ hata: 'İstek zaman aşımına uğradı' });
  }
  
  const { olay, veri } = req.body;
  console.log(`Olay: ${olay}, Sipariş: ${veri.siparisId}`);
  
  res.json({ ok: true });
});