ks.today API Dökümantasyonu

1. Giriş

Bu kılavuz, ks.today API'sini kullanarak kendi uygulamalarınız veya sistemlerinizle entegrasyon yapmanıza yardımcı olmak amacıyla hazırlanmıştır. API, ks.today üzerinde oluşturduğunuz tablolara ve verilere programatik olarak erişmenizi ve temel CRUD (Create, Read, Update, Delete - Oluşturma, Okuma, Güncelleme, Silme) işlemlerini gerçekleştirmenizi sağlar.

Bu kılavuz, API'nin çalışma mantığını, kimlik doğrulama adımlarını, endpoint yapılarını, istek ve yanıt formatlarını PHP örnekleriyle açıklamaktadır.

2. Kimlik Doğrulama ve Kurulum

2.1. API Anahtarı (API Key)

API'ye yapılan tüm istekler geçerli bir API anahtarı ile doğrulanmalıdır.

  • API anahtarları, ks.today arayüzünde /api/settings/apikeys/ sayfasından oluşturulur.
  • Oluşturulan her anahtar, belirli bir ks.today kullanıcısına bağlanır.
  • API anahtarının yetkileri, bağlı olduğu kullanıcının rolleri ile sınırlıdır. Yani, anahtar sadece kullanıcının izinli olduğu işlemleri yapabilir.
  • API anahtarınızı, her isteğin HTTP Authorization başlığında (header) Bearer token olarak göndermelisiniz:
Authorization: Bearer <SİZİN_API_ANAHTARINIZ>

2.2. Temel URL (Base URL)

API endpoint'leri, size özel veya merkezi bir temel URL üzerinden çalışır. İsteklerinizi yönlendireceğiniz temel URL genellikle şu formatlardadır:

  • https://sirketiniz.ks.today/api/
  • https://websiteniz.com/api/
  • (Not: sirketiniz veya websiteniz.com kısımları kendi alan adınız veya size atanan ks.today adresi olacaktır.)

Bu kılavuzdaki endpoint örnekleri, bu temel URL'in devamına eklenecek şekilde gösterilmiştir.

3. Örnek API İstemcisi (PHP)

API ile etkileşimi kolaylaştırmak için aşağıdaki PHP sınıfını kullanabilirsiniz. Bu sınıf, istekleri oluşturma, başlıkları ayarlama, JSON verisi gönderme ve yanıtları işleme gibi temel görevleri yerine getirir.

<?php

/**
 * KsTodayApiClient Class
 * Handles requests to the ks.today API.
 */
class KsTodayApiClient
{
    private static $apiKey = null;
    private static $baseUrl = null;
    private static $defaultTimeout = 30; // seconds

    /**
     * Sets the API Key for subsequent requests.
     *
     * @param string $apiKey The API key.
     */
    public static function setApiKey(string $apiKey)
    {
        self::$apiKey = $apiKey;
    }

    /**
     * Sets the Base URL for the API endpoints.
     * Example: "https://yourcompany.ks.today/api/"
     *
     * @param string $baseUrl The base URL ending with "/api/".
     */
    public static function setBaseUrl(string $baseUrl)
    {
        // Ensure base URL ends with /api/ for consistency
        if (substr($baseUrl, -5) !== '/api/') {
             if (substr($baseUrl, -1) !== '/') {
                $baseUrl .= '/';
             }
             // If it doesn't end with 'api/', you might want to append it or throw an error.
             // For robust implementation, ensure the URL format is correct.
             // $baseUrl .= 'api/'; 
        }
        self::$baseUrl = $baseUrl;
    }
    
    /**
     * Checks if the API Key and Base URL are set.
     * @return bool True if both are set, false otherwise.
     */
    public static function isConfigured(): bool
    {
        return !empty(self::$apiKey) && !empty(self::$baseUrl);
    }

    /**
     * Makes a request to the ks.today API.
     *
     * @param string $endpoint The API endpoint path (e.g., "adm/specs/", "account/user/edit/").
     * @param string $method The HTTP method (GET, POST, PATCH). Note: API uses GET for Delete.
     * @param array $params For GET requests, key-value array for query parameters. For POST/PATCH, the data payload array.
     * @param array $options Additional cURL options if needed (e.g., ['timeout' => 60]).
     * @return array|null The decoded JSON response as an array, or null on failure.
     */
    public static function request(string $endpoint, string $method = 'GET', array $params = [], array $options = []): ?array
    {
        if (!self::isConfigured()) {
            error_log("KsTodayApiClient not configured. Set API Key and Base URL.");
            return null; // Or throw an exception
        }

        $method = strtoupper($method);
        // Ensure URL concatenation is correct
        $url = rtrim(self::$baseUrl, '/') . '/' . ltrim($endpoint, '/');

        $ch = curl_init();

        $curlOptions = [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYHOST => 0, // Use 2 in production environment if possible
            CURLOPT_SSL_VERIFYPEER => 0, // Use true in production environment if possible
            CURLOPT_TIMEOUT => $options['timeout'] ?? self::$defaultTimeout,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . self::$apiKey,
            ],
        ];

        if ($method === 'GET') {
            if (!empty($params)) {
                // Build query string respecting the specific array format for filters
                $queryString = http_build_query($params);
                // Fix array formatting (e.g., filter[field][0]=value -> filter[field][]=value)
                // This replacement is crucial for ks.today filter format
                $queryString = preg_replace('/%5B\d+%5D=/', '[]=', $queryString);
                $url .= '?' . $queryString;
            }
            // Note: GET is also used for DELETE in this API
            if (strpos($endpoint, '/del/') !== false) {
                 // API uses GET for delete, no specific cURL option needed for method
            }
        } elseif ($method === 'POST') {
            $curlOptions[CURLOPT_POST] = true;
            $curlOptions[CURLOPT_POSTFIELDS] = json_encode($params);
        } elseif ($method === 'PATCH') {
            $curlOptions[CURLOPT_CUSTOMREQUEST] = 'PATCH';
            $curlOptions[CURLOPT_POSTFIELDS] = json_encode($params);
        } else {
             // Unsupported method specified by the caller
             error_log("Unsupported HTTP method: " . $method);
             curl_close($ch);
             return null;
        }

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt_array($ch, $curlOptions);

        $result = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if (curl_errno($ch)) {
            // Log cURL errors
            error_log("cURL Error (" . $url . "): " . curl_error($ch));
            curl_close($ch);
            return null; // Indicate failure
        }

        curl_close($ch);

        $response = json_decode($result, true);

        // Check if JSON decoding failed
        if ($response === null && json_last_error() !== JSON_ERROR_NONE) {
             // Log JSON decoding errors
             error_log("Failed to decode JSON response from ks.today API (" . $url . "): " . $result);
             return null; // Indicate failure
        }
        
        // Even if JSON decoded, check the 'result' flag from the API response if present
        if (isset($response['result']) && $response['result'] === false) {
            // Optional: Log the API-level error message if provided
            error_log("ks.today API Error (" . $url . "): " . var_export($response['content'] ?? 'Unknown error', true));
        }

        return $response; // Return the decoded array
    }
}

?>

Kullanım Örneği

<?php
// require 'KsTodayApiClient.php'; // Include the class file

// Setup (Usually done once at application startup)
KsTodayApiClient::setApiKey('SİZİN_API_ANAHTARINIZ');
KsTodayApiClient::setBaseUrl('https://sirketiniz.ks.today/api/'); 

// Make a request (Example: List records)
$endpoint = 'ornek/tablo/'; // Replace with your table path
$params = ['list_limit' => 10]; // GET parameters
$response = KsTodayApiClient::request($endpoint, 'GET', $params);

if ($response && ($response['result'] ?? false)) {
    // Request successful and API returned 'result: true'
    $records = $response['content']['list'] ?? [];
    echo "Found " . count($records) . " records.";
    // Process records...
} else {
    // Request failed or API returned 'result: false'
    echo "API request failed.";
    // Log or display error details from $response... 
}
?>

4. API Endpointleri ve CRUD İşlemleri

Aşağıda, ks.today verileri üzerinde temel CRUD işlemlerini gerçekleştirmek için kullanacağınız metotlar, endpoint'ler ve gerekli parametreler açıklanmaktadır.

4.1. Create (Oluşturma)

Yeni bir kayıt oluşturmak için kullanılır.

  • Metod: POST
  • Endpoint: {tablo_yolu}/edit/ (Örn: musteriler/adresler/edit/)
  • İstek Body (JSON):
    • postvar: Yeni kayıt eklemek için bu anahtarın değeri boş string ("") olmalıdır.
    • Diğer Alanlar: Oluşturulacak kayda ait alan adları ve değerleri (örn: {"v_name": "Değer", "i_miktar": 10}). Alan adları ks.today'deki tanımlarınızla eşleşmelidir.
  • Yanıt: Başarı durumunda {"result": true, ...}, hata durumunda {"result": false, ...} döner. Başarılı yanıt, oluşturulan kaydın ID'sini içerebilir.

Örnek (PHP)

<?php
$endpoint = 'urunler/stok/edit/'; // Your table path + /edit/
$data = [
    'postvar'   => '', // Indicates CREATE operation
    'v_urun_adi' => 'Yeni Ürün',
    'i_stok_adedi' => 100,
    'e_aktif' => '1' 
];
$response = KsTodayApiClient::request($endpoint, 'POST', $data);

if ($response && ($response['result'] ?? false)) {
    echo "Record created successfully. New ID: " . ($response['content']['ID'] ?? 'N/A');
} else {
    echo "Failed to create record.";
    // Log error details from $response if needed
}
?>

4.2. Read (Okuma/Listeleme)

Mevcut kayıtları listelemek, filtrelemek veya belirli kayıtları getirmek için kullanılır.

  • Metod: GET
  • Endpoint: {tablo_yolu}/ (Örn: projeler/gorevler/)
  • İstek Parametreleri (Query String): Filtreleme, sayfalama, ID ile getirme gibi işlemler için URL'e eklenen parametrelerdir. Detayları Bölüm 5'te bulabilirsiniz.
  • Yanıt: Başarı durumunda {"result": true, "content": {...}} döner. content objesi kayıt listesini (list), alan tanımlarını (fields), sayfalama bilgilerini (pagination) ve diğer meta verileri içerir. Hata durumunda {"result": false, ...} döner.

Örnek (PHP - Listeleme ve Filtreleme)

<?php
$endpoint = 'projeler/gorevler/'; // Your table path
$params = [
    'list_limit' => 25,         // Records per page
    'page' => 2,               // Page number
    'filter' => [              // Example filter: active tasks
        'id_durum' => ['1', '2'], // Status ID 1 OR 2 (Assuming 1=Open, 2=In Progress)
        'e_aktif' => ['1']      // Is active
    ],
    'searchvar' => 'acil'      // Search for "acil" in searchable fields
];
$response = KsTodayApiClient::request($endpoint, 'GET', $params);

if ($response && ($response['result'] ?? false)) {
    $records = $response['content']['list'] ?? [];
    echo "Found " . count($records) . " records.";
    // Process records...
} else {
    echo "Failed to list records.";
    // Log error details from $response if needed
}
?>

Örnek (PHP - Belirli ID'leri Getirme)

<?php
$endpoint = 'projeler/gorevler/';
$params = ['ids' => '101,105,210']; // Fetch records with these specific IDs
$response = KsTodayApiClient::request($endpoint, 'GET', $params);
// ... response handling ...
?>

Örnek (PHP - Tek ID Getirme)

<?php
$endpoint = 'projeler/gorevler/';
// Method 1: Using 'ids' parameter
// $params = ['ids' => '101']; 

// Method 2: Using ROW_ID filter (ROW_ID is a standard field representing the record ID)
$params = [
    'filter' => [
        'ROW_ID' => [ 
            'v_value_start' => '101',
            'v_value_end' => '101'
        ]
    ]
]; 
$response = KsTodayApiClient::request($endpoint, 'GET', $params);
// ... response handling ...
?>

4.3. Update (Güncelleme - Kısmi)

Mevcut bir kaydın belirli alanlarını güncellemek için kullanılır.

  • Metod: PATCH
  • Endpoint: {tablo_yolu}/edit/ (Örn: musteriler/adresler/edit/)
  • İstek Body (JSON):
    • postvar: Güncellenecek kaydın ID'si.
    • Diğer Alanlar: Sadece değiştirilecek alanlar ve yeni değerleri. Bu istekte gönderilmeyen alanların mevcut değerleri değişmez (korunur).
  • Yanıt: Başarı durumunda {"result": true}, hata durumunda {"result": false, ...} döner.
Önemli Not: PATCH metodu sadece gönderdiğiniz alanları günceller. Eğer PATCH yerine başka bir metot (örn: POST) kullanılırsa veya API farklı çalışıyorsa, göndermediğiniz alanlar varsayılan değerlerine dönebilir veya sıfırlanabilir. Kısmi güncelleme için PATCH kullanmanız önerilir.

Örnek (PHP)

<?php
$recordIdToUpdate = 55; // ID of the record to update
$endpoint = 'musteriler/adresler/edit/'; // Your table path + /edit/
$data = [
    'postvar'    => $recordIdToUpdate, // Indicates UPDATE for this ID
    'v_adres_satir1' => 'Yeni Adres Bilgisi', // Update only this field
    'v_posta_kodu'   => '34000'             // Update only this field
    // Other fields like 'v_sehir' are not sent, their values will remain unchanged
];
$response = KsTodayApiClient::request($endpoint, 'PATCH', $data);

if ($response && ($response['result'] ?? false)) {
    echo "Record ID " . $recordIdToUpdate . " updated successfully.";
} else {
    echo "Failed to update record.";
    // Log error details from $response if needed
}
?>

4.4. Delete (Silme)

Bir veya daha fazla kaydı silmek için kullanılır.

Dikkat: ks.today API'si, silme işlemi için standart DELETE metodu yerine GET metodunu kullanır. Ayırt edici özellik URL yapısıdır.
  • Metod: GET
  • Endpoint: {tablo_yolu}/del/{IDs}
    • {IDs}: Silinecek kaydın/kayıtların ID'si veya virgülle ayrılmış ID listesi.
    • Örnek (Tekli): urunler/stok/del/15
    • Örnek (Çoklu): urunler/stok/del/15,18,21
  • İstek Body: Gerekli değil (boş).
  • Yanıt: Başarı durumunda {"result": true}, hata durumunda {"result": false, ...} döner.

Örnek (PHP - Tekli Silme)

<?php
$recordIdToDelete = 15;
$endpoint = 'urunler/stok/del/' . $recordIdToDelete; // Append ID directly
    
// No body/params needed for DELETE via GET request to this endpoint structure
$response = KsTodayApiClient::request($endpoint, 'GET'); 

if ($response && ($response['result'] ?? false)) {
    echo "Record ID " . $recordIdToDelete . " deleted successfully.";
} else {
    echo "Failed to delete record.";
    // Log error details from $response if needed
}
?>

Örnek (PHP - Çoklu Silme)

<?php
$recordIdsToDelete = '15,18,21'; // Comma-separated IDs
$endpoint = 'urunler/stok/del/' . $recordIdsToDelete; // Append IDs directly
    
$response = KsTodayApiClient::request($endpoint, 'GET'); 

if ($response && ($response['result'] ?? false)) {
    echo "Record IDs " . $recordIdsToDelete . " deleted successfully.";
} else {
    echo "Failed to delete records.";
    // Log error details from $response if needed
}
?>

5. Read İşlemi Detayları (Filtreleme, Sayfalama, Yanıt Yapısı)

GET /{tablo_yolu}/ endpoint'i, verileri okumak için güçlü filtreleme ve sayfalama yetenekleri sunar.

5.1. Sayfalama (Pagination)

  • list_limit=N: Bir sayfada kaç kayıt gösterileceğini belirtir (örn: list_limit=100). Varsayılan genellikle 20'dir.
  • page=N: Hangi sayfayı getirmek istediğinizi belirtir (1'den başlar, örn: page=3). Varsayılan 1'dir.

5.2. Kayıt Filtreleme

İstediğiniz kayıtları bulmak için çeşitli filtre parametreleri kullanabilirsiniz. Bu parametreler URL query string'ine eklenir.

  • Genel Arama (searchvar):
    • searchvar=aranan: Metin tabanlı, aranabilir olarak işaretlenmiş alanlarda (genellikle LIKE ile) arama yapar.
    • Örnek: ?searchvar=rapor
  • ID ile Getirme (ids):
    • ids=ID1,ID2,...: Sadece belirtilen ID'lere sahip kayıtları getirir.
    • Örnek: ?ids=5,12,25
  • Alan Bazlı Filtreler (filter, filterIsNull, filterNotIn):
    Not: PHP'de http_build_query kullanırken, filter[alanAdi][]=deger formatını (köşeli parantezleri) korumak önemlidir. Örnek istemci sınıfı bunu otomatik yapar.
    • Eşitlik / İçerir (filter[AlanAdi][]=Deger):
      • İlişkili Alan (ID): filter[kullanici_id][]=10 (Kullanıcı ID'si 10 olanlar)
      • Metin Alanı (İçerir): filter[aciklama][]=önemli (Açıklamasında "önemli" geçenler)
      • Select Alanı: filter[durum][]=aktif (Durumu "aktif" olanlar)
      • Birden Fazla Değer (VEYA - OR): filter[durum][]=aktif&filter[durum][]=beklemede (Durumu "aktif" VEYA "beklemede" olanlar)
    • NULL Kontrolü (filterIsNull[AlanAdi][]=Durum):
      • Dolu Olanlar (IS NOT NULL): filterIsNull[bitis_tarihi][]=0
      • Boş Olanlar (IS NULL): filterIsNull[bitis_tarihi][]=1
    • Hariç Tutma (filterNotIn[AlanAdi][]=Deger):
      • filterNotIn[kategori][]=eski (Kategorisi "eski" olmayanlar)
      • Birden Fazla Değer: filterNotIn[kullanici_id][]=1&filterNotIn[kullanici_id][]=2 (Kullanıcı ID'si 1 VEYA 2 olmayanlar)
    • Aralık - Sayısal (filter[AlanAdi][v_value_start/end]=Deger):
      • filter[fiyat][v_value_start]=100 (Fiyat >= 100)
      • filter[fiyat][v_value_end]=500 (Fiyat <= 500)
      • İkisi birlikte: 100 ile 500 arası (dahil).
    • Aralık - Tarih/Datetime (filter[AlanAdi][v_time_start/end]=Deger):
      • filter[kayit_tarihi][v_time_start]=2024-01-01 (>= 1 Ocak 2024 00:00:00)
      • filter[kayit_tarihi][v_time_end]=2024-12-31 (<= 31 Aralık 2024 23:59:59)
      • datetime alanlar için YYYY-MM-DD HH:MM:SS formatı da kullanılabilir. Sadece tarih gönderilirse, başlangıç için 00:00:00, bitiş için 23:59:59 eklenir.
    • Ön Tanımlı Tarih Aralığı (filter[AlanAdi][v_tp]=ID):
      • filter[kayit_tarihi][v_tp]=7 (Bu ayki kayıtlar)
      • v_time_start veya v_time_end ile birlikte kullanılmaz.
      • v_tp ID'leri ve Anlamları:
        • 1: Bugün
        • 2: Dün
        • 3: Son 7 Gün
        • 4: Geçen Hafta
        • 5: Bu Hafta
        • 6: Son 30 Gün
        • 7: Bu Ay
        • 8: Geçen Ay
        • 9: Bu Yıl
        • 10: Gelecek 30 Gün
        • 11: Bugünden Önce (<= Bugün)
        • 12: Bugünden Sonra (>= Bugün)
        • 13: Geçen Yıl

5.3. Yanıt Yapısı (Response Structure)

GET isteklerine gelen başarılı yanıtlar ({"result": true, ...}), content anahtarı altında hem veriyi hem de verinin yapısını açıklayan zengin meta veriler içerir. Bu, dinamik arayüzler oluşturmanızı sağlar.

  • content.active: Eriştiğiniz tablo/model hakkında temel bilgiler.
  • content.tableName: Veritabanındaki gerçek tablo adı.
  • content.list: Filtrelenmiş ve sayfalanmış kayıtların bulunduğu dizi.
  • content.fields: Tablodaki her alanın detaylı tanımı. Bu bölüm, alanın adını, görünen adını (v_name), tipini (text, number, date, select, parent vb.), ilişkili olup olmadığını, seçeneklerini, gösterim sırasını ve daha fazlasını içerir. Formları ve tabloları dinamik olarak oluşturmak için bu bilgileri kullanabilirsiniz.
  • content.pagination: Sayfalama bilgileri (hangi sayfada olduğunuz, toplam sayfa sayısı vb.).
  • content.parents: Eğer tabloda başka tablolara bağlı alanlar (parent tipinde) varsa, bu alanlar için ek bilgi içerir. Buradaki values dizisi, o anki listelemede (content.list) bulunan kayıtlara karşılık gelen ilişkili değerlerin (ID ve metin) bir listesini sunar.
    Tüm İlişkili Değerleri Alma: Eğer bir ilişkili alan için (örn: Kategoriler) filtreleme seçeneklerini doldurmak amacıyla tüm olası değerleri almak isterseniz, content.parents...values listesi yeterli olmayacaktır. Bunun yerine, ilgili alanın meta verisinden (content.fields...parent.CntName) parent tablonun API yolunu öğrenip, o yola ayrı bir GET isteği yapmanız gerekir (örn: GET /projeler/kategoriler/?list_limit=1000). Bu şekilde elde ettiğiniz tam liste ile filtreleme arayüzünü (örn: dropdown) doldurabilirsiniz. İlişkili bir alanda isme göre arama yapmak için de yine parent tablonun endpoint'ine searchvar ile istek atabilirsiniz.
  • content.FilterableFields, content.filterIsNull, filterNotIn: Hangi alanların nasıl filtrelenebileceğini gösteren ve aynı zamanda isteğinizde gönderdiğiniz aktif filtreleri yansıtan yapılar.
  • content.FilterAjaxValues: Aktif filtrelerden ilişkili alanlara ait ID ve metin karşılıklarını gösterir.
  • content.ListSub: Varsa, ana tabloyla ilişkili alt tabloların tanımlarını içerir.
  • content.modelConfig: Tablonun ks.today'deki genel ayarları.

6. Meta Veri Alma (Alan Listesi)

Bir tablonun alan yapısını (örneğin, dinamik bir filtreleme formu veya veri giriş formu oluşturmak için) öğrenmek istiyorsanız, tablo boş bile olsa normal bir listeleme isteği yapabilirsiniz. Düşük bir limit (örn: list_limit=1) kullanmak yeterlidir. Yanıttaki content.fields bölümü size alan tanımlarını verecektir.

<?php
$endpoint = 'urunler/kategoriler/'; // Your table path
$params = ['list_limit' => 1]; // Get metadata even if no records exist
$response = KsTodayApiClient::request($endpoint, 'GET', $params);

if ($response && ($response['result'] ?? false)) {
    $fields = $response['content']['fields'] ?? [];
    $filterableFieldsInfo = $response['content']['FilterableFields'] ?? [];
    // Use $fields and $filterableFieldsInfo to dynamically build UI elements
    echo "Field definitions retrieved successfully.";
    // print_r($fields); 
} else {
    echo "Failed to retrieve field information.";
    // Log error details from $response if needed
}
?>

7. Özet Tablo

İşlem Metod Endpoint Suffix ID Konumu Body Gerekli Mi? Temel Body Parametreleri
Create (Oluşturma) POST /edit/ Yok Evet postvar: "", Alanlar
Read (Listeleme) GET / Query Parametreleri Hayır Yok
Read (Tek/Çoklu ID) GET / Query (ids veya filter[ROW_ID]) Hayır Yok
Update (Kısmi Güncelleme) PATCH /edit/ Body (postvar) Evet postvar: KAYIT_ID, Alanlar
Delete (Silme) GET /del/{ID1,ID2...} URL Path Hayır Yok

8. Sonuç

ks.today API, verilerinize programatik olarak erişmek ve yönetmek için kapsamlı bir yol sunar. Bu kılavuzda açıklanan metotlar ve endpoint'ler ile temel CRUD işlemlerini gerçekleştirebilir, güçlü filtreleme yeteneklerinden yararlanabilir ve API'nin sağladığı zengin meta veriler sayesinde dinamik uygulamalar oluşturabilirsiniz.

Entegrasyon sırasında karşılaşabileceğiniz özel durumlar veya daha ileri seviye kullanım senaryoları için ek destek veya dökümantasyon gerekebilir.

Çerezler (cookie), everyg web sitesini ve hizmetlerimizi daha etkin bir şekilde sunmamızı sağlamaktadır. Çerezlerle ilgili detaylı bilgi için Gizlilik Politikamızı ziyaret edebilirsiniz.
Daha Fazla Bilgi