# Gurubase Siper Dokümantasyonu > Türkçe kişisel veri maskeleme ve AI gateway: dakikalar içinde ilk istek, API referansı, güvenlik. # Gurubase Siper Dokümantasyonu Source: https://siper.gurubase.ai/docs/ OpenAI uyumlu AI gateway ve Türkçe kişisel veri maskeleme. Dakikalar içinde ilk isteğinizi gönderin. Gurubase Siper üç parçadan oluşur: OpenAI uyumlu bir AI gateway, Türkçe metin için kişisel veri maskeleme ve bir yönetim paneli. İstekler, dış dil modeline gitmeden önce Türkiye’de maskelenir. Kişisel veri içeren metinlerle çalışan ve bu veriyi olduğu gibi yurt dışındaki modellere göndermek istemeyen ekipler için tasarlandı. Diyagram: Uygulamanızın istekleri Gurubase Gateway'e gelir; Gateway yurt içinde çalışır. Siper PII Maskeleme kişisel veriyi maskeler, ham veri burada kalır; dış dil modeline yalnız maskeli metin gider. Maskeleme pratikte şöyle görünür: Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor. örneği maskelenince: , TCKN , başvuru durumunu soruyor. ## Buradan başlayın - [AI Gateway](/docs/ai-gateway/): Tek geçiş noktası ne kazandırır: maskeleme, görünürlük, dayanıklılık, bütçe. - [Başlangıç](/docs/getting-started/): Sanal anahtarınızı alın, OpenAI SDK ile ilk isteğinizi gönderin. - [Kavramlar](/docs/concepts/): Maskeleme nasıl çalışır, yer tutucu formatı, fail-closed davranış ve veri egemenliği. - [Kategoriler](/docs/categories/): Maskelenen 26 kişisel veri kategorisi, sentetik örnekleriyle. - [Rehberler](/docs/guides/gateway-integration/): OpenAI SDK ile geçiş, streaming ve yalnız maskeleme. - [API referansı](/docs/api/gateway/): Gateway ve maskeleme uç noktalarının tam referansı. - [Güvenlik](/docs/security/): Veri saklama yaklaşımı, denetim izi ve erişim kontrolleri. Hesap oluşturmak için [bizimle iletişime geçin](https://siper.gurubase.ai/iletisim); hesabınız hazırsa [panele](https://gateway-tr.gurubase.io) giriş yapıp sanal anahtarınızı üretebilirsiniz. Siper, [Gurubase](https://gurubase.io) ürün ailesindendir. Gurubase, kurumun kendi bilgi kaynaklarından beslenen, her yanıtında kaynak gösteren ve bağlam zayıfsa yanıtlamayı reddeden AI ajanları kurmanızı sağlar; Siper ise bu ailenin Türkçe kişisel veri koruması katmanıdır. ## AI ajanları için Bu dokümanlar makine-okunur biçimde de sunulur; AI ajanları ve LLM’ler doğrudan tüketebilir: - [llms.txt](/docs/llms.txt): sayfa dizini ve özetler - [llms-full.txt](/docs/llms-full.txt): tüm dokümanların tam metni tek dosyada - Her sayfanın ham Markdown hali: URL sonuna `.md` ekleyin (ör. [getting-started.md](/docs/getting-started.md)) Bu dosyalar her build’de otomatik üretilir ve içerikle güncel kalır. --- # AI Gateway Source: https://siper.gurubase.ai/docs/ai-gateway/ Uygulamalarınızın dil modeli trafiğini tek noktadan geçiren katman: maskeleme, denetim izi, kota ve kullanım aynı yerde toplanır. Kodunuz değişmez. Bir AI gateway, uygulamalarınız ile dil modelleri arasında duran ara katmandır. İstekler doğrudan sağlayıcıya gitmek yerine önce buradan geçer; kurum, geçen her isteği tek yerden görür ve tek yerden kurallara bağlar. Gurubase Gateway bu katmanı Türkiye’de çalıştırır ve geçiş anına bir adım daha ekler: kişisel veri, istek dış modele çıkmadan maskelenir. Diyagram: müşteri asistanı, destek akışı ve iç araçlar dahil tüm uygulamaların istekleri tek geçiş noktası olan Gurubase Gateway'e gelir. Gateway yurt içinde çalışır ve isteği Siper maskelemeden geçirir; ham veri burada kalır. Maskeli metin buradan sağlayıcılara dağılır: OpenAI, Anthropic, Gemini gibi genel sağlayıcılar ya da kendi sunucunuzdaki vLLM ve Ollama. Denetim izi, kota ve kullanım aynı noktada toplanır. ## Neden tek geçiş noktası Dağınık kullanımda her ekip kendi anahtarıyla, kendi kodundan, kendi sağlayıcısına gider. Kimin ne gönderdiğini kimse toplu göremez; bu, kurumsal literatürde shadow AI diye anılan tablodur. Tek geçiş noktası bunu dört yerde değiştirir. **Kişisel veri kontrolü.** Maskeleme tek bir yerde uygulanır. Her uygulamanın ayrı ayrı doğru yapmasını beklemek yerine kural geçiş noktasında durur, istek hangi ekipten gelirse gelsin aynı şekilde işler. **Görünürlük.** Hangi ekip hangi modeli ne kadar kullanıyor, hangi kategoriler ne sıklıkta yakalanıyor, hangi istek hata aldı. Sanal anahtar ve model kırılımıyla tek ekranda toplanır. **Dayanıklılık.** Sağlayıcı yavaşladığında ya da hata döndürdüğünde yeniden deneme ve alternatife geçme kararı uygulama kodunda değil, geçiş noktasında verilir. **Bütçe.** Token bütçesi, kota ve uyarı eşikleri anahtar bazında izlenir; kullanım kurum genelinde tek yerden okunur. ## Kodunuzda ne değişir İki değer. Gerisi standart OpenAI SDK’sı olarak kalır: model adı, parametreler ve yanıt biçimi aynıdır. ```diff client = OpenAI( - base_url="https://api.openai.com/v1", - api_key=OPENAI_API_KEY, + base_url="https://gw-tr.gurubase.io/v1", + api_key=SANAL_ANAHTAR, ) ``` Sağlayıcının gerçek anahtarı Gateway içinde durur; uygulamanız yalnız panelden ürettiğiniz sanal anahtarı taşır. Adım adım geçiş için [Gateway entegrasyonu](/docs/guides/gateway-integration/). ## Koruma katmanları Maskeleme, geçiş noktasında çalışan koruma katmanlarının ilki ve varsayılan olanıdır. Girdi her istekte maskelenir; yanıt maskeleme isteğe bağlı açılır. Prompt injection ve halüsinasyon korumaları aynı katmana eklenecek, yakında yayına girecek özelliklerdir. Ayrıntı ve güncel durum için [Koruma katmanları](/docs/guardrails/). ## Modeller ve sağlayıcılar Gateway OpenAI uyumlu tek bir arayüz sunar. Arkasında OpenAI, Anthropic ve Gemini gibi genel sağlayıcılar ya da kendi sunucunuzda çalışan modeller olabilir; istemci tarafında değişen tek şey `model` alanıdır. Erişebildiğiniz modelleri `/v1/models` ucundan alırsınız. Sağlayıcı seçimi, yeniden deneme ve alternatife geçiş davranışı için [Modeller ve sağlayıcılar](/docs/models/). ## Görünürlük ve yönetişim Panel, geçiş noktasında biriken veriyi okunur hale getirir: istek ve token sayısı, işlenen karakter, yakalanan kategorilerin dağılımı, model ve sanal anahtar kırılımı. Yönetimsel olaylar salt ekleme bir denetim izine yazılır ve dışa aktarılabilir. Ekranlar için [Panel](/docs/panel/), saklama ve erişim kuralları için [Güvenlik](/docs/security/). ## Yurt içinde çalışır Gateway ve maskeleme, Türkiye’de barındırılan altyapıda çalışır. Dış modele yalnız maskeli metin gider; ham kişisel veri yurt içinde işlenir ve orada kalır. Maskeleme tamamlanamazsa istek dış modele hiç gitmez, Gateway 502 döndürür. Bu davranışın adı fail-closed; ayrıntısı [Kavramlar](/docs/concepts/) sayfasında. - [Başlangıç](/docs/getting-started/): Sanal anahtarınızı alın, ilk maskeli isteğinizi gönderin. - [Koruma katmanları](/docs/guardrails/): Girdi ve yanıt maskeleme, yakında eklenecek katmanlar. - [Modeller ve sağlayıcılar](/docs/models/): Model seçimi, yeniden deneme ve alternatife geçiş. - [Panel](/docs/panel/): Kullanım grafikleri, kota, kullanıcı ve anahtar yönetimi. --- # Başlangıç Source: https://siper.gurubase.ai/docs/getting-started/ Kurulum gerektirmeden başlayın: sanal anahtarınızı alın, OpenAI SDK'da base_url değerini değiştirin ve dakikalar içinde ilk maskeli isteğinizi gönderin. İlk isteğiniz için iki adres ve bir sanal anahtar yeter. Kurulum yok; OpenAI SDK kullanıyorsanız yalnız `base_url` değerini ve anahtarı değiştirirsiniz, kodunuzun geri kalanına dokunmazsınız. ## Erişim bilgileriniz | Kullanım | Adres | | --- | --- | | API tabanı (OpenAI SDK `base_url`) | `https://gw-tr.gurubase.io/v1` | | Yönetim paneli | `https://gateway-tr.gurubase.io` | ## Sanal anahtarınızı üretin [Panele](https://gateway-tr.gurubase.io) giriş yapın ve bir sanal anahtar üretin; isteklerinizi bu anahtarla gönderirsiniz. Dil modeli sağlayıcısının gerçek anahtarı Gateway içinde kalır, uygulamanızda tutmanız gerekmez. Adımlar için [Panel](/docs/panel/). ## İlk istek Aşağıdaki üç örnek de Responses API’ye aynı isteği gönderir. Metinde bir ad ve bir TCKN var; ikisi de modele gitmeden önce maskelenir. ```bash curl https://gw-tr.gurubase.io/v1/responses \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "input": "Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor." }' ``` ```python from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) resp = client.responses.create( model="gpt-4o-mini", input="Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor.", ) print(resp.output_text) ``` ```ts import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://gw-tr.gurubase.io/v1", apiKey: process.env.SANAL_ANAHTAR, }); const resp = await client.responses.create({ model: "gpt-4o-mini", input: "Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor.", }); console.log(resp.output_text); ``` ## Ne oldu? Girdinizdeki ad ve TCKN, modele giden kopyada yer tutucularla değiştirildi: ```text Girdi : "Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor." Modele: ", TCKN , başvuru durumunu soruyor." ``` Model maskeli metinle çalışır; yanıt dönerken aynı yer tutucular korunur. Yer tutucular API çıktısında İngilizcedir; yer tutucuların biçimini ve panel gösteriminden farkını [Kavramlar](/docs/concepts/) sayfasında bulursunuz. ## Sıradaki adımlar - [Kavramlar](/docs/concepts/): Yer tutucu formatı, fail-closed davranış ve veri egemenliği. - [Gateway entegrasyonu](/docs/guides/gateway-integration/): Streaming, Chat Completions ve yalnız maskeleme. - [Kategoriler](/docs/categories/): Maskelenen 26 kişisel veri kategorisinin tam listesi. - [Panel](/docs/panel/): Sanal anahtar üretimi ve kullanım takibi. --- # Kavramlar Source: https://siper.gurubase.ai/docs/concepts/ Siper kavramları: maskeleme adımında ne olur, yer tutucu formatı nasıl okunur, fail-closed davranış ne yapar ve veriniz hangi sınırlar içinde işlenir. Maskelemesi açık bir sanal anahtardan dil modeline giden her istek önce maskeleme adımından geçer. Bu sayfa o adımda ne olduğunu anlatır: yer tutucuların biçimi, maskeleme yapılamadığında Gateway’in davranışı ve verinizin nerede işlendiği. ## Maskeleme nasıl çalışır? Gateway’e gelen metin, modele iletilmeden önce taranır. Tespit edilen her kişisel veri `` biçiminde bir yer tutucuyla değiştirilir: metindeki ilk kişi adı `` olur, ikincisi ``. Model bu alanların yerinde yer tutucuları görür; yanıt dönerken yer tutucular korunur. Ad, TCKN, telefon ve adres dahil 26 kategori tespit edilir. Tam liste ve sentetik örnekler için [Kategoriler](/docs/categories/). Bu doğruluğun arkasında veri var: KVKK’nın özel nitelikli kategorilerini (sağlık, din, siyasi görüş, sendika üyeliği ve ceza mahkûmiyeti dahil) kapsayan, Türkçeye özgü büyük bir eğitim veri setini kendimiz oluşturduk ve modeli bu setle aylar süren bir çalışmayla eğittik. Yeni sürümleri aynı test protokolüyle yeniden ölçer, karşılaştırmalı sonuçları [benchmark sayfasında](https://siper.gurubase.ai/benchmark) paylaşırız. Temmuz 2026 ölçümünde yakalama oranı %84,6’dır; hiçbir otomatik tespit sistemi her kişisel veri alanını bulmayı garanti etmez. ## Yer tutucu formatı ve dil ayrımı Doğrudan `/mask` ve `/mask/batch` yanıtlarında yer tutucular ham kategori adlarıyla döner: ``, ``, ``. OpenAI uyumlu Gateway ve yönetim paneli aynı kategorileri Türkçe etiketlerle gösterir. Aynı kategorideki her yeni değer numarayı bir artırır. | Doğrudan `/mask` | Gateway ve panel | | --- | --- | | `` | `` | | `` | `` | | `` | `` | Entegrasyon kodunda kullandığınız yüzeyin sözleşmesini esas alın: doğrudan maskeleme uçları ham kategori adlarını, Gateway ise Türkçe etiketleri döndürür. ## Maskeleme yapılamazsa ne olur? İstek durur. Maskeleme hizmeti bir isteği işleyemezse Gateway o isteği dış modele iletmez ve 502 durum koduyla yanıtlar; “maskesiz de olsa gönder” diye bir seçenek yoktur. 502 aldığınızda isteği daha sonra yeniden deneyin. Bu davranışın adı fail-closed. ## Veri egemenliği Maskeleme, model çağrısından önce, Türkiye’de barındırılan altyapıda çalışır. Maskelemesi açık akışta tespit edilen kişisel veriler Türkiye’de yer tutucuya dönüştürülür; dış dil modeline bu değerlerin maskeli biçimi gider. Diyagram: Uygulamanızın istekleri Gurubase Gateway'e gelir; Gateway yurt içinde çalışır. Siper PII Maskeleme kişisel veriyi maskeler, ham veri burada kalır; dış dil modeline yalnız maskeli metin gider. Saklama, denetim izi ve erişim konuları için [Güvenlik](/docs/security/). --- # Maskelenen kategoriler Source: https://siper.gurubase.ai/docs/categories/ Siper'in maskelediği 26 kişisel veri kategorisinin tam listesi, kısa açıklama ve sentetik örneklerle; KVKK m.6 özel nitelikli kategoriler ayrıca işaretli. Siper, Türkçe metinde 26 kişisel veri kategorisi tespit eder ve maskeler. Bu sayfa tam listedir: her kategorinin yanında kısa bir açıklama ve sentetik bir örnek var. Dokuz kategori KVKK’nın 6. maddesindeki özel nitelikli kişisel veri tanımına girer; onları ayrı bölümde bulursunuz. Örneklerin tamamı sentetiktir, gerçek bir kişiye ait değildir. Maskeli çıktıda her kategorinin kendi yer tutucusu vardır; API bunları İngilizce adlarıyla döndürür. Biçimin ayrıntısı için [Kavramlar](/docs/concepts/). ## Genel kategoriler | Kategori | Açıklama | Sentetik örnek | | --- | --- | --- | | Kişi | Ad ve soyadı. | `Ahmet Yılmaz` | | Adres | Sokak, mahalle ve açık adres bilgisi. | `Zambak Sk. No:4` | | Doğum tarihi | Gün, ay ve yıl içeren doğum tarihi. | `12.03.1981` | | TCKN | T.C. kimlik numarası. | `10000000214` | | YKN | Yabancı kimlik numarası; 99 ile başlar. | `99…` | | VKN | Vergi kimlik numarası. | vergi no | | MERSİS | Şirketlerin Merkezi Sicil Kayıt Sistemi numarası. | MERSİS no | | SGK | Sosyal Güvenlik Kurumu sicil numarası. | SGK sicil | | Pasaport | Pasaport numarası. | `U1234…` | | Seri no | Kimlik kartı seri numarası. | kimlik seri | | Telefon (mobil) | Cep telefonu numarası. | `0532 000 11 22` | | Telefon (sabit) | Sabit hat numarası. | `0212…` | | E-posta | E-posta adresi. | `ayse.demir@ornek.gov.tr` | | IBAN | Banka hesap numarası. | `TR33…` | | Kart | Ödeme kartı numarası. | `4111…` | | Plaka | Araç plakası. | `35 ABC 042` | | IP adresi | IP adresi. | `10.1.2.3` | ## Özel nitelikli kategoriler (KVKK m.6) Aşağıdaki dokuz kategori 6698 sayılı Kanunun 6. maddesi kapsamındadır. Kategorinin adı tek başına kişisel veri değildir; “sendika üyeliği” kavramını anmak ile bir kişinin sendika üyeliğini yazmak farklı şeylerdir. Bu yüzden tablodaki her örnek bir cümledir ve ters tırnaklı bölüm, Siper’in o cümlede maskelediği ifadedir. Örneklerin tamamı sentetiktir ve canlı serviste doğrulanmıştır; gerçek bir inanç, köken, parti veya kuruluş adı geçmez. | Kategori | Açıklama | Örnek cümle ve maskelenen bölüm | | --- | --- | --- | | Sağlık | Kişiye bağlı tanı, tedavi ve sağlık durumu. | Ayşe Demir’e `diyabet tanısı` kondu. | | Din | Kişinin dini inancına dair ifadeler. | Çalışan, `dini inancı` gerekçesiyle izin talep etti. | | Etnik köken | Kişinin etnik kökenine dair ifadeler. | Tanık, `etnik kökenine` yönelik ayrımcılığa uğradığını belirtti. | | Siyasi görüş | Kişinin siyasi görüşü ve parti üyeliği. | Başvuran, `Y Partisi üyeliğini` doğruladı. | | Sendika üyeliği | Kişinin sendika üyeliği. | Ahmet Yılmaz, `Örnek-İş Sendikası` üyesidir. | | Ceza mahkûmiyeti | Kişinin mahkûmiyet ve güvenlik tedbiri bilgisi. | Müşteri, `adli sicil kaydı` bulunmadığını beyan etti. | | Cinsel hayat | Kişinin cinsel hayatına dair ifadeler. | Danışan, `cinsel yönelimini` görüşmede paylaştı. | | Biyometrik | Biyometrik şablon ve kayıt kodları; kod yalnız biyometrik bağlam yakınındaysa maskelenir. | Parmak izi şablonu `FP-7788` sistemde kayıtlı. | | Genetik | Kişiye bağlı gen ve varyant adları; ad yalnız genetik bağlam içinde maskelenir. | `BRCA1` mutasyonu taşıdığı genetik testle doğrulandı. | Siper bu kategorilerde temkinli davranır: “diyabet tanısı” gibi bir ifade, cümlede açık bir kişiye bağlanmasa da maskelenebilir. Tercih bilinçlidir; kişisel veriyi kaçırma riski, genel bir ifadeyi fazladan maskeleme maliyetinden ağır basar. Kurumunuza özgü, kişisel veri taşımadığından emin olduğunuz kalıpları maskeleme dışında tutmak için `allow_patterns` alanını kullanabilirsiniz ([Yalnız maskeleme → Desen listeleri](/docs/guides/mask-only/#desen-listeleri)). Kapsamı daraltmak isterseniz `/mask` isteğinde hazır kategori kümeleri var; örneğin `KVKK_SENSITIVE` yalnız bu dokuz kategoriyi maskeler. Ayrıntı: [Yalnız maskeleme → Kategori filtreleme](/docs/guides/mask-only/#kategori-filtreleme). Kategorileri kendi metninizde denemek için [Playground](/docs/guides/playground/). --- # Koruma katmanları Source: https://siper.gurubase.ai/docs/guardrails/ Geçiş noktasında çalışan koruma katmanları: girdi maskeleme her istekte, yanıt maskeleme isteğe bağlı; prompt injection ve halüsinasyon korumaları yakında. Gateway’den geçen her istek, dış modele çıkmadan önce koruma katmanlarından geçer. Bugün çalışan katmanlar maskelemeye dayanır; aynı geçiş noktasına eklenecek iki katman daha var. | Katman | Ne yapar | Durum | | --- | --- | --- | | Girdi maskeleme | İsteğin içindeki kişisel veriyi model görmeden maskeler | Açık (varsayılan) | | Yanıt maskeleme | Modelin döndürdüğü kişisel veriyi istemciye geçmeden maskeler | İsteğe bağlı | | Prompt injection koruması | Modeli verilen talimatların dışına çıkarmayı amaçlayan girdileri işaretler | Yakında | | Halüsinasyon koruması | Modelin dayanağı olmayan yanıtlarını işaretler | Yakında | ## Girdi maskeleme Varsayılan ve her istekte çalışan katman budur. Metin dış modele iletilmeden taranır, tespit edilen her kişisel veri `` gibi bir yer tutucuyla değiştirilir ve modele yalnız maskeli metin gider. Kapsam 26 kategoridir; KVKK’nın 6. maddesindeki özel nitelikli veriler de buradadır. Tam liste ve sentetik örnekler için [Kategoriler](/docs/categories/), yer tutucu biçimi için [Kavramlar](/docs/concepts/). Maskeleme tamamlanamazsa istek dış modele gitmez ve Gateway 502 döndürür. “Maskesiz de olsa gönder” diye bir seçenek yoktur. ## Yanıt maskeleme Girdi her istekte maskelenir; yanıt tarafı kurum talep ettiğinde açılır. Model yanıtında kişisel veri üretirse ya da girdideki bir değeri yinelerse, bu değerler istemciye dönmeden maskelenir. Streaming yanıtlarda uygulanmaz: gerçek zamanlı akışı bozmamak için yanıt olduğu gibi geçer ve bu durum denetim izine işlenir. ## Maskelemeyi kapatmak Maskeleme sanal anahtar bazında kapatılabilir; o anahtardan gelen istekler doğrudan dil modeline gider ve Gateway o anahtar için yalnız bir yapay zekâ ağ geçidi gibi davranır. Aynı kurumda maskeli ve maskesiz anahtarlar yan yana çalışabilir. KVKK sorumluluğu Maskelemesi kapalı bir anahtardan gönderilen kişisel veri, maskelenmeden dil modeline iletilir; bu trafikte KVKK kapsamındaki sorumluluk tümüyle kurumdadır. Maskelemeyi yalnız kişisel veri taşımadığından emin olduğunuz anahtarlarda kapatın; emin değilseniz açık bırakın. ## Yakında eklenecek katmanlar İki katman geliştirme aşamasındadır. İkisi de aynı geçiş noktasında, maskeleme ile aynı akışta çalışacak şekilde tasarlanıyor. **Prompt injection koruması.** Kullanıcı girdisine gizlenmiş, modeli kendisine verilen talimatların dışına çıkarmayı amaçlayan denemeleri işaretler. Tipik örnek, görünüşte sıradan bir metnin içine yerleştirilmiş “önceki talimatları yok say” türü yönergelerdir. **Halüsinasyon koruması.** Modelin, dayanağı olmayan bir yanıtı emin bir dille verdiği durumları işaretler. Kişisel veri sızıntısından farklı bir risktir: burada sorun verinin dışarı çıkması değil, içeri yanlış bilginin girmesidir. Yayına alındıklarında bu sayfa güncellenir ve [Sürüm notları](/docs/release-notes/) sayfasına tarihli bir giriş düşülür. --- # Modeller ve sağlayıcılar Source: https://siper.gurubase.ai/docs/models/ Tek OpenAI uyumlu arayüzün arkasında OpenAI ve Anthropic dahil farklı sağlayıcılar: model seçimi, erişilebilir modelleri listeleme, yeniden deneme ve alternatife geçiş. Gateway tek bir OpenAI uyumlu arayüz sunar. Arkasında hangi sağlayıcının çalıştığı istemciyi ilgilendirmez: uygulamanız aynı istek biçimini gönderir, değişen tek alan `model` olur. ## Model seçimi Model adı istekte belirtilir. Kuruma tanımlı modeller arasında geçiş yapmak için tek satır değişir; SDK, parametreler ve yanıt biçimi aynı kalır. ```python resp = client.responses.create( model="gpt-4o-mini", input="Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor.", ) ``` Hangi modellere erişebildiğinizi `/v1/models` ucundan alırsınız. Liste, kurumunuz için tanımlanmış modelleri döndürür; yalnız maskeleme için ayrılmış `gurubase-siper` adı da buradadır. Uç noktanın tam referansı için [Erişilebilir modelleri listele](/docs/api/gateway/models/listmodels/). ## Sağlayıcılar Aynı arayüzün arkasında iki tür sağlayıcı çalışabilir: OpenAI, Anthropic ve Gemini gibi genel sağlayıcılar ya da kendi sunucunuzda barındırdığınız modeller. Hangi sağlayıcıların açık olacağı ve her sanal anahtarın hangi modellere erişeceği kurum için tanımlanır. Sağlayıcının gerçek API anahtarı Gateway içinde durur. Uygulamalarınız ve panel kullanıcıları yalnız sanal anahtar görür; sağlayıcı anahtarı istemciye hiçbir zaman inmez. Anahtar üretme, döndürme ve iptal adımları için [Panel](/docs/panel/). Maskeleme bu seçimden bağımsızdır: hangi sağlayıcı seçilirse seçilsin, istek dış modele çıkmadan önce aynı koruma katmanlarından geçer. Katmanlar için [Koruma katmanları](/docs/guardrails/). ## Yeniden deneme ve alternatife geçiş Sağlayıcılar zaman zaman hız sınırı döndürür ya da yavaşlar. Bu durumda yeniden deneme kararı uygulama kodunuzda değil, Gateway’de verilir: istek, artan bekleme aralıklarıyla yeniden denenir. Kurumunuz için birden fazla sağlayıcı tanımlıysa, bir sağlayıcı yanıt veremediğinde isteğin alternatif bir sağlayıcıya yönlendirilmesi de aynı yerde yapılandırılır. Uygulama tarafında ek kod gerekmez. Sizin tarafınızdaki limitler (dakika başına istek, token bütçesi ve 429 davranışı) ayrı bir konudur; ayrıntısı [Limitler ve kotalar](/docs/limits/) sayfasındadır. --- # Panel Source: https://siper.gurubase.ai/docs/panel/ Gurubase Gateway yönetim paneli: giriş ve MFA, kullanım grafikleri, token bütçesi ve kota alarmları, kullanıcı ve sanal anahtar yönetimi tek yerde. Gateway’i [https://gateway-tr.gurubase.io](https://gateway-tr.gurubase.io) adresindeki panelden yönetirsiniz: sanal anahtarlar, kullanım takibi, kota ve kullanıcılar tek yerde. Giriş yaptığınızda Genel Bakış ekranı açılır; token bütçenizin durumunu, sağlayıcıya giden isteklerdeki hata oranını ve maskeleme sayaçlarını burada görürsünüz. ![Genel Bakış ekranı: token bütçesi, hata oranı ve maskeleme sayaçları](/docs/screenshots/panel/genel-bakis-light@2x.png) ## Giriş ve MFA Panele e-posta ve şifrenizle girersiniz. İlk girişte çok faktörlü doğrulama (MFA) kurulumu istenir: bir TOTP uygulamasıyla (Google Authenticator, 1Password gibi) QR kodu okutur, üretilen 6 haneli kodu girersiniz. Sonraki girişlerde şifrenin yanında o anki kod sorulur. MFA atlanamaz; telefonunu değiştirip kod üretemeyen bir kullanıcının doğrulamasını yönetici sıfırlar. ![İki adımlı doğrulama ekranı](/docs/screenshots/panel/giris-mfa-light@2x.png) ## Kullanım grafikleri Kullanım ekranı, seçtiğiniz zaman aralığı için istek ve token sayısını giriş/çıkış ayrımıyla gösterir. Günlük işlenen karakter grafiği ve tespit edilen kategorilerin dağılımı aynı ekrandadır; model ve sanal anahtar kırılımıyla hangi anahtarın ne tükettiğini izlersiniz. ![Kullanım grafikleri: işlenen karakter ve kategori dağılımı](/docs/screenshots/panel/kullanim-grafikleri-light@2x.png) ## Kota ve alarmlar Token bütçeniz panelde canlı bir kartta durur: kullanılan, kalan ve uyarı eşikleri. Kart, %80 ve doluluk eşiklerinde sizi uyarır; hizmet kesilmez. Bütçe modelinin ayrıntısı ve 429 davranışı için [Limitler ve kotalar](/docs/limits/). ![Token bütçesi kartı: kullanılan ve kalan token](/docs/screenshots/panel/kota-alarm-light@2x.png) ## Kullanıcı yönetimi Kurum içi hesapları Kullanıcılar ekranından yönetirsiniz. Yeni kullanıcı davet eder, rol atarsınız; yetkiler rol tabanlıdır (RBAC). Bir hesabı pasifleştirebilir, gerektiğinde MFA kurulumunu sıfırlayabilirsiniz. Her kullanıcının sanal anahtarları ve kota kullanımı da aynı ekrandan izlenir. ![Kullanıcılar ekranı: rol, durum ve MFA sütunlarıyla hesap listesi](/docs/screenshots/panel/kullanicilar-light@2x.png) ## Anahtar yönetimi Sanal anahtarları Anahtarlar ekranından üretir, döndürür ve iptal edersiniz. Üretilen anahtar tam haliyle yalnız oluşturma anında görünür; o anda güvenli bir yere kaydedin. Sonrasında listede yalnız maskeli özeti kalır. Dil modeli sağlayıcısının gerçek anahtarı panelde de istemcide de görünmez; Gateway içinde durur. Anahtarı uygulamanıza bağlamak için [Gateway entegrasyonu](/docs/guides/gateway-integration/). ![Anahtarlar ekranı: maskeli anahtar listesi ve hazır kullanım örnekleri](/docs/screenshots/panel/anahtarlar-light@2x.png) Her anahtarda neyin maskeleneceğini ayrı ayrı seçebilirsiniz. Anahtarın satırındaki üç noktadan **Güncelle**’yi açın: yerleşik veri türleri ile kurumunuza özel desenler aynı yerde listelenir, tek tıkla açıp kapatırsınız. Varsayılan olarak hepsi açıktır; kapattığınız tür yalnız o anahtarda maskelenmez ve modele olduğu gibi gider. ![Anahtarı güncelle penceresi: yerleşik veri türleri ve kuruma özel desenler için aç kapa listesi](/docs/screenshots/panel/anahtar-guncelle-light@2x.png) Kapatılanların saklanması bilinçli bir tercihtir: Ayarlar’a sonradan yeni bir desen eklediğinizde o desen mevcut anahtarlarınıza kendiliğinden uygulanır. Böylece yeni bir kuralı tek tek anahtarlara işlemeniz gerekmez. Maskelemeyi kod yazmadan denemek isterseniz paneldeki Playground yeter; akışı [Playground](/docs/guides/playground/) rehberi anlatır. ## Maskeleme desenleri Yerleşik kategoriler kimlik numarası, telefon, adres gibi yaygın kişisel verileri kapsar. Kurumunuzun kendi tanımlayıcıları da varsa (dosya numarası, müvekkil kodu, sipariş numarası gibi) bunları **Ayarlar > Maskeleme Desenleri** bölümünden tanımlarsınız. Verdiğiniz etiket, maskeli çıktıda görünen yer tutucuyu belirler: `MUVEKKIL_NO` etiketi `` üretir. ![Maskeleme desenleri ekranı: desen listesi, anlık geçerlilik denetimi ve yerleşik kategori listesi](/docs/screenshots/panel/maskeleme-desenleri-light@2x.png) Ekran üç şeyi kolaylaştırır: - **Anlık denetim.** Yazarken desenin geçerli olup olmadığını görürsünüz. Kesin sonuç maskeleme servisinden gelir, tarayıcıdan değil; bu yüzden kaydedilen bir desen üretimde sürpriz yapmaz. - **Test penceresi.** Örnek metin yazıp desenlerin gerçek etkisini görürsünüz: hangi parçalar maskelendi, muafiyetler neyi açıkta bıraktı. - **Yerleşik kategori listesi.** Zaten bulduğumuz veri türleri örnekleriyle listelenir, böylece hâlihazırda kapsanan bir türü yeniden tanımlamazsınız. Yerleşik bir adla çakışan etiket kaydedilmez: aynı ad iki farklı kaynağı tek yer tutucu altında karıştırır ve geri çevirme eşlemesini belirsizleştirirdi. Tanımlar kurum düzeyinde tutulur, yani tek yerde tanımlarsınız ve tüm anahtarlarınıza uygulanır. Anahtar bazında istisna yapmak isterseniz yukarıdaki **Güncelle** penceresinden kapatabilirsiniz; desenin kendisi yine Ayarlar’da kalır. Desen sayısı ve uzunluğu için geçerli sınırlar [Limitler ve kotalar](/docs/limits/) sayfasında. Muafiyet desenleri ters yönde çalışır: eşleşen değer maskelenmez. Kamuya açık bir kurum adı yanlışlıkla kişisel veri sanılıyorsa işinize yarar. Maskelemeyi azalttıkları için panelde ayrıca işaretlenirler; ne açtığınızı görerek karar verin. --- # Limitler ve kotalar Source: https://siper.gurubase.ai/docs/limits/ Siper'de limitler ve kotalar: dönemsel token bütçesi, dakika başına istek (RPM), 429 yanıtının anlamı ve Retry-After ile doğru yeniden deneme. Normal kullanımda bir limite takılmazsınız; limitler bilerek cömert tutulur. Hesabınıza uygulanan iki mekanizma vardır: dönemsel token bütçesi ve anahtar bazında dakika başına istek limiti. Amaç kullanımı kısıtlamak değil; hizmetin herkes için öngörülebilir kalması. ## Token bütçesi Tüm istekleriniz, dönem için tanımlanan tek bir token bütçesinden düşülür. Kullanılmayan token dönem sonunda yanmaz; bütçe devreder ve birikir. Bütçe dolunca hizmet kesilmez. Bütçenin %80’ine geldiğinizde ve bütçe dolduğunda panelde birer uyarı belirir; istekleriniz işlenmeye devam eder. Kalan token, kullanım oranı ve eşikler paneldeki Token Bütçesi kartında canlı görünür; kartın yeri için [Panel](/docs/panel/). ## Dakika başına istek (RPM) Her sanal anahtar için dakika başına istek (requests per minute, RPM) limiti isteğe bağlı olarak tanımlanabilir. Varsayılan sınırsızdır; limit yalnız açıkça ayarlandığında uygulanır ve kısa süreli ani yükte hizmeti korur. Anahtarınıza uygulanan değer paneldeki anahtar listesinde yazar; değer yoksa anahtar sınırsızdır. ## 429 yanıtı ve Retry-After RPM limitine ulaşırsanız Gateway, OpenAI ile uyumlu bir 429 yanıtı döndürür: ```http HTTP/1.1 429 Too Many Requests Retry-After: 2 Content-Type: application/json { "error": { "type": "rate_limit_exceeded", "message": "Dakika başına istek limiti aşıldı." } } ``` `Retry-After` başlığı kaç saniye sonra yeniden deneyebileceğinizi söyler. Çoğu OpenAI SDK’sı 429’u kendiliğinden yeniden dener; kendi istemcinizi yazıyorsanız artan aralıklarla yeniden deneme ekleyin. 429, kota aşımı değildir. Token bütçeniz dolduğunda istekler durmaz, yalnız uyarı görürsünüz; 429 yalnız anlık hız limitinde döner ve `Retry-After` süresi geçince kendiliğinden çözülür. ## Maskeleme deseni sınırları Kurumunuza özel desenler için üç sınır vardır: en çok **25 desen**, desen başına en çok **200 karakter** ve tarama için bir zaman bütçesi. Sınırlar keyfi değil; kötü kurgulanmış tek bir desen maskelemeyi uzun süre meşgul edebilir, bütçe bunu keser. Bütçe aşıldığında iki yön farklı davranır ve bu ayrım bilinçlidir: - **Maskeleyen desen** bütçeyi aşarsa istek `422` ile reddedilir. Sessizce eksik maskelemek yerine hata vermeyi tercih ediyoruz. - **Muafiyet deseni** bütçeyi aşarsa o desen uygulanmaz ve istek normal şekilde tamamlanır. Muafiyet maskelemeyi azaltır; azaltan bir kural belirsizlikte devreye girmemelidir. Aynı sınırlar, desenleri doğrudan istek gövdesinde gönderdiğinizde de geçerlidir. Panelden tanımladığınız kurum desenleri istekteki desenlere eklenir ve istek gövdesiyle düşürülemez; sonuç yalnız maskelemeyi artırır. Desenleri panelden tanımlamak için [Panel](/docs/panel/). ## Özet | Limit | Varsayılan | Aşımda davranış | Nerede görünür | | --- | --- | --- | --- | | Token bütçesi | Dönemsel, devirli | Uyarı; hizmet kesilmez | Paneldeki Token Bütçesi kartı | | RPM | Sınırsız; anahtara göre ayarlanabilir | `429` + `Retry-After` | Paneldeki anahtar listesi | | Maskeleme deseni | En çok 25 desen, 200 karakter | Maskeleyen desen `422`; muafiyet uygulanmaz | Ayarlar > Maskeleme Desenleri | Bütçenizi büyütmek veya bir anahtara özel limit tanımlamak isterseniz bizimle iletişime geçin. --- # Güvenlik Source: https://siper.gurubase.ai/docs/security/ Kişisel veri modele gitmeden maskelenir. Fail-closed davranış, veri saklamama, Türkiye'de barındırılan altyapı ve denetim izi. Kişisel veri, dış dil modeline gitmeden önce Türkiye’de maskelenir; güvenlik modelinin geri kalanı bu cümleyi ayakta tutmak için var. Bu sayfada hata durumunda ne olduğunu, nelerin saklanmadığını ve panele kimin nasıl eriştiğini bulursunuz. ## Kişisel veri modele gitmeden maskelenir Her istek, dil modeli çağrılmadan önce maskeleme adımından geçer. Modele yalnız maskeli metin gider; tespit edilen değerlerin yerinde `` gibi yer tutucular vardır. Yer tutucu biçimi için [Kavramlar](/docs/concepts/). ## Yanıt maskeleme Girdi her istekte maskelenir; kurum talep ederse yanıt tarafı da açılır ve modelin döndürdüğü kişisel veri istemciye geçmeden maskelenir. Davranışın ayrıntısı ve streaming istisnası [Koruma katmanları](/docs/guardrails/) sayfasındadır. ## Maskeleme yapılamazsa istek durur Maskeleme fail-closed çalışır: maskeleme tamamlanamadığında istek dış modele gitmez, Gateway 502 döndürür ve orijinal metni de iletmez. Kuşkulu durumda istek geçmez. Davranışın ayrıntısı [Kavramlar](/docs/concepts/) sayfasında. ## Maskeleme aç/kapa (passthrough) Maskeleme varsayılan olarak açıktır ve önerdiğimiz kullanım budur. Kurum isterse belirli bir sanal anahtar için maskelemeyi kapatabilir; ayar anahtar bazındadır ve panelden anında devreye girer. Maskelemesi kapalı anahtarlarda KVKK sorumluluğu tümüyle kurumdadır. Ayrıntı için [Koruma katmanları](/docs/guardrails/). ## Veri saklamama Ham kişisel veri kalıcı olarak saklanmaz. Yer tutucudan orijinal değere dönmeyi mümkün kılan eşleme (vault) varsayılan olarak kapalıdır; yalnız açıkça istendiğinde üretilir ve loglanmaz. ## Veri egemenliği Maskeleme, Türkiye’de barındırılan altyapıda ve model çağrısından önce çalışır. Platform ve maskeleme modeli DT Cloud İstanbul sunucularında barındırılır. Yurt dışındaki modele yalnız maskeli metin gider; ham kişisel veri yurt içinde işlenir ve orada kalır. Altyapıyı tamamen kendi sistemlerinde çalıştırmak isteyen kurumlar için kurum içi kurulum seçeneği de vardır; iki çalışma modelinin karşılaştırması için [Deployment](/docs/deployment/). ## Denetim izi Yönetimsel olaylar (girişler, MFA kurulumları; anahtar üretme, döndürme ve iptal; kullanıcı ve kota değişiklikleri) salt ekleme (append-only) bir denetim izine yazılır. Kayıtlar sonradan değiştirilmez, ize yalnız yeni kayıt eklenir; iz CSV veya Excel olarak dışa aktarılabilir. Maskeleme olayları için kategori ve tespit sayısı gibi üstveriler tutulur; iz yüzey metni içermez, maskelenen metnin kendisi kayda geçmez. ![Denetim izi ekranı: olay listesi yalnız üstveri gösterir, yüzey metni yok](/docs/screenshots/panel/denetim-light@2x.png) ## Erişim güvenliği Panele giriş e-posta, şifre ve zorunlu TOTP koduyla yapılır; yetkiler rol tabanlıdır. Trafik TLS ile şifrelenir. Dil modeli sağlayıcısının gerçek anahtarı yalnız Gateway içinde durur; panel ve istemciler sanal anahtarla çalışır. Panel adımları için [Panel](/docs/panel/). ## Maskelenen kategoriler Maskeleme 26 kategoriyi kapsar; ad, TCKN, IBAN gibi genel kategorilerin yanında KVKK’nın 6. maddesindeki özel nitelikli veriler de bu kapsamdadır. Tam liste ve sentetik örnekler için [Kategoriler](/docs/categories/). --- # Deployment Source: https://siper.gurubase.ai/docs/deployment/ Siper iki şekilde çalışır: İstanbul'da bizim işlettiğimiz yönetilen hizmet ya da kurumun kendi sunucularındaki kurulum. Ürün ikisinde de birebir aynıdır. Siper iki şekilde çalıştırılabilir: İstanbul’da bizim işlettiğimiz yönetilen hizmet ya da kurumun kendi sunucularındaki kurulum. Bu sayfa ikisi arasındaki farkı anlatır. Kurulum adımlarını içermez; kurum içi kurulum sizinle birlikte planlanır ve yürütülür. Önemli olan şu: **ürün ikisinde de birebir aynıdır.** Gateway, maskeleme ve panel tek bir bütün olarak kurulur. Kurum içi kurulumda kırpılmış bir sürüm almazsınız. Diyagram, iki kurulum modelini karşılaştırır. Yönetilen hizmette uygulamanız kurumunuzda çalışır; Gateway ve maskeleme İstanbul'daki altyapımızın sınırı içindedir ve dış sağlayıcıya yalnız maskeli metin gider. Kurum içi kurulumda uygulamanız, Gateway ve maskeleme aynı sınırın, yani kurumunuzun içindedir; dış sağlayıcıya yine yalnız maskeli metin gider. Sağlayıcı da kendi sunucunuzdaysa istek kurum ağının dışına hiç çıkmaz. | | Yönetilen hizmet | Kurum içi kurulum | | --- | --- | --- | | Nerede çalışır | İstanbul’daki altyapımızda | Kurumun kendi sunucularında | | Kim işletir | Biz | Kurumun kendi ekibi | | Ham veri nerede işlenir | Türkiye’de, altyapımızda | Kurum ortamında | | Panel, denetim izi, kategoriler | Aynı | Aynı | | API sözleşmesi ve maskeleme davranışı | Aynı | Aynı | ## İki modelde de aynı olan Maskeleme davranışı, 26 kategori, yer tutucu biçimi ve fail-closed kuralı değişmez. Panel, denetim izi, sanal anahtar yönetimi ve kullanım grafikleri aynıdır. API sözleşmesi aynıdır: uygulamanız hangi modelde çalıştığını bilmek zorunda değildir, yalnız `base_url` farklıdır. Bu, kurum içi kuruluma geçmenin ya da tersine yönetilen hizmete taşınmanın uygulama kodunuzda değişiklik gerektirmediği anlamına gelir. ## Dış model trafiği Gateway’in seçilen dil modeli sağlayıcısına çıkışı her iki modelde de vardır: istek maskelendikten sonra sağlayıcıya gider. Yani kurum içi kurulum tek başına “hiçbir şey dışarı çıkmaz” demek değildir; dışarı çıkan şey maskeli metindir. Tamamen kapalı bir kurulum istiyorsanız, sağlayıcı olarak kendi sunucunuzdaki bir modeli seçersiniz. vLLM ve Ollama gibi çözümlerin OpenAI uyumlu arayüzü olduğu için Gateway bunlara da aynı şekilde bağlanır. Bu durumda istek kurum ağının dışına hiç çıkmaz. Sağlayıcı seçimi için [Modeller ve sağlayıcılar](/docs/models/). ## Hangisini seçmeli Çoğu kurum için İstanbul’daki yönetilen hizmet en pratik yoldur: kurulum ve işletme bizde kalır, ham veri yine Türkiye’de işlenir ve dış modele yalnız maskeli metin gider. Veriyi kendi altyapısından hiç çıkaramayan kurumlar için kurum içi kurulum vardır. Kapsam, işletme sorumluluğu ve sürüm güncellemeleri sözleşmeyle belirlenir; başlamak için [bizimle iletişime geçin](https://siper.gurubase.ai/iletisim). Veri saklama, denetim izi ve erişim kuralları için [Güvenlik](/docs/security/). --- # Release notes Source: https://siper.gurubase.ai/docs/release-notes/ Siper'de yayına alınan iyileştirme ve düzeltmelerin tek sayfalık dökümü: yeni yetenekler, maskeleme ve panel değişiklikleri; en yeni değişiklik en üstte. Siper’de yayına alınan değişiklikler bu sayfada en yeniden en eskiye doğru listelenir. ## 8 Temmuz 2026 **İyileştirme:** Doğum tarihi kategorisi artık daha fazla yazım biçimini tanıyor: yazıyla ay (“7 Mart 1985”), ISO biçimi (“1992-10-12”) ve iki haneli yıl (“15.03.85”). Tespit için doğum bağlamı gerekir; sözleşme veya fatura tarihi gibi doğum bildirmeyen tarihler maskelenmez. Kategorilerin tam listesi için [Kategoriler](/docs/categories/). **İyileştirme:** Bir kullanıcı, kısa metinde sorunsuz maskelenen bir bloğun aynı istekte defalarca tekrarlanması durumunda bazı adların gözden kaçabildiğini bildirdi. Sorun giderildi; uzun ve tekrarlı metinlerde tespit artık kararlı. Ayrıca aynı değer metinde kaç kez geçerse geçsin hep aynı numaralı yer tutucuyu alır; örneğin aynı ad her geçtiği yerde `` olur. Normal harflerin süslü, kalın veya tam genişlik gibi farklı Unicode yazımlarıyla yazılmış kişisel veriler de artık tespit ediliyor. Yer tutucu biçimi için [Kavramlar](/docs/concepts/). ## 3 Temmuz 2026 **İyileştirme:** `/mask` ve `/mask/batch` uçlarının varsayılan yanıtı sadeleşti. Yanıt artık `masked_text`, `transform`, `spans` (kategori, karakter aralığı ve güven puanı) ile `timings_ms.total` alanlarından oluşur; iç alanlar yanıttan çıkarıldı. Alanların açıklamasını [Yalnız maskeleme](/docs/guides/mask-only/) rehberinde bulursunuz. **Düzeltme:** Ürünü ilk kez deneyenler çoğu zaman herkesçe bilinen test kimlik numaralarını yapıştırıyor; bu numaralar bilinçli bir istisna listesinde olduğu için maskelenmiyordu ve “çalışmıyor” izlenimi doğuyordu. İstisna kaldırıldı: NVİ’nin tanınmış test numarası artık maskelenir. Vergi numarası bağlamıyla yazılmış bilinen test vergi kimlik numaraları için de aynısı geçerli. Kendi metninizle denemek için [Playground](/docs/guides/playground/). ## 23 Haziran 2026 **Düzeltme:** Bir kullanıcı bildirimi üzerine giderildi: Kimlik numarası metinde yalnız “TC” kısaltmasıyla anıldığında bazı durumlarda maskelenmiyordu. Artık bu yazım da maskelenir. Kategorilerin tam listesi için [Kategoriler](/docs/categories/). --- # Gateway entegrasyonu Source: https://siper.gurubase.ai/docs/guides/gateway-integration/ OpenAI SDK ile geçiş, Responses API ve Chat Completions, streaming, yalnız maskeleme ve sanal anahtar. Mevcut OpenAI entegrasyonunuzu Gateway’e taşırken yalnız iki değer değişir: - `base_url` → `https://gw-tr.gurubase.io/v1` - API anahtarı → [panelden](https://gateway-tr.gurubase.io) ürettiğiniz sanal anahtar Gerisi standart OpenAI SDK’sıdır; model adı, parametreler ve yanıt biçimi aynı kalır. Maskeleme her istekte otomatik çalışır: girdi, modele iletilmeden önce maskelenir. ## Drop-in geçiş Aşağıdaki örneklerde yalnız `base_url` ve anahtar satırları Gateway’e özgüdür; kodun kalanı, doğrudan sağlayıcıya giden sürümle aynıdır. ### Responses API Varsayılan yol Responses API’dir. Örnekteki ad ve TCKN, modele gitmeden maskelenir. ```python from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) resp = client.responses.create( model="gpt-4o-mini", input="Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor.", ) print(resp.output_text) ``` ```bash curl https://gw-tr.gurubase.io/v1/responses \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "input": "Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor." }' ``` ```ts import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://gw-tr.gurubase.io/v1", apiKey: process.env.SANAL_ANAHTAR, }); const resp = await client.responses.create({ model: "gpt-4o-mini", input: "Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor.", }); console.log(resp.output_text); ``` ### Chat Completions Kodunuz `chat.completions` kullanıyorsa Responses API’ye geçmeniz gerekmez; aynı iki değişiklik burada da yeter. Bundan sonraki Python ve TypeScript örnekleri, yukarıda tanımlanan `client` ile devam eder. ```python resp = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "user", "content": "Ayşe Demir'in talebini özetle."}, ], ) print(resp.choices[0].message.content) ``` ```bash curl https://gw-tr.gurubase.io/v1/chat/completions \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [ { "role": "user", "content": "Ayşe Demir'\''in talebini özetle." } ] }' ``` ```ts const resp = await client.chat.completions.create({ model: "gpt-4o-mini", messages: [{ role: "user", content: "Ayşe Demir'in talebini özetle." }], }); console.log(resp.choices[0].message.content); ``` ## Streaming `stream: true` verdiğinizde yanıt SSE ile parça parça akar. Maskelemenin yeri değişmez: girdi modele gitmeden maskelenir, akış maskeli metin üzerinden üretilir. ```python stream = client.chat.completions.create( model="gpt-4o-mini", stream=True, messages=[{"role": "user", "content": "Toplantı notlarını madde madde özetle."}], ) for chunk in stream: print(chunk.choices[0].delta.content or "", end="", flush=True) ``` ```ts const stream = await client.chat.completions.create({ model: "gpt-4o-mini", stream: true, messages: [{ role: "user", content: "Toplantı notlarını madde madde özetle." }], }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ""); } ``` ## Yalnız maskeleme (`gurubase-siper`) Metni dil modeline göndermeden, aynı uçtan yalnız maskeleme alabilirsiniz. `model` alanına rezerve `gurubase-siper` değerini verin; Gateway metni maskeler ve maskeli halini doğrudan döndürür. ```bash curl https://gw-tr.gurubase.io/v1/responses \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "model": "gurubase-siper", "input": "Vatandaş Ahmet Yılmaz, TCKN 10000000382, başvuru durumu nedir?" }' ``` Maskeli metin `output_text` alanında döner: ```text Vatandaş , TCKN , başvuru durumu nedir? ``` İstek hiçbir dil modeline gitmez; `gurubase-siper` bir dil modeli değil, Gateway’in maskeleme için ayırdığı rezerve model adıdır ve Chat Completions ile de çalışır. Maskeleme yapılamazsa istek 502 ile durur, ham metin de dönmez (fail-closed). Tespit raporuna (kategori ve konum listesi) da ihtiyacınız varsa doğrudan `/mask` ucunu kullanın: [Yalnız maskeleme](/docs/guides/mask-only/). ## Sanal anahtar Tüm istekler `Authorization: Bearer` başlığındaki sanal anahtarla doğrulanır. Sanal anahtarı panelden üretirsiniz; gerçek sağlayıcı anahtarı yalnız Gateway içinde durur, uygulamanızda tutmanız gerekmez. Bir anahtarı panelden iptal edip yenisini üretebilirsiniz. Adımlar için [Panel](/docs/panel/). ## Modelleri listeleme Erişebildiğiniz modelleri `/v1/models` ucundan alırsınız; listede rezerve `gurubase-siper` adı da görünür. ```bash curl https://gw-tr.gurubase.io/v1/models \ -H "Authorization: Bearer $SANAL_ANAHTAR" ``` Maskelemeyi Gateway olmadan, kendi akışınızın bir adımı olarak kullanmak için [Yalnız maskeleme](/docs/guides/mask-only/); kod yazmadan denemek için [Playground](/docs/guides/playground/). Kendi uygulamanızı yazmak yerine hazır bir kurumsal asistan arıyorsanız [Gurubase](https://gurubase.io) kurumun bilgi kaynaklarına (Confluence, Zendesk, Google Drive, web sitesi ve benzeri) bağlanan, yanıtlarını bu kaynaklara dayandırıp kaynak gösteren ajanlar sunar; bulut veya kurum içi (on-premise) kurulabilir. --- # Yalnız maskeleme Source: https://siper.gurubase.ai/docs/guides/mask-only/ Siper /mask ucunun doğrudan kullanımı. Dönüşüm seçenekleri, toplu istek, kategori filtreleme ve desen listeleri. Maskelemeyi dil modeli olmadan, kendi akışınızın bir adımı olarak da kullanabilirsiniz. `/mask` ucu metni alır; maskeli metinle birlikte hangi aralıkta ne bulunduğunu gösteren bir tespit raporu döndürür. Diyagram: girdi metni /mask uç noktasına gider; yanıt maskeli metin ve tespit raporunu birlikte döner. İstekleri, panelden ürettiğiniz sanal anahtarla `Authorization: Bearer` başlığında yetkilendirirsiniz; Gateway çağrılarında kullandığınız anahtarın aynısıdır. `/mask` çağrıları da istek limitlerine ve denetim izine tabidir. Gövde hataları (eksik veya bozuk istek) ve kimlik hataları Gateway’in hata biçimiyle döner; alan doğrulama ayrıntıları ise maskeleme servisinin kendi biçimiyle gelebilir. ## İlk çağrı ```bash curl https://gw-tr.gurubase.io/mask \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{"text": "Ahmet Yılmaz, TCKN 10000000382, İstanbul'\''da yaşıyor."}' ``` ```json { "masked_text": ", TCKN , İstanbul'da yaşıyor.", "transform": "placeholder", "spans": [ { "category": "person", "start": 0, "end": 12, "score": 0.85 }, { "category": "tckn", "start": 19, "end": 30, "score": 1.0 } ], "timings_ms": { "total": 27.58 } } ``` `masked_text` maskeli metindir; doğrudan maskeleme uçlarında yer tutucular ham kategori adlarını kullanır ([Kavramlar](/docs/concepts/)). `spans` listesi her tespit için kategoriyi, girdi metnindeki karakter aralığını (`start`, `end`) ve güven puanını (`score`) verir. `timings_ms.total` toplam işleme süresidir. ## Dönüşüm seçenekleri `transform` alanı maskeli metnin biçimini belirler; varsayılan `placeholder`. | Değer | Davranış | | --- | --- | | `placeholder` | Değeri `` gibi numaralı bir yer tutucuyla değiştirir; hangi kategoriden kaç değer geçtiği görünür kalır. | | `mask` | Karakterleri dolgu karakteriyle örter; uzunluk korunur. Dolgu karakterini `mask_char` ile seçersiniz, varsayılan `#`. | ## Toplu istek Birden çok metni `/mask/batch` ucuna tek istekte gönderirsiniz; `results` dizisi girdiyle aynı sırada döner. Uzunluk sınırını aşan metin için `/mask` 413 döndürür. `/mask/batch`’te bu sınır, birleştirilmiş toplam metin üzerinden uygulanır. ```bash curl https://gw-tr.gurubase.io/mask/batch \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "texts": [ "Ahmet Yılmaz aradı.", "IBAN: TR12 0001 0000 0000 0000 0000 01" ] }' ``` ## Kategori filtreleme Varsayılan davranış 26 kategorinin tamamını maskelemektir. `categories` alanıyla kapsamı daraltırsınız: bir `preset` seçersiniz, gerekirse `enable` listesi kümeye kategori ekler, `disable` çıkarır. Kategori anahtarları, rapordaki `category` değerleriyle aynıdır (`person`, `tckn`, `saglik` gibi). | Preset | Kapsam | | --- | --- | | `ALL` | Tüm kategoriler; varsayılan davranışla aynı. | | `KVKK` | Tüm KVKK kapsamı; `ALL` ile aynı küme. | | `KVKK_SENSITIVE` | Yalnız m.6 özel nitelikli dokuz kategori. | | `IDENTITY` | Yalnız kişi ve adres. | | `IDENTIFIERS` | Yalnız numara ve kod türü tanımlayıcılar (TCKN, IBAN, telefon gibi). | ```json { "text": "...", "categories": { "preset": "KVKK_SENSITIVE" } } ``` Kategorilerin tam listesi ve m.6 ayrımı için [Kategoriler](/docs/categories/). ## Desen listeleri İki liste alanıyla maskeleme kararına kendi kurallarınızı eklersiniz. İkisi de düzenli ifade (regular expression, Python `re` sözdizimi) listesi alır; geçersiz bir desen 422 döndürür. - `allow_patterns`: tespit edilen bir alanın yüzey metni desenle eşleşiyorsa o alan maskelenmez. Kişisel veri olmayan sabit değerler için kullanışlıdır; örneğin ortak destek adresinizin veya kurum adınızın maskelenmesini istemezsiniz. - `block_patterns`: desenle eşleşen her metin parçası, model tespit etmemiş olsa bile maskelenir. Kuruma özgü sicil, dosya veya müşteri numarası biçimlerini garantiye almak için. Düz dize verirseniz kategori `custom` olur; `{"pattern": ..., "category": ...}` nesnesiyle kategori atarsınız. Mevcut bir tespitle çakışan eşleşme atlanır; tespit kazanır. ```json { "text": "...", "allow_patterns": ["destek@kurum\\.example", "\\bDemo Kurum\\b"], "block_patterns": [ "\\bMST-\\d{6}\\b", { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" } ] } ``` Yer tutucu biçimi ve dil ayrımı için [Kavramlar](/docs/concepts/). Aynı maskelemeyi sohbet akışının içinde kullanmak için [Gateway entegrasyonu](/docs/guides/gateway-integration/). --- # Playground Source: https://siper.gurubase.ai/docs/guides/playground/ Paneldeki Playground ile maskelemeyi kod yazmadan deneyin. Canlı önizleme, hazır örnekler ve sohbet. Maskelemeyi denemenin en hızlı yolu paneldeki Playground’dur. Kod yazmazsınız: metni yapıştırırsınız, maskeli halini ve modelin yanıtını aynı ekranda görürsünüz. ## Maskeleme önizlemesi Metni yazarken panel, tespit edilen kişisel verileri anında işaretler. Her kategori kendi rengiyle vurgulanır; maskeli çıktı hemen yanında durur. İstek göndermeden önce, modele gidecek metnin son halini bilirsiniz. ![Playground maskeleme ekranı: girdi metni ve renk kodlu maskeli çıktı yan yana](/docs/screenshots/panel/playground-maskeleme-light@2x.png) ## Hazır örnekler Hazır örneklerden biriyle başlayabilirsiniz; şöyle görünür: ```text Girdi : "Ayşe Demir, ayse.demir@ornek.gov.tr, 0532 000 11 22'den ulaşılabilir." Maskeli: ", , 'den ulaşılabilir." ``` Etiket dili Buradaki `` gibi Türkçe etiketler panel gösterimine özgüdür. API’yi doğrudan çağırırsanız çıktı İngilizcedir (``, ``); ayrımın ayrıntısı için [Kavramlar](/docs/concepts/). ## Sohbet Önizlemeyle kalmayıp akışı uçtan uca da deneyebilirsiniz: 1. Metni yazın; maskeli önizleme belirir. 2. Gönderin; Gateway maskeli metni modele iletir. 3. Yanıt akar; yer tutucular yanıtta olduğu gibi korunur. Böylece dil modeline giden metnin maskeli hali her adımda gözünüzün önündedir. ![Playground sohbet ekranı: maskeli metin modele gider, yanıt akışta görünür](/docs/screenshots/panel/playground-sohbet-light@2x.png) Gördüğünüz akışı uygulamanıza taşımak için [Gateway entegrasyonu](/docs/guides/gateway-integration/) rehberiyle devam edin; maskelenen kategorilerin tam listesi [Kategoriler](/docs/categories/) sayfasında. --- # MCP sunucusu Source: https://siper.gurubase.ai/docs/guides/mcp/ Siper'in demo MCP sunucusunu Claude Code gibi araçlara ekleyin; metniniz modele gitmeden maskelensin. Siper’in maskelemesini Claude Code gibi yapay zekâ araçlarının içinden kullanabilirsiniz. Model Context Protocol (MCP), bu tür araçların dış servisleri birer tool olarak çağırmasını tanımlayan açık bir standarttır; Siper bu standartla konuşan bir demo sunucu yayınlar: ```text https://siper.gurubase.ai/api/mcp ``` Sunucu tek tool sunar: Türkçe metindeki kişisel verileri maskeleyen `mask_turkish_pii`. Metni bir dil modeline göndermeden önce bu tool’dan geçirirsiniz; modele maskeli hali gider. Anahtar gerekmez. Taşıma katmanı Streamable HTTP’dir; oturum da SSE de yok, her istek kendi başına yeterlidir. Tool, 26 kategorinin tamamını maskeler; tam listeyi [Kategoriler](/docs/categories/) sayfasında bulursunuz. Çıktıda değerlerin yerini `` gibi numaralı yer tutucular alır; biçimin ayrıntısı [Kavramlar](/docs/concepts/) sayfasında. ## Claude Code’a ekleme Tek komut yeter: ```bash claude mcp add --transport http siper-mask https://siper.gurubase.ai/api/mcp ``` Kurulumdan sonra Claude Code, gerektiğinde `mask_turkish_pii` tool’unu kendiliğinden çağırabilir; “şu metni maskele” diyerek elle de tetikleyebilirsiniz. ## Diğer istemciler Cursor, VS Code ve benzeri istemciler için kurulum bağlantıları ile yapılandırma örnekleri, endpoint adresini tarayıcıda açınca çıkan bilgi sayfasındadır: [siper.gurubase.ai/api/mcp](https://siper.gurubase.ai/api/mcp). İstemcilerin sunucuyu kendiliğinden tanıması için bir keşif kartı da yayında: [server-card.json](https://siper.gurubase.ai/.well-known/mcp/server-card.json). ## Sınırlar Bu sunucu ürünün kendisi değil, tanıtım amaçlı bir demo servistir; kendini istemcilere `siper-mask-demo` adıyla tanıtır. - Girdi (`text`) en çok 2.000 karakterdir. - İstek sayısı sınırlıdır (rate limit). - Anahtarsız çalışır; bu yüzden üretim yüzeyi değildir. Üretim entegrasyonunda MCP demosu değil, ürün uçları kullanılır: sohbet akışında otomatik maskeleme için Gateway’in `/v1` ucu ([Gateway entegrasyonu](/docs/guides/gateway-integration/)), maskelemeyi tek başına bir adım olarak kullanmak için `/mask` API’si ([Yalnız maskeleme](/docs/guides/mask-only/)). Demoyu deneyip çıktıyı beğendiyseniz sıradaki durak [Başlangıç](/docs/getting-started/): sanal anahtarınızı alır, ilk maskeli isteğinizi kendi kodunuzdan gönderirsiniz. --- # Gurubase Gateway API Source: https://siper.gurubase.ai/docs/api/gateway/ Gurubase Gateway, **OpenAI Chat Completions** ile birebir uyumlu bir AI gateway’idir. Mevcut OpenAI SDK’nızda yalnızca `base_url` ve API anahtarını (sanal anahtar) değiştirerek geçiş yaparsınız; kod değişikliği gerekmez. Varsayılan olarak açık olan maskelemede, istek arka uçtaki dil modeline (örn. Azure OpenAI) iletilmeden **önce** metinde tespit edilen kişisel alanlar Gurubase Siper ile Türkiye’de yer tutuculara dönüştürülür. Maskeleme sanal anahtar bazında kapatılabilir; kapalı anahtar isteği değiştirmeden modele iletir (passthrough). Yanıt geri akar. > **Kimlik doğrulama:** Tüm istekler `Authorization: Bearer ` > başlığı ile gönderilir. Sanal anahtar admin panelden üretilir; gerçek > sağlayıcı (Azure) anahtarı yalnızca gateway içinde tutulur, istemciye inmez. Version 1.0 Base URL `https://gw-tr.gurubase.io` ## Chat OpenAI uyumlu Chat Completions uç noktaları - [POST Chat Completions (OpenAI uyumlu) `/v1/chat/completions`](/docs/api/gateway/chat/createchatcompletion/) ## Responses OpenAI-uyumlu Responses API uç noktası - [POST Responses API (OpenAI uyumlu) `/v1/responses`](/docs/api/gateway/responses/createresponse/) ## Models Erişilebilir modellerin listesi - [GET Erişilebilir modelleri listele `/v1/models`](/docs/api/gateway/models/listmodels/) --- # Responses API (OpenAI uyumlu) Source: https://siper.gurubase.ai/docs/api/gateway/responses/createresponse/ OpenAI `POST /v1/responses` ile uyumlu. `input` alanı string ya da mesaj dizisi olabilir; maskeleme açıkken her iki biçimde de tespit edilen PII alanları model çağrısından önce yer tutuculara dönüştürülür. Maskeleme adımı çalıştırılamazsa istek **fail-closed** olarak modele gitmeden durur. POST `/v1/responses` ## Request body required `application/json` `model` string required Hedef model kimliği (panelde tanımlı). `input` string | ChatMessage[] required String ya da mesaj dizisi. Maskeleme açıkken her iki biçimde de tespit edilen kişisel alanlar model çağrısından önce gateway içinde yer tutuculara dönüştürülür. One of: string `string` ChatMessage[] Array of `ChatMessage` `role` string required Allowed: `system` `user` `assistant` `tool` `content` string required Mesaj metni. Maskeleme açıkken tüm rollerin (`system`, `user`, `assistant`, `tool`) içeriğinde tespit edilen kişisel alanlar gateway içinde yer tutuculara dönüştürülür. `stream` boolean default: false `temperature` number min 0 · max 2 `max_output_tokens` integer Üretilecek azami token sayısı. min 1 ## Responses 200 Başarılı yanıt `id` string `object` string `created_at` integer `model` string `status` string `output` ResponsesOutputItem[] Array of `ResponsesOutputItem` `id` string `type` string `status` string `role` string `content` ResponsesContentPart[] Array of `ResponsesContentPart` `type` string `text` string `annotations` object[] `usage` Usage `prompt_tokens` integer `completion_tokens` integer `total_tokens` integer 401 Eksik veya geçersiz sanal anahtar `error` object `message` string `type` string 413 Girdi maskeleme sınırını aşıyor. İstek modele iletilmez; metni bölüp yeniden gönderin. `error` object `message` string `type` string 429 Kota/oran limiti aşıldı `error` object `message` string `type` string 502 Maskeleme adımı çalıştırılamadı. İstek **fail-closed** olarak modele iletilmez; "maskesiz de olsa gönder" seçeneği yoktur. `error` object `message` string `type` string ### Request #### openai-python ``` from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) resp = client.responses.create( model="gpt-4o-mini", input="Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor.", ) print(resp.output_text) ``` #### python ``` import requests response = requests.post( "https://gw-tr.gurubase.io/v1/responses", headers={ "Content-Type": "application/json" }, json={ "model": "gpt-4o-mini", "input": "Ahmet Yılmaz, TCKN 10000000382, talebini iletti.", "stream": False, "temperature": 0, "max_output_tokens": 0 }, ) ``` #### curl ``` curl -X POST "https://gw-tr.gurubase.io/v1/responses" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "input": "Ahmet Yılmaz, TCKN 10000000382, talebini iletti.", "stream": false, "temperature": 0, "max_output_tokens": 0 }' ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/v1/responses", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "model": "gpt-4o-mini", "input": "Ahmet Yılmaz, TCKN 10000000382, talebini iletti.", "stream": false, "temperature": 0, "max_output_tokens": 0 }) }); ``` ### Response #### 200 ``` { "id": "resp_01ec5099f62feeda", "object": "response", "created_at": 1782136928, "model": "gpt-4o-mini", "status": "completed", "output": [ { "id": "msg_01ec5099f62feeda", "type": "message", "status": "completed", "role": "assistant", "content": [ { "type": "output_text", "text": "Kayıt alındı.", "annotations": [ {} ] } ] } ], "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 } } ``` #### 401 ``` { "error": { "message": "string", "type": "string" } } ``` #### 413 ``` { "error": { "message": "string", "type": "string" } } ``` #### 429 ``` { "error": { "message": "string", "type": "string" } } ``` #### 502 ``` { "error": { "message": "string", "type": "string" } } ``` --- # Chat Completions (OpenAI uyumlu) Source: https://siper.gurubase.ai/docs/api/gateway/chat/createchatcompletion/ OpenAI `POST /v1/chat/completions` ile uyumlu. Maskeleme açıkken istek gövdesindeki `messages` içeriğinde tespit edilen PII alanları model çağrısından önce yer tutuculara dönüştürülür. `stream: true` ile SSE streaming desteklenir. POST `/v1/chat/completions` ## Request body required `application/json` `model` string required Hedef model kimliği (panelde tanımlı). `messages` ChatMessage[] required min items 1 Array of `ChatMessage` `role` string required Allowed: `system` `user` `assistant` `tool` `content` string required Mesaj metni. Maskeleme açıkken tüm rollerin (`system`, `user`, `assistant`, `tool`) içeriğinde tespit edilen kişisel alanlar gateway içinde yer tutuculara dönüştürülür. `stream` boolean true ise yanıt SSE stream olarak döner. default: false `temperature` number min 0 · max 2 · default: 1 `max_tokens` integer Üretilecek azami token sayısı. min 1 `top_p` number min 0 · max 1 ## Responses 200 Başarılı yanıt `id` string `object` string `created` integer `model` string `choices` ChatChoice[] Array of `ChatChoice` `index` integer `finish_reason` string `message` ChatMessage `role` string required Allowed: `system` `user` `assistant` `tool` `content` string required Mesaj metni. Maskeleme açıkken tüm rollerin (`system`, `user`, `assistant`, `tool`) içeriğinde tespit edilen kişisel alanlar gateway içinde yer tutuculara dönüştürülür. `usage` Usage `prompt_tokens` integer `completion_tokens` integer `total_tokens` integer 401 Eksik veya geçersiz sanal anahtar `error` object `message` string `type` string 413 Girdi maskeleme sınırını aşıyor. İstek modele iletilmez; metni bölüp yeniden gönderin. `error` object `message` string `type` string 429 Kota/oran limiti aşıldı `error` object `message` string `type` string 502 Maskeleme adımı çalıştırılamadı. İstek **fail-closed** olarak modele iletilmez; "maskesiz de olsa gönder" seçeneği yoktur. `error` object `message` string `type` string ### Request #### openai-python ``` from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) resp = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "user", "content": "Ayşe Demir'in talebini özetle."}, ], ) print(resp.choices[0].message.content) ``` #### python ``` import requests response = requests.post( "https://gw-tr.gurubase.io/v1/chat/completions", headers={ "Content-Type": "application/json" }, json={ "model": "gpt-4o-mini", "messages": [ { "role": "system", "content": "string" } ], "stream": False, "temperature": 1, "max_tokens": 0, "top_p": 0 }, ) ``` #### curl ``` curl -X POST "https://gw-tr.gurubase.io/v1/chat/completions" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [ { "role": "system", "content": "string" } ], "stream": false, "temperature": 1, "max_tokens": 0, "top_p": 0 }' ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "model": "gpt-4o-mini", "messages": [ { "role": "system", "content": "string" } ], "stream": false, "temperature": 1, "max_tokens": 0, "top_p": 0 }) }); ``` ### Response #### 200 ``` { "id": "chatcmpl-abc123", "object": "chat.completion", "created": 1718000000, "model": "gpt-4o-mini", "choices": [ { "index": 0, "finish_reason": "stop", "message": { "role": "system", "content": "string" } } ], "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 } } ``` #### 401 ``` { "error": { "message": "Sanal anahtar gerekli veya geçersiz.", "type": "invalid_request_error" } } ``` #### 413 ``` { "error": { "message": "string", "type": "string" } } ``` #### 429 ``` { "error": { "message": "string", "type": "string" } } ``` #### 502 ``` { "error": { "message": "string", "type": "string" } } ``` --- # Erişilebilir modelleri listele Source: https://siper.gurubase.ai/docs/api/gateway/models/listmodels/ Sanal anahtarın erişebildiği modellerin OpenAI-uyumlu listesi. GET `/v1/models` ## Responses 200 Model listesi `object` string `data` Model[] Array of `Model` `id` string Model kimliği; sağlayıcı öneki ile gelir (ör. `openai/gpt-4o-mini`). `object` string `owned_by` string Sahip alanı; gateway listesinde genellikle boş döner. ### Request #### openai-python ``` from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) for model in client.models.list(): print(model.id) ``` #### python ``` import requests response = requests.get( "https://gw-tr.gurubase.io/v1/models", ) ``` #### curl ``` curl -X GET "https://gw-tr.gurubase.io/v1/models" ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/v1/models", { method: "GET" }); ``` ### Response #### 200 ``` { "object": "list", "data": [ { "id": "openai/gpt-4o-mini", "object": "model", "owned_by": "" } ] } ``` --- # Gurubase Siper API Source: https://siper.gurubase.ai/docs/api/siper/ Gurubase Siper API, Türkçe metindeki kişisel verileri tespit eder, seçtiğiniz dönüşüme göre maskeler ve yakalanan kategorileri aynı yanıtta döner. Gateway entegrasyonunda Siper, dil modeline gitmeden önce metni maskeler; bağımsız olarak da `/mask` ve `/mask/batch` uçlarıyla doğrudan kullanılabilir. > **Kimlik doğrulama:** Panelden ürettiğiniz sanal anahtar > `Authorization: Bearer ` başlığında gönderilir. > Kurum içi (on-premise) kurulumda da mimari aynıdır: Gateway ve panel > kurulumla birlikte gelir, istekler yine sanal anahtarla yetkilendirilir. Version 1.0 Base URL `https://gw-tr.gurubase.io` ## Maskeleme Tekil ve toplu maskeleme uç noktaları - [POST Metni maskele `/mask`](/docs/api/siper/maskeleme/mask/) - [POST Toplu maskele `/mask/batch`](/docs/api/siper/maskeleme/maskbatch/) --- # Metni maskele Source: https://siper.gurubase.ai/docs/api/siper/maskeleme/mask/ Verilen metindeki kişisel verileri tespit eder ve seçilen dönüşüme göre maskeler. Varsayılan dönüşüm `placeholder` (geri-çözülebilir yer-tutucu). POST `/mask` ## Request body required `application/json` `text` string required Maskelenecek ham metin. `transform` string `placeholder` (geri-çözülebilir ``), `mask` (uzunluk-koruyan `####`, geri-alınamaz). default: "placeholder" Allowed: `placeholder` `mask` `mask_char` string transform=mask için dolgu karakteri. default: "#" `return_vault` boolean Yer-tutucu → orijinal değer eşlemesini döndürür (hassas! varsayılan kapalı, asla loglanmaz). default: false `categories` object Kategori filtreleme: `{preset, enable:[...], disable:[...]}`. preset değerleri: ALL, IDENTITY, IDENTIFIERS, KVKK, KVKK_SENSITIVE. (KVKK = tüm kapsam; KVKK_SENSITIVE = yalnız m.6 özel-kategori.) `allow_patterns` string[] Düzenli ifade (regular expression, Python `re` sözdizimi) listesi; maskelemeden muaf tutma (allowlist). Tespit edilen bir alanın yüzey metni desenlerden biriyle eşleşiyorsa o alan MASKELENMEZ. Kurum adı gibi kamuya açık bir değer yanlışlıkla kişisel veri sanılıyorsa kullanın. Geçersiz desen 422 döndürür. **Sınırlar:** en çok 25 desen, desen başına en çok 200 karakter. Tarama için bir zaman bütçesi vardır. Muafiyet desenleri bütçeyi aşarsa o desen UYGULANMAZ ve istek normal şekilde tamamlanır: maskelemeyi azaltan bir kural belirsizlikte devreye girmemelidir. `block_patterns` string | object[] Düzenli ifade listesi; eşleşen her metin parçası, model tespit etmemiş olsa bile ZORLA maskelenir. Kurum içi sicil/dosya numarası gibi size özgü tanımlayıcıları garantiye almak için kullanın. Düz dize verilirse kategori `custom` olur; `{pattern, category}` nesnesiyle kategori atanır. Mevcut bir tespitle çakışan eşleşme atlanır (tespit kazanır). Geçersiz desen 422 döndürür. **Sınırlar:** en çok 25 desen, desen başına en çok 200 karakter. Tarama için bir zaman bütçesi vardır; bütçe aşılırsa istek 422 döndürür. Sessizce eksik maskelemek yerine isteği reddetmek tercih edilir. **Kurum desenleri:** panelden kurumunuz için tanımlanan desenler bu istekteki desenlere EKLENİR ve istek gövdesiyle düşürülemez. Sonuç yalnız maskelemeyi artırır. Array of `string | object` One of: string `string` object `pattern` string required Düzenli ifade (Python `re` sözdizimi). `category` string Zorlanan alana atanacak kategori (varsayılan `custom`). ## Responses 200 Maskeleme sonucu `masked_text` string Maskelenmiş metin. `transform` string `spans` Span[] Array of `Span` `category` string `start` integer `end` integer `score` number `timings_ms` object Toplam işlem süresi (ms): yalnız { total }. `vault` object return_vault=true ise yer-tutucu → orijinal eşlemesi (hassas). 401 Eksik veya geçersiz sanal anahtar `detail` string 413 Metin azami uzunluğu aştı (parçalayın veya /mask/batch kullanın) 422 Geçersiz istek gövdesi `detail` ValidationError[] Array of `ValidationError` `loc` string | integer[] Array of `string | integer` Any of: string `string` integer `integer` `msg` string `type` string ### Request #### python ``` import requests response = requests.post( "https://gw-tr.gurubase.io/mask", headers={ "Content-Type": "application/json" }, json={ "text": "Ahmet Yılmaz, TC 10000000214.", "transform": "placeholder", "mask_char": "#", "return_vault": False, "categories": {}, "allow_patterns": [ "\\bDemo Kurum\\b" ], "block_patterns": [ "\\bPRJ-\\d{4}\\b", { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" } ] }, ) ``` #### curl ``` curl -X POST "https://gw-tr.gurubase.io/mask" \ -H "Content-Type: application/json" \ -d '{ "text": "Ahmet Yılmaz, TC 10000000214.", "transform": "placeholder", "mask_char": "#", "return_vault": false, "categories": {}, "allow_patterns": [ "\\bDemo Kurum\\b" ], "block_patterns": [ "\\bPRJ-\\d{4}\\b", { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" } ] }' ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/mask", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "text": "Ahmet Yılmaz, TC 10000000214.", "transform": "placeholder", "mask_char": "#", "return_vault": false, "categories": {}, "allow_patterns": [ "\\bDemo Kurum\\b" ], "block_patterns": [ "\\bPRJ-\\d{4}\\b", { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" } ] }) }); ``` ### Response #### 200 ``` { "masked_text": "string", "transform": "string", "spans": [ { "category": "person", "start": 0, "end": 0, "score": 0.85 } ], "timings_ms": {}, "vault": {} } ``` #### 401 ``` { "detail": "string" } ``` #### 413 Metin azami uzunluğu aştı (parçalayın veya /mask/batch kullanın) #### 422 ``` { "detail": [ { "loc": [ "string" ], "msg": "string", "type": "string" } ] } ``` --- # Toplu maskele Source: https://siper.gurubase.ai/docs/api/siper/maskeleme/maskbatch/ Birden çok metni tek istekte maskeler. Yanıt, girdi sırasıyla eşlenir. Uzunluk sınırı, birleştirilmiş toplam metin üzerinden uygulanır. POST `/mask/batch` ## Request body required `application/json` `texts` string[] required Maskelenecek metin listesi. `transform` string default: "placeholder" Allowed: `placeholder` `mask` `surrogate` `return_vault` boolean default: false ## Responses 200 Her girdi için maskeleme sonucu `results` MaskResponse[] Array of `MaskResponse` `masked_text` string Maskelenmiş metin. `transform` string `spans` Span[] Array of `Span` `category` string `start` integer `end` integer `score` number `timings_ms` object Toplam işlem süresi (ms): yalnız { total }. `vault` object return_vault=true ise yer-tutucu → orijinal eşlemesi (hassas). 401 Eksik veya geçersiz sanal anahtar 413 Çok fazla metin veya birleştirilmiş toplam metin uzunluk sınırını aştı 422 Geçersiz istek gövdesi `detail` ValidationError[] Array of `ValidationError` `loc` string | integer[] Array of `string | integer` Any of: string `string` integer `integer` `msg` string `type` string ### Request #### python ``` import requests response = requests.post( "https://gw-tr.gurubase.io/mask/batch", headers={ "Content-Type": "application/json" }, json={ "texts": [ "Ahmet Yılmaz aradı.", "IBAN: TR12 0001 0000 0000 0000 0000 01" ] }, ) ``` #### curl ``` curl -X POST "https://gw-tr.gurubase.io/mask/batch" \ -H "Content-Type: application/json" \ -d '{ "texts": [ "Ahmet Yılmaz aradı.", "IBAN: TR12 0001 0000 0000 0000 0000 01" ] }' ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/mask/batch", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "texts": [ "Ahmet Yılmaz aradı.", "IBAN: TR12 0001 0000 0000 0000 0000 01" ] }) }); ``` ### Response #### 200 ``` { "results": [ { "masked_text": "string", "transform": "string", "spans": [ { "category": "person", "start": 0, "end": 0, "score": 0.85 } ], "timings_ms": {}, "vault": {} } ] } ``` #### 401 Eksik veya geçersiz sanal anahtar #### 413 Çok fazla metin veya birleştirilmiş toplam metin uzunluk sınırını aştı #### 422 ``` { "detail": [ { "loc": [ "string" ], "msg": "string", "type": "string" } ] } ``` --- # Introduction Source: https://siper.gurubase.ai/docs/en/ OpenAI-compatible AI gateway with Turkish personal data masking. Send your first request in minutes. Gurubase Siper consists of three parts: an OpenAI-compatible AI gateway, personal data masking for Turkish text, and a management panel. Requests are masked in Turkey before they go to the external language model. It is designed for teams that work with text containing personal data and do not want to send that data as-is to models abroad. Diagram: your application's requests reach Gurubase Gateway, which is hosted in Türkiye. Siper PII Masking masks personal data and the raw data stays there; only masked text reaches the external language model. In practice, masking looks like this: The example "Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor." becomes ", TCKN , başvuru durumunu soruyor." after masking. ## Start here - [AI Gateway](/docs/en/ai-gateway/): What a single point of passage gives you: masking, visibility, resilience, budget. - [Getting started](/docs/en/getting-started/): Get your virtual key and send your first request with the OpenAI SDK. - [Concepts](/docs/en/concepts/): How masking works, the placeholder format, fail-closed behavior, and data sovereignty. - [Categories](/docs/en/categories/): The 26 masked personal data categories, with synthetic examples. - [Guides](/docs/en/guides/gateway-integration/): Switching with the OpenAI SDK, streaming, and mask-only usage. - [API reference](/docs/en/api/gateway/): Full reference for the Gateway and masking endpoints. - [Security](/docs/en/security/): Data retention approach, audit trail, and access controls. To create an account, [contact us](https://siper.gurubase.ai/iletisim); if your account is ready, you can sign in to the [panel](https://gateway-tr.gurubase.io) and generate your virtual key. Siper is part of the [Gurubase](https://gurubase.io) product family. Gurubase lets you build AI agents that draw on your organization’s own knowledge sources, cite a source in every answer, and decline to answer when the context is weak; Siper is the family’s Turkish personal data protection layer. ## For AI agents These docs are also available in machine-readable form for AI agents and LLMs: - [llms.txt](/docs/llms.txt): a page index with summaries - [llms-full.txt](/docs/llms-full.txt): the full text of every page in one file - Each page’s raw Markdown: append `.md` to its URL (for example [getting-started.md](/docs/en/getting-started.md)) These files are generated automatically on every build and stay in sync with the content. --- # AI Gateway Source: https://siper.gurubase.ai/docs/en/ai-gateway/ One layer for all your applications' language model traffic: masking, audit trail, quota, and usage collected in one place. Your code stays the same. An AI gateway is the layer that sits between your applications and language models. Instead of going straight to the provider, requests pass through it first; the organization sees every request in one place and applies its rules in one place. Gurubase Gateway runs this layer in Turkey and adds one more step at the moment of passage: personal data is masked before the request leaves for the external model. Diagram: requests from every application, including the customer assistant, the support flow and internal tools, arrive at Gurubase Gateway as a single entry point. The gateway runs in Türkiye and passes each request through Siper masking; raw data stays there. The masked text then fans out to providers: hosted providers such as OpenAI, Anthropic and Gemini, or vLLM and Ollama on your own server. Audit trail, quota and usage are collected at the same point. ## Why a single point of passage When usage is scattered, each team goes to its own provider, with its own key, from its own code. No one can see who sent what across the organization; this is the picture known in enterprise literature as shadow AI. A single point of passage changes that in four places. **Personal data control.** Masking is applied in one place. Instead of expecting every application to get it right on its own, the rule sits at the point of passage and works the same way no matter which team the request comes from. **Visibility.** Which team uses which model and how much, which categories are detected and how often, which requests returned an error. It is collected on a single screen, broken down by virtual key and model. **Resilience.** When a provider slows down or returns an error, the decision to retry or switch to an alternative is made at the gateway, not in application code. **Budget.** Token budget, quota, and warning thresholds are tracked per key; usage is read from one place across the organization. ## What changes in your code Two values. The rest stays the standard OpenAI SDK: the model name, the parameters, and the response format are the same. ```diff client = OpenAI( - base_url="https://api.openai.com/v1", - api_key=OPENAI_API_KEY, + base_url="https://gw-tr.gurubase.io/v1", + api_key=VIRTUAL_KEY, ) ``` The provider’s real key stays inside the Gateway; your application carries only the virtual key you generated in the panel. For a step-by-step switch, see [Gateway integration](/docs/en/guides/gateway-integration/). ## Guardrails Masking is the first guardrail running at the point of passage, and the default one. Input is masked on every request; response masking is turned on optionally. Prompt injection protection and hallucination protection will be added to the same layer; they are coming soon. For details and current status, see [Guardrails](/docs/en/guardrails/). ## Models and providers The Gateway offers a single OpenAI-compatible interface. Behind it there can be general providers such as OpenAI, Anthropic, and Gemini, or models running on your own servers; the only thing that changes on the client side is the `model` field. You get the models you can access from the `/v1/models` endpoint. For provider selection, retry, and fallback behavior, see [Models and providers](/docs/en/models/). ## Visibility and governance The panel makes the data that accumulates at the gateway readable: request and token counts, characters processed, the distribution of detected categories, and the breakdown by model and virtual key. Administrative events are written to an append-only audit trail and can be exported. For the screens, see [Panel](/docs/en/panel/); for retention and access rules, see [Security](/docs/en/security/). ## Runs in Turkey The Gateway and masking run on infrastructure hosted in Turkey. Only masked text goes to the external model; raw personal data is processed in Turkey and stays there. If masking cannot be completed, the request does not go to the external model at all, and the Gateway returns a 502. This behavior is called fail-closed; the details are on the [Concepts](/docs/en/concepts/) page. - [Getting started](/docs/en/getting-started/): Get your virtual key and send your first masked request. - [Guardrails](/docs/en/guardrails/): Input and response masking, and the layers coming soon. - [Models and providers](/docs/en/models/): Model selection, retry, and fallback. - [Panel](/docs/en/panel/): Usage charts, quota, user and key management. --- # Getting started Source: https://siper.gurubase.ai/docs/en/getting-started/ Start without any setup: get your virtual key, change the base_url in the OpenAI SDK, and send your first masked request within minutes. Two addresses and one virtual key are all you need for your first request. There is nothing to install; if you use the OpenAI SDK, you only change the `base_url` value and the key, and the rest of your code stays the same. ## Your access details | Use | Address | | --- | --- | | API base (OpenAI SDK `base_url`) | `https://gw-tr.gurubase.io/v1` | | Management panel | `https://gateway-tr.gurubase.io` | ## Generate your virtual key Sign in to the [panel](https://gateway-tr.gurubase.io) and generate a virtual key; you send your requests with this key. The language model provider’s real key stays inside the Gateway, so you never keep it in your application. See [Panel](/docs/en/panel/) for the steps. ## First request All three examples below send the same request to the Responses API. The text contains a name and a Turkish national ID number (TCKN); both are masked before they reach the model. ```bash curl https://gw-tr.gurubase.io/v1/responses \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "input": "Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor." }' ``` ```python from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) resp = client.responses.create( model="gpt-4o-mini", input="Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor.", ) print(resp.output_text) ``` ```ts import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://gw-tr.gurubase.io/v1", apiKey: process.env.SANAL_ANAHTAR, }); const resp = await client.responses.create({ model: "gpt-4o-mini", input: "Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor.", }); console.log(resp.output_text); ``` ## What happened? The name and the TCKN in your input were replaced with placeholders in the copy sent to the model: ```text Input : "Ayşe Demir, TCKN 10000000214, başvuru durumunu soruyor." To model: ", TCKN , başvuru durumunu soruyor." ``` The model works with the masked text, and the same placeholders are preserved in the response. Placeholders in the API output are in English; the [Concepts](/docs/en/concepts/) page covers the placeholder format and how it differs from what the panel displays. ## Next steps - [Concepts](/docs/en/concepts/): Placeholder format, fail-closed behavior, and data sovereignty. - [Gateway integration](/docs/en/guides/gateway-integration/): Streaming, Chat Completions, and mask-only usage. - [Categories](/docs/en/categories/): The full list of 26 personal data categories that get masked. - [Panel](/docs/en/panel/): Virtual key generation and usage tracking. --- # Concepts Source: https://siper.gurubase.ai/docs/en/concepts/ Siper concepts: what happens in the masking step, how to read the placeholder format, what fail-closed behavior does, and where your data is processed. Every request sent through a virtual key with masking enabled passes through a masking step first. This page explains what happens in that step: the format of the placeholders, how the Gateway behaves when masking cannot be performed, and where your data is processed. ## How does masking work? Text arriving at the Gateway is scanned before it is forwarded to the model. Each detected piece of personal data is replaced with a placeholder in the form ``: the first person name in the text becomes ``, the second ``. For detected values, the model sees these placeholders instead of the original values; the placeholders are preserved as the response comes back. Detection covers 26 categories, including names, TCKN (Turkish national ID number), phone numbers, and addresses. For the full list and synthetic examples, see [Categories](/docs/en/categories/). Behind this accuracy is data: we built a large Turkish training dataset that covers KVKK’s special categories (including health, religion, political opinion, trade-union membership, and criminal convictions) and trained the model on it over months of work. We re-measure new releases under the same test protocol and share comparative results on the [benchmark page](https://siper.gurubase.ai/benchmark). Recall measured 84.6% in the July 2026 evaluation; no automated detector can guarantee that it will find every piece of personal data. ## Placeholder format and the language distinction Direct `/mask` and `/mask/batch` responses use raw category names such as ``, ``, and ``. The OpenAI-compatible Gateway and the management panel display the same categories with Turkish labels. Each new value in the same category increments the number by one. | Direct `/mask` | Gateway and panel | | --- | --- | | `` | `` | | `` | `` | | `` | `` | In integration code, follow the contract of the surface you call: direct masking endpoints return raw category names, while the Gateway returns Turkish labels. ## What happens if masking fails? The request stops. If the masking service cannot process a request, the Gateway does not forward that request to the external model and responds with a 502 status code; there is no “send it unmasked anyway” option. When you receive a 502, retry the request later. This behavior is called fail-closed. ## Data sovereignty Masking runs before the model call, on infrastructure hosted in Turkey. With masking enabled, detected personal data is converted to placeholders in Turkey and those masked values are sent to the external language model. Diagram: your application's requests reach Gurubase Gateway, which is hosted in Türkiye. Siper PII Masking masks personal data and the raw data stays there; only masked text reaches the external language model. For retention, audit trail, and access topics, see [Security](/docs/en/security/). --- # Masked categories Source: https://siper.gurubase.ai/docs/en/categories/ The full list of 26 personal data categories Siper masks, with short descriptions and synthetic examples; KVKK Article 6 special categories are marked. Siper detects and masks 26 personal data categories in Turkish text. This page is the full list: next to each category you will find a short description and a synthetic example. Nine categories fall under the special categories of personal data defined in Article 6 of KVKK (Turkey’s personal data protection law); you will find them in a separate section. All examples are synthetic and do not belong to any real person. In masked output, each category has its own placeholder; the API returns them with English names. For format details, see [Concepts](/docs/en/concepts/). ## General categories | Category | Description | Synthetic example | | --- | --- | --- | | Person | First and last name. | `Ahmet Yılmaz` | | Address | Street, neighborhood, and full address details. | `Zambak Sk. No:4` | | Birth date | Date of birth with day, month, and year. | `12.03.1981` | | TCKN | TCKN (Turkish national ID number). | `10000000214` | | YKN | Foreign national ID number; starts with 99. | `99…` | | VKN | Tax ID number. | tax ID | | MERSİS | Companies’ Central Registry System (MERSİS) number. | MERSİS no | | SGK | Social Security Institution (SGK) registry number. | SGK registry no | | Passport | Passport number. | `U1234…` | | Serial no | ID card serial number. | ID serial | | Phone (mobile) | Mobile phone number. | `0532 000 11 22` | | Phone (landline) | Landline number. | `0212…` | | Email | Email address. | `ayse.demir@ornek.gov.tr` | | IBAN | Bank account number. | `TR33…` | | Card | Payment card number. | `4111…` | | License plate | Vehicle license plate. | `35 ABC 042` | | IP address | IP address. | `10.1.2.3` | ## Special categories (KVKK Article 6) The nine categories below fall under Article 6 of Law No. 6698. A category name on its own is not personal data; mentioning the concept of “union membership” and writing down a specific person’s union membership are different things. That is why every example in the table is a sentence, and the backticked part is the expression Siper masks in that sentence. All examples are synthetic and have been verified against the live service; no real belief, origin, party, or organization name appears. | Category | Description | Example sentence and masked part | | --- | --- | --- | | Health | Diagnosis, treatment, and health status tied to a person. | Ayşe Demir’e `diyabet tanısı` kondu. | | Religion | Statements about a person’s religious belief. | Çalışan, `dini inancı` gerekçesiyle izin talep etti. | | Ethnic origin | Statements about a person’s ethnic origin. | Tanık, `etnik kökenine` yönelik ayrımcılığa uğradığını belirtti. | | Political opinion | A person’s political opinion and party membership. | Başvuran, `Y Partisi üyeliğini` doğruladı. | | Union membership | A person’s union membership. | Ahmet Yılmaz, `Örnek-İş Sendikası` üyesidir. | | Criminal conviction | A person’s conviction and security measure information. | Müşteri, `adli sicil kaydı` bulunmadığını beyan etti. | | Sex life | Statements about a person’s sex life. | Danışan, `cinsel yönelimini` görüşmede paylaştı. | | Biometric | Biometric template and record codes; a code is masked only when it appears near a biometric context. | Parmak izi şablonu `FP-7788` sistemde kayıtlı. | | Genetic | Gene and variant names tied to a person; a name is masked only within a genetic context. | `BRCA1` mutasyonu taşıdığı genetik testle doğrulandı. | Siper errs on the side of caution in these categories: an expression like “diyabet tanısı” (diabetes diagnosis) may be masked even when the sentence does not tie it to a specific person. This is a deliberate choice; the risk of missing personal data outweighs the cost of masking a general expression unnecessarily. To exclude patterns specific to your organization that you are certain carry no personal data, use the `allow_patterns` field ([Mask-only usage → Pattern lists](/docs/en/guides/mask-only/#pattern-lists)). If you want to narrow the scope, the `/mask` request offers predefined category sets; for example, `KVKK_SENSITIVE` masks only these nine categories. Details: [Mask-only usage → Category filtering](/docs/en/guides/mask-only/#category-filtering). To try the categories on your own text, use the [Playground](/docs/en/guides/playground/). --- # Guardrails Source: https://siper.gurubase.ai/docs/en/guardrails/ Guardrail layers at the gateway: input masking on every request, response masking optional; prompt injection and hallucination protection coming soon. Every request that passes through the Gateway goes through guardrail layers before it leaves for the external model. The layers running today are based on masking; two more will be added at the same checkpoint. | Layer | What it does | Status | | --- | --- | --- | | Input masking | Masks personal data inside the request before the model sees it | On (default) | | Response masking | Masks personal data returned by the model before it reaches the client | Optional | | Prompt injection protection | Flags inputs that aim to push the model outside the instructions it was given | Coming soon | | Hallucination protection | Flags model responses that have no grounding | Coming soon | ## Input masking This is the default layer, and it runs on every request. Text is scanned before it is forwarded to the external model, each detected piece of personal data is replaced with a placeholder such as ``, and only masked text goes to the model. Coverage is 26 categories; the special categories of personal data under Article 6 of KVKK are included. For the full list and synthetic examples see [Categories](/docs/en/categories/), and for the placeholder format see [Concepts](/docs/en/concepts/). If masking cannot be completed, the request does not go to the external model and the Gateway returns a 502. There is no “send it unmasked anyway” option. ## Response masking Input is masked on every request; the response side is enabled when the organization requests it. If the model produces personal data in its response or repeats a value from the input, those values are masked before they return to the client. It is not applied to streaming responses: to avoid breaking the real-time stream, the response passes through as-is, and this is recorded in the audit trail. ## Turning masking off Masking can be turned off per virtual key; requests from that key go directly to the language model, and for that key the Gateway acts as a plain AI gateway. Masked and unmasked keys can run side by side in the same organization. KVKK responsibility Personal data sent through a key with masking turned off is forwarded to the language model unmasked; for that traffic, responsibility under KVKK rests entirely with the organization. Turn masking off only for keys you are sure carry no personal data; if you are not sure, leave it on. ## Layers coming soon Two layers are in development. Both are designed to run at the same checkpoint, in the same flow as masking. **Prompt injection protection.** Flags attempts hidden in user input that aim to push the model outside the instructions it was given. A typical example is an instruction of the “ignore the previous instructions” kind placed inside otherwise ordinary text. **Hallucination protection.** Flags cases where the model gives an answer with no grounding in a confident tone. This is a different risk from a personal data leak: here the problem is not data going out, but wrong information coming in. When they go live, this page will be updated and a dated entry will be added to the [Release notes](/docs/en/release-notes/) page. --- # Models and providers Source: https://siper.gurubase.ai/docs/en/models/ Different providers behind one OpenAI-compatible interface, including OpenAI and Anthropic: model selection, listing accessible models, retries, and failover. The Gateway offers a single OpenAI-compatible interface. Which provider runs behind it is not the client’s concern: your application sends the same request shape, and the only field that changes is `model`. ## Model selection The model name is given in the request. Switching between the models defined for your organization takes one line; the SDK, the parameters, and the response format stay the same. ```python resp = client.responses.create( model="gpt-4o-mini", input="Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor.", ) ``` You get the models you can access from the `/v1/models` endpoint. The list returns the models defined for your organization; the name `gurubase-siper`, reserved for masking only, is also there. For the full reference of the endpoint, see [List accessible models](/docs/en/api/gateway/models/listmodels/). ## Providers Two kinds of providers can run behind the same interface: general providers such as OpenAI, Anthropic, and Gemini, or models you host on your own servers. Which providers are open, and which models each virtual key can reach, are defined for the organization. The provider’s real API key stays inside the Gateway. Your applications and panel users see only the virtual key; the provider key never reaches the client. For key generation, rotation, and revocation steps, see [Panel](/docs/en/panel/). Masking is independent of this choice: whichever provider is selected, the request passes through the same protection layers before it goes to the external model. For the layers, see [Guardrails](/docs/en/guardrails/). ## Retries and switching to an alternative Providers return a rate limit from time to time, or slow down. In that case the retry decision is made in the Gateway, not in your application code: the request is retried with increasing wait intervals. If more than one provider is defined for your organization, routing the request to an alternative provider when one cannot respond is configured in the same place. No extra code is needed on the application side. The limits on your side (requests per minute, token budget, and 429 behavior) are a separate topic; the details are on the [Limits and quotas](/docs/en/limits/) page. --- # Panel Source: https://siper.gurubase.ai/docs/en/panel/ The Gurubase Gateway admin panel: sign-in and MFA, usage charts, token budget and quota alerts, plus user and virtual key management in one place. You manage the Gateway from the panel at [https://gateway-tr.gurubase.io](https://gateway-tr.gurubase.io): virtual keys, usage tracking, quota, and users in one place. The panel UI is in Turkish. When you sign in, the “Genel Bakış” (Overview) screen opens; this is where you see the state of your token budget, the error rate of requests going to the provider, and the masking counters. ![Overview screen: token budget, error rate, and masking counters](/docs/screenshots/panel/genel-bakis-light@2x.png) ## Sign-in and MFA You sign in to the panel with your email and password. On first sign-in, you are asked to set up multi-factor authentication (MFA): you scan the QR code with a TOTP app (such as Google Authenticator or 1Password) and enter the generated 6-digit code. On later sign-ins, the current code is requested alongside your password. MFA cannot be skipped; if a user changes phones and can no longer generate codes, an administrator resets their verification. ![Two-step verification screen](/docs/screenshots/panel/giris-mfa-light@2x.png) ## Usage charts The “Kullanım” (Usage) screen shows request and token counts for the time range you select, split into input and output. The daily processed-characters chart and the distribution of detected categories are on the same screen; with the model and virtual key breakdown, you can track which key consumes what. ![Usage charts: processed characters and category distribution](/docs/screenshots/panel/kullanim-grafikleri-light@2x.png) ## Quota and alerts Your token budget sits on a live card in the panel: used, remaining, and warning thresholds. The card warns you at the 80% and full thresholds; the service is not cut off. For details of the budget model and the 429 behavior, see [Limits and quotas](/docs/en/limits/). ![Token budget card: used and remaining tokens](/docs/screenshots/panel/kota-alarm-light@2x.png) ## User management You manage your organization’s accounts from the “Kullanıcılar” (Users) screen. You invite new users and assign roles; permissions are role-based (RBAC). You can deactivate an account and, when needed, reset its MFA setup. Each user’s virtual keys and quota usage are also tracked from the same screen. ![Users screen: account list with role, status, and MFA columns](/docs/screenshots/panel/kullanicilar-light@2x.png) ## Key management You generate, rotate, and revoke virtual keys from the “Anahtarlar” (Keys) screen. A generated key is shown in full only at the moment of creation; save it somewhere safe right then. Afterwards, only a masked summary remains in the list. The language model provider’s real key is visible neither in the panel nor in the client; it stays inside the Gateway. To wire the key into your application, see [Gateway integration](/docs/en/guides/gateway-integration/). ![Keys screen: masked key list and ready-to-use examples](/docs/screenshots/panel/anahtarlar-light@2x.png) You can choose what gets masked for each key separately. Open **“Güncelle” (Update)** from the three dots on the key’s row: built-in data types and your organization’s own patterns are listed together, and you switch each one on or off with a single click. Everything is on by default; a type you switch off is not masked for that key alone and goes to the model as-is. ![Update key dialog: on and off switches for built-in data types and organization patterns](/docs/screenshots/panel/anahtar-guncelle-light@2x.png) Storing what you switched off, rather than what you left on, is deliberate: when you later add a new pattern under Settings, it applies to your existing keys automatically. You do not have to carry a new rule to each key by hand. If you want to try masking without writing code, the Playground in the panel is enough; the [Playground](/docs/en/guides/playground/) guide walks through the flow. ## Masking patterns The built-in categories cover common personal data such as national ID numbers, phone numbers, and addresses. If your organization also has identifiers of its own (a case number, a client code, an order number), you define them under **“Ayarlar > Maskeleme Desenleri” (Settings > Masking Patterns)**. The label you give determines the placeholder that appears in the masked output: the label `MUVEKKIL_NO` produces ``. ![Masking patterns screen: pattern list, live validity check, and the list of built-in categories](/docs/screenshots/panel/maskeleme-desenleri-light@2x.png) The screen makes three things easier: - **Live checking.** You see whether a pattern is valid as you type. The definitive answer comes from the masking service, not from the browser, so a saved pattern will not surprise you in production. - **A test dialog.** You enter sample text and see the real effect of your patterns: which parts were masked, and what the exemptions left exposed. - **The built-in category list.** The data types we already detect are listed with examples, so you do not redefine something that is already covered. A label that collides with a built-in name is not saved: the same name would mix two different sources under one placeholder and make the reverse mapping ambiguous. Definitions are kept at the organization level, so you define them in one place and they apply to all of your keys. If you want an exception for a single key, switch it off from the **“Güncelle” (Update)** dialog above; the pattern itself stays under Settings. For the limits on pattern count and length, see [Limits and quotas](/docs/en/limits/). Exemption patterns work in the opposite direction: a matching value is not masked. They are useful when a publicly known organization name is mistaken for personal data. Because they reduce masking, they are marked separately in the panel; decide with a clear view of what you are opening up. --- # Limits and quotas Source: https://siper.gurubase.ai/docs/en/limits/ Limits and quotas in Siper: the periodic token budget, requests per minute (RPM), what a 429 response means, and how to retry correctly with Retry-After. In normal use you will not hit a limit; the limits are deliberately generous. Two mechanisms apply to your account: a periodic token budget and a per-key requests-per-minute limit. The goal is not to restrict usage; it is to keep the service predictable for everyone. ## Token budget All your requests are deducted from a single token budget defined for the period. Unused tokens do not expire at the end of the period; the budget rolls over and accumulates. When the budget is used up, the service is not cut off. A warning appears in the panel when you reach 80% of the budget and another when the budget is used up; your requests keep being processed. Remaining tokens, usage rate, and the thresholds are shown live on the “Token Bütçesi” (Token Budget) card in the panel; see [Panel](/docs/en/panel/) for where the card is. ## Requests per minute (RPM) A requests-per-minute (RPM) limit can optionally be defined for each virtual key. The default is unlimited; the limit applies only when explicitly set and protects the service during short bursts of load. The value applied to your key is shown in the key list in the panel; if there is no value, the key is unlimited. ## The 429 response and Retry-After If you reach the RPM limit, the Gateway returns an OpenAI-compatible 429 response: ```http HTTP/1.1 429 Too Many Requests Retry-After: 2 Content-Type: application/json { "error": { "type": "rate_limit_exceeded", "message": "Dakika başına istek limiti aşıldı." } } ``` The `Retry-After` header tells you how many seconds to wait before trying again. Most OpenAI SDKs retry a 429 on their own; if you are writing your own client, add retries with increasing intervals. A 429 is not a quota overrun. When your token budget is used up, requests do not stop, and you only see a warning; a 429 is returned only for the momentary rate limit and resolves on its own once the `Retry-After` period passes. ## Masking pattern limits Three limits apply to your organization’s own patterns: at most **25 patterns**, at most **200 characters** per pattern, and a time budget for scanning. The limits are not arbitrary: a single badly shaped pattern can keep masking busy for a long time, and the budget cuts that short. When the budget is exceeded, the two directions behave differently, and the distinction is deliberate: - A **masking pattern** that exceeds the budget causes the request to be rejected with `422`. We prefer returning an error over silently masking less than we should. - An **exemption pattern** that exceeds the budget is simply not applied, and the request completes normally. An exemption reduces masking, and a rule that reduces masking should not take effect under uncertainty. The same limits apply when you send patterns directly in the request body. The organization patterns you define in the panel are added to the ones in the request and cannot be dropped by the request body; the result can only increase masking. To define patterns from the panel, see [Panel](/docs/en/panel/). ## Summary | Limit | Default | Behavior when exceeded | Where it is shown | | --- | --- | --- | --- | | Token budget | Periodic, rolls over | Warning; service is not cut off | Token Budget card in the panel | | RPM | Unlimited; configurable per key | `429` + `Retry-After` | Key list in the panel | | Masking pattern | At most 25 patterns, 200 characters | Masking pattern `422`; exemption not applied | Settings > Masking Patterns | If you would like to increase your budget or define a custom limit for a key, get in touch with us. --- # Security Source: https://siper.gurubase.ai/docs/en/security/ Personal data is masked before it reaches the model. Fail-closed behavior, no data retention, infrastructure hosted in Turkey, and the audit trail. Personal data is masked in Turkey before it goes to the external language model; the rest of the security model exists to keep that sentence true. On this page you will find what happens when something fails, what is not stored, and who can access the panel and how. ## Personal data is masked before it reaches the model Every request passes through the masking step before the language model is called. Only masked text goes to the model; detected values are replaced with placeholders such as ``. See [Concepts](/docs/en/concepts/) for the placeholder format. ## Response masking Input is masked on every request; if the organization requests it, the response side is enabled as well and personal data returned by the model is masked before it reaches the client. The details and the streaming exception are on the [Guardrails](/docs/en/guardrails/) page. ## If masking cannot be performed, the request stops Masking works fail-closed: when masking cannot be completed, the request does not go to the external model, the Gateway returns a 502, and the original text is not forwarded either. When in doubt, the request does not pass. The details of this behavior are on the [Concepts](/docs/en/concepts/) page. ## Masking on/off (passthrough) Masking is on by default, and that is the usage we recommend. If the organization wishes, masking can be turned off for a specific virtual key; the setting is per key and takes effect immediately from the panel. For keys with masking turned off, responsibility under KVKK (Turkey’s personal data protection law) rests entirely with the organization. See [Guardrails](/docs/en/guardrails/) for details. ## No data retention Raw personal data is not stored permanently. The mapping (vault) that makes it possible to go from a placeholder back to the original value is off by default; it is produced only when explicitly requested and is not logged. ## Data sovereignty Masking runs on infrastructure hosted in Turkey and before the model call. The platform and the masking model are hosted on DT Cloud servers in Istanbul. Only masked text goes to the model abroad; raw personal data is processed in Turkey and stays there. For organizations that want to run the infrastructure entirely on their own systems, an on-premise deployment option is also available; for details, [contact us](https://siper.gurubase.ai/iletisim). ## Audit trail Administrative events (sign-ins, MFA setups; key generation, rotation, and revocation; user and quota changes) are written to an append-only audit trail. Records are not modified after the fact; only new records are added to the trail, and the trail can be exported as CSV or Excel. For masking events, metadata such as category and detection count is kept; the trail contains no surface text, and the masked text itself is not recorded. ![Audit trail screen: the event list shows only metadata, no surface text](/docs/screenshots/panel/denetim-light@2x.png) ## Access security Signing in to the panel requires email, password, and a mandatory TOTP code; permissions are role-based. Traffic is encrypted with TLS. The language model provider’s real key stays inside the Gateway only; the panel and clients work with virtual keys. See [Panel](/docs/en/panel/) for the panel steps. ## Masked categories Masking covers 26 categories; alongside general categories such as name, TCKN (Turkish national ID number), and IBAN, the special categories of personal data under Article 6 of KVKK are also in scope. See [Categories](/docs/en/categories/) for the full list and synthetic examples. --- # Deployment Source: https://siper.gurubase.ai/docs/en/deployment/ Siper runs in two ways: the managed service we operate in Istanbul, or an installation on your own servers. The product is identical in both. Siper can run in two ways: the managed service we operate in Istanbul, or an installation on your organization’s own servers. This page explains the difference between the two. It does not contain installation steps; an on-premise installation is planned and carried out together with us. The important part: **the product is identical in both.** The gateway, masking, and panel are installed as a single whole. An on-premise installation is not a reduced version. The diagram compares the two installation models. In the managed service your application runs in your organization, while the gateway and masking sit inside the boundary of our infrastructure in Istanbul, and only masked text goes to the external provider. In an on-premise installation your application, the gateway and masking are inside the same boundary, your organization; only masked text goes to the external provider. If the provider runs on your own servers too, the request never leaves your network. | | Managed service | On-premise installation | | --- | --- | --- | | Where it runs | On our infrastructure in Istanbul | On your organization’s servers | | Who operates it | We do | Your own team | | Where raw data is processed | In Turkey, on our infrastructure | In your environment | | Panel, audit trail, categories | Same | Same | | API contract and masking behavior | Same | Same | ## What is the same in both Masking behavior, the 26 categories, the placeholder format, and the fail-closed rule do not change. The panel, the audit trail, virtual key management, and usage charts are the same. The API contract is the same: your application does not need to know which model it runs against, only the `base_url` differs. This means moving to an on-premise installation, or the other way around to the managed service, does not require changes in your application code. ## External model traffic In both models the Gateway reaches out to the language model provider you select: the request goes to the provider after it has been masked. So an on-premise installation by itself does not mean “nothing leaves”; what leaves is masked text. If you want a fully closed setup, you choose a model running on your own servers as the provider. Solutions such as vLLM and Ollama expose an OpenAI-compatible interface, so the Gateway connects to them the same way. In that case the request never leaves your network. For provider selection, see [Models and providers](/docs/en/models/). ## Which one to choose For most organizations the managed service in Istanbul is the most practical path: installation and operations stay with us, raw data is still processed in Turkey, and only masked text goes to the external model. The on-premise installation exists for organizations that cannot let data leave their own infrastructure at all. Scope, operational responsibility, and version updates are agreed in the contract; to get started, [contact us](https://siper.gurubase.ai/iletisim). For data retention, the audit trail, and access rules, see [Security](/docs/en/security/). --- # Release notes Source: https://siper.gurubase.ai/docs/en/release-notes/ A single-page log of the improvements and fixes shipped in Siper: new capabilities, masking and panel changes, with the newest change at the top. Changes released in Siper are listed on this page from newest to oldest. ## July 8, 2026 **Improvement:** The date of birth category now recognizes more written forms: the month spelled out (“7 Mart 1985”), the ISO format (“1992-10-12”), and two-digit years (“15.03.85”). Detection requires a birth context; dates that do not indicate a birth, such as contract or invoice dates, are not masked. For the full list of categories, see [Categories](/docs/en/categories/). **Improvement:** A user reported that when a block that masks fine in a short text is repeated many times in the same request, some names could slip through. The issue is fixed; detection is now stable in long, repetitive texts. In addition, the same value gets the same numbered placeholder no matter how many times it appears in the text; for example, the same name becomes `` everywhere it appears. Personal data written with different Unicode renderings of regular letters, such as script, bold, or fullwidth forms, is now detected as well. See [Concepts](/docs/en/concepts/) for the placeholder format. ## July 3, 2026 **Improvement:** The default response of the `/mask` and `/mask/batch` endpoints has been simplified. The response now consists of the `masked_text`, `transform`, `spans` (category, character range, and confidence score), and `timings_ms.total` fields; internal fields were removed from the response. You will find the field descriptions in the [Mask-only usage](/docs/en/guides/mask-only/) guide. **Fix:** People trying the product for the first time often paste widely known test ID numbers; because these numbers were on a deliberate exception list, they were not masked, which created the impression that the product “does not work”. The exception has been removed: the well-known test number published by NVİ (Turkey’s civil registry authority) is now masked. The same applies to known test tax identification numbers written with a tax number context. To try it with your own text, see [Playground](/docs/en/guides/playground/). ## June 23, 2026 **Fix:** Resolved following a user report: when an ID number was referred to in the text only with the abbreviation “TC”, in some cases it was not masked. This spelling is now masked too. For the full list of categories, see [Categories](/docs/en/categories/). --- # Gateway integration Source: https://siper.gurubase.ai/docs/en/guides/gateway-integration/ Switching with the OpenAI SDK, Responses API and Chat Completions, streaming, mask-only usage, and virtual keys. When you move your existing OpenAI integration to the Gateway, only two values change: - `base_url` → `https://gw-tr.gurubase.io/v1` - API key → the virtual key you generate in the [panel](https://gateway-tr.gurubase.io) The rest is the standard OpenAI SDK; the model name, parameters, and response format stay the same. Masking runs automatically on every request: the input is masked before it is forwarded to the model. ## Drop-in switch In the examples below, only the `base_url` and key lines are specific to the Gateway; the rest of the code is identical to the version that goes directly to the provider. ### Responses API The default path is the Responses API. The name and the TCKN (Turkish national ID number) in the example are masked before reaching the model. ```python from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) resp = client.responses.create( model="gpt-4o-mini", input="Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor.", ) print(resp.output_text) ``` ```bash curl https://gw-tr.gurubase.io/v1/responses \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "input": "Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor." }' ``` ```ts import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://gw-tr.gurubase.io/v1", apiKey: process.env.SANAL_ANAHTAR, }); const resp = await client.responses.create({ model: "gpt-4o-mini", input: "Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor.", }); console.log(resp.output_text); ``` ### Chat Completions If your code uses `chat.completions`, you do not need to switch to the Responses API; the same two changes are enough here as well. The Python and TypeScript examples from this point on continue with the `client` defined above. ```python resp = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "user", "content": "Ayşe Demir'in talebini özetle."}, ], ) print(resp.choices[0].message.content) ``` ```bash curl https://gw-tr.gurubase.io/v1/chat/completions \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [ { "role": "user", "content": "Ayşe Demir'\''in talebini özetle." } ] }' ``` ```ts const resp = await client.chat.completions.create({ model: "gpt-4o-mini", messages: [{ role: "user", content: "Ayşe Demir'in talebini özetle." }], }); console.log(resp.choices[0].message.content); ``` ## Streaming When you set `stream: true`, the response arrives chunk by chunk over SSE. The masking step does not move: the input is masked before it goes to the model, and the stream is generated from the masked text. ```python stream = client.chat.completions.create( model="gpt-4o-mini", stream=True, messages=[{"role": "user", "content": "Toplantı notlarını madde madde özetle."}], ) for chunk in stream: print(chunk.choices[0].delta.content or "", end="", flush=True) ``` ```ts const stream = await client.chat.completions.create({ model: "gpt-4o-mini", stream: true, messages: [{ role: "user", content: "Toplantı notlarını madde madde özetle." }], }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ""); } ``` ## Mask-only (`gurubase-siper`) You can get masking only, from the same endpoint, without sending the text to a language model. Set the `model` field to the reserved value `gurubase-siper`; the Gateway masks the text and returns the masked version directly. ```bash curl https://gw-tr.gurubase.io/v1/responses \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "model": "gurubase-siper", "input": "Vatandaş Ahmet Yılmaz, TCKN 10000000382, başvuru durumu nedir?" }' ``` The masked text is returned in the `output_text` field: ```text Vatandaş , TCKN , başvuru durumu nedir? ``` The request never reaches any language model; `gurubase-siper` is not a language model but the reserved model name the Gateway sets aside for masking, and it also works with Chat Completions. If masking cannot be performed, the request stops with a 502 and the raw text is not returned either (fail-closed). If you also need the detection report (the list of categories and positions), use the `/mask` endpoint directly: [Mask-only usage](/docs/en/guides/mask-only/). ## Virtual key All requests are authenticated with the virtual key in the `Authorization: Bearer` header. You generate the virtual key in the panel; the real provider key stays inside the Gateway only, so you do not need to keep it in your application. You can revoke a key in the panel and generate a new one. See [Panel](/docs/en/panel/) for the steps. ## Listing models You get the models you can access from the `/v1/models` endpoint; the reserved `gurubase-siper` name also appears in the list. ```bash curl https://gw-tr.gurubase.io/v1/models \ -H "Authorization: Bearer $SANAL_ANAHTAR" ``` To use masking without the Gateway, as a step in your own pipeline, see [Mask-only usage](/docs/en/guides/mask-only/); to try it without writing code, see [Playground](/docs/en/guides/playground/). If you are looking for a ready-made enterprise assistant instead of writing your own application, [Gurubase](https://gurubase.io) offers agents that connect to your organization’s knowledge sources (Confluence, Zendesk, Google Drive, your website, and more), ground their answers in those sources, and cite them; it can be deployed in the cloud or on-premise. --- # Mask-only usage Source: https://siper.gurubase.ai/docs/en/guides/mask-only/ Using the Siper /mask endpoint directly. Transform options, batch requests, category filtering, and pattern lists. You can also use masking without a language model, as a step in your own pipeline. The `/mask` endpoint takes text and returns the masked text together with a detection report that shows what was found in which range. Diagram: input text goes to the /mask endpoint; the response returns the masked text together with the detection report. You authorize requests with the virtual key you generate in the panel, sent in the `Authorization: Bearer` header; it is the same key you use for Gateway calls. `/mask` calls are also subject to request limits and the audit trail. Body errors (missing or malformed requests) and authentication errors are returned in the Gateway’s error format; field validation details may arrive in the masking service’s own format. ## First call ```bash curl https://gw-tr.gurubase.io/mask \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{"text": "Ahmet Yılmaz, TCKN 10000000382, İstanbul'\''da yaşıyor."}' ``` ```json { "masked_text": ", TCKN , İstanbul'da yaşıyor.", "transform": "placeholder", "spans": [ { "category": "person", "start": 0, "end": 12, "score": 0.85 }, { "category": "tckn", "start": 19, "end": 30, "score": 1.0 } ], "timings_ms": { "total": 27.58 } } ``` `masked_text` is the masked text; direct masking endpoints use raw category names in placeholders ([Concepts](/docs/en/concepts/)). The `spans` list gives, for each detection, the category, the character range in the input text (`start`, `end`), and the confidence score (`score`). `timings_ms.total` is the total processing time. ## Transform options The `transform` field determines the shape of the masked text; the default is `placeholder`. | Value | Behavior | | --- | --- | | `placeholder` | Replaces the value with a numbered placeholder such as ``; you can still see how many values of each category appeared. | | `mask` | Covers the characters with a fill character; length is preserved. You choose the fill character with `mask_char`, the default is `#`. | ## Batch requests You send multiple texts to the `/mask/batch` endpoint in a single request; the `results` array is returned in the same order as the input. For text that exceeds the length limit, `/mask` returns 413. On `/mask/batch`, this limit is applied to the combined total text. ```bash curl https://gw-tr.gurubase.io/mask/batch \ -H "Authorization: Bearer $SANAL_ANAHTAR" \ -H "Content-Type: application/json" \ -d '{ "texts": [ "Ahmet Yılmaz aradı.", "IBAN: TR12 0001 0000 0000 0000 0000 01" ] }' ``` ## Category filtering The default behavior is to mask all 26 categories. You narrow the scope with the `categories` field: you pick a `preset`, and if needed the `enable` list adds categories to the set while `disable` removes them. Category keys are the same as the `category` values in the report (such as `person`, `tckn`, `saglik`). | Preset | Scope | | --- | --- | | `ALL` | All categories; same as the default behavior. | | `KVKK` | Full coverage under KVKK (Turkey’s personal data protection law); the same set as `ALL`. | | `KVKK_SENSITIVE` | Only the nine special categories under Article 6. | | `IDENTITY` | Only person and address. | | `IDENTIFIERS` | Only number- and code-style identifiers (such as TCKN, IBAN, phone). | ```json { "text": "...", "categories": { "preset": "KVKK_SENSITIVE" } } ``` For the full list of categories and the Article 6 distinction, see [Categories](/docs/en/categories/). ## Pattern lists With two list fields, you add your own rules to the masking decision. Both take a list of regular expressions (Python `re` syntax); an invalid pattern returns 422. - `allow_patterns`: if the surface text of a detected span matches a pattern, that span is not masked. Useful for fixed values that are not personal data; for example, you do not want your shared support address or your organization’s name to be masked. - `block_patterns`: every piece of text that matches a pattern is masked, even if the model did not detect it. Use it to lock in organization-specific registry, file, or customer number formats. If you pass a plain string, the category is `custom`; with a `{"pattern": ..., "category": ...}` object you assign a category. A match that overlaps an existing detection is skipped; the detection wins. ```json { "text": "...", "allow_patterns": ["destek@kurum\\.example", "\\bDemo Kurum\\b"], "block_patterns": [ "\\bMST-\\d{6}\\b", { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" } ] } ``` For the placeholder format and the language distinction, see [Concepts](/docs/en/concepts/). To use the same masking inside a chat flow, see [Gateway integration](/docs/en/guides/gateway-integration/). --- # Playground Source: https://siper.gurubase.ai/docs/en/guides/playground/ Try masking without writing code, using the Playground in the panel. Live preview, ready-made examples, and chat. The fastest way to try masking is the Playground in the panel. You write no code: you paste the text, and you see the masked version and the model’s response on the same screen. ## Masking preview As you type the text, the panel highlights the detected personal data instantly. Each category is highlighted in its own color; the masked output sits right next to it. Before you send a request, you know the final form of the text that will go to the model. ![Playground masking screen: input text and color-coded masked output side by side](/docs/screenshots/panel/playground-maskeleme-light@2x.png) ## Ready-made examples You can start with one of the ready-made examples; it looks like this: ```text Girdi : "Ayşe Demir, ayse.demir@ornek.gov.tr, 0532 000 11 22'den ulaşılabilir." Maskeli: ", , 'den ulaşılabilir." ``` Label language Turkish labels such as `` here are specific to the panel display. If you call the API directly, the output is in English (``, ``); see [Concepts](/docs/en/concepts/) for the details of this distinction. ## Chat You can go beyond the preview and try the flow end to end: 1. Type the text; the masked preview appears. 2. Send it; the Gateway forwards the masked text to the model. 3. The response streams in; placeholders are preserved in the response as-is. This way, the masked form of the text going to the language model is in front of you at every step. ![Playground chat screen: masked text goes to the model, the response appears in the stream](/docs/screenshots/panel/playground-sohbet-light@2x.png) To bring the flow you see here into your application, continue with the [Gateway integration](/docs/en/guides/gateway-integration/) guide; the full list of masked categories is on the [Categories](/docs/en/categories/) page. --- # MCP server Source: https://siper.gurubase.ai/docs/en/guides/mcp/ Add Siper's demo MCP server to tools like Claude Code so your text is masked before it reaches the model. You can use Siper’s masking from inside AI tools such as Claude Code. The Model Context Protocol (MCP) is an open standard that defines how such tools call external services as tools; Siper publishes a demo server that speaks this standard: ```text https://siper.gurubase.ai/api/mcp ``` The server offers a single tool: `mask_turkish_pii`, which masks personal data in Turkish text. You run the text through this tool before sending it to a language model; the masked version is what reaches the model. No key is required. The transport layer is Streamable HTTP; there are no sessions and no SSE, each request stands on its own. The tool masks all 26 categories; you can find the full list on the [Categories](/docs/en/categories/) page. In the output, values are replaced with numbered placeholders such as ``; the format details are on the [Concepts](/docs/en/concepts/) page. ## Adding to Claude Code One command is enough: ```bash claude mcp add --transport http siper-mask https://siper.gurubase.ai/api/mcp ``` After setup, Claude Code can call the `mask_turkish_pii` tool on its own when needed; you can also trigger it manually by saying “mask this text”. ## Other clients Setup links and configuration examples for Cursor, VS Code, and similar clients are on the info page that appears when you open the endpoint address in a browser: [siper.gurubase.ai/api/mcp](https://siper.gurubase.ai/api/mcp). A discovery card is also live so clients can recognize the server on their own: [server-card.json](https://siper.gurubase.ai/.well-known/mcp/server-card.json). ## Limits This server is not the product itself but a demo service for evaluation; it introduces itself to clients under the name `siper-mask-demo`. - The input (`text`) is at most 2,000 characters. - The number of requests is limited (rate limit). - It runs without a key; for that reason it is not a production surface. For production integration, use the product endpoints, not the MCP demo: the Gateway’s `/v1` endpoint for automatic masking in a chat flow ([Gateway integration](/docs/en/guides/gateway-integration/)), and the `/mask` API to use masking as a standalone step ([Mask-only usage](/docs/en/guides/mask-only/)). If you tried the demo and liked the output, the next stop is [Getting started](/docs/en/getting-started/): you get your virtual key and send your first masked request from your own code. --- # Gurubase Gateway API Source: https://siper.gurubase.ai/docs/en/api/gateway/ Gurubase Gateway is an AI gateway fully compatible with **OpenAI Chat Completions**. You switch by changing only the `base_url` and the API key (virtual key) in your existing OpenAI SDK; no code changes are required. With masking enabled by default, detected personal-data fields are replaced in Türkiye by Gurubase Siper **before** a request is forwarded to the backend language model (e.g. Azure OpenAI). Masking can be disabled per virtual key; a disabled key forwards the request unchanged (passthrough). The response flows back. > **Authentication:** All requests are sent with the > `Authorization: Bearer ` header. The virtual key is > generated in the admin panel; the real provider (Azure) key is kept only > inside the gateway and is never sent down to the client. Version 1.0 Base URL `https://gw-tr.gurubase.io` ## Chat OpenAI-compatible Chat Completions endpoints - [POST Chat Completions (OpenAI compatible) `/v1/chat/completions`](/docs/en/api/gateway/chat/createchatcompletion/) ## Responses OpenAI-compatible Responses API endpoint - [POST Responses API (OpenAI compatible) `/v1/responses`](/docs/en/api/gateway/responses/createresponse/) ## Models List of accessible models - [GET List accessible models `/v1/models`](/docs/en/api/gateway/models/listmodels/) --- # Responses API (OpenAI compatible) Source: https://siper.gurubase.ai/docs/en/api/gateway/responses/createresponse/ Compatible with OpenAI `POST /v1/responses`. The `input` field can be a string or an array of messages. With masking enabled, detected PII fields in either form are replaced before the model call. If the masking step cannot run, the request stops **fail-closed** before the model call. POST `/v1/responses` ## Request body required `application/json` `model` string required Target model identifier (defined in the panel). `input` string | ChatMessage[] required A string or an array of messages. With masking enabled, detected personal-data fields in either form are replaced inside the gateway before the model call. One of: string `string` ChatMessage[] Array of `ChatMessage` `role` string required Allowed: `system` `user` `assistant` `tool` `content` string required Message text. With masking enabled, detected personal-data fields in all roles (`system`, `user`, `assistant`, `tool`) are replaced with placeholders inside the gateway. `stream` boolean default: false `temperature` number min 0 · max 2 `max_output_tokens` integer Maximum number of tokens to generate. min 1 ## Responses 200 Successful response `id` string `object` string `created_at` integer `model` string `status` string `output` ResponsesOutputItem[] Array of `ResponsesOutputItem` `id` string `type` string `status` string `role` string `content` ResponsesContentPart[] Array of `ResponsesContentPart` `type` string `text` string `annotations` object[] `usage` Usage `prompt_tokens` integer `completion_tokens` integer `total_tokens` integer 401 Missing or invalid virtual key `error` object `message` string `type` string 413 The input exceeds the masking limit. The request is not forwarded to the model; split the text and retry. `error` object `message` string `type` string 429 Quota or rate limit exceeded `error` object `message` string `type` string 502 The masking step could not run. The request is **fail-closed** and is not forwarded to the model; there is no "send it unmasked" option. `error` object `message` string `type` string ### Request #### openai-python ``` from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) resp = client.responses.create( model="gpt-4o-mini", input="Ahmet Yılmaz, TCKN 10000000382, adres değişikliği istiyor.", ) print(resp.output_text) ``` #### python ``` import requests response = requests.post( "https://gw-tr.gurubase.io/v1/responses", headers={ "Content-Type": "application/json" }, json={ "model": "gpt-4o-mini", "input": "Ahmet Yılmaz, TCKN 10000000382, talebini iletti.", "stream": False, "temperature": 0, "max_output_tokens": 0 }, ) ``` #### curl ``` curl -X POST "https://gw-tr.gurubase.io/v1/responses" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "input": "Ahmet Yılmaz, TCKN 10000000382, talebini iletti.", "stream": false, "temperature": 0, "max_output_tokens": 0 }' ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/v1/responses", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "model": "gpt-4o-mini", "input": "Ahmet Yılmaz, TCKN 10000000382, talebini iletti.", "stream": false, "temperature": 0, "max_output_tokens": 0 }) }); ``` ### Response #### 200 ``` { "id": "resp_01ec5099f62feeda", "object": "response", "created_at": 1782136928, "model": "gpt-4o-mini", "status": "completed", "output": [ { "id": "msg_01ec5099f62feeda", "type": "message", "status": "completed", "role": "assistant", "content": [ { "type": "output_text", "text": "Kayıt alındı.", "annotations": [ {} ] } ] } ], "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 } } ``` #### 401 ``` { "error": { "message": "string", "type": "string" } } ``` #### 413 ``` { "error": { "message": "string", "type": "string" } } ``` #### 429 ``` { "error": { "message": "string", "type": "string" } } ``` #### 502 ``` { "error": { "message": "string", "type": "string" } } ``` --- # Chat Completions (OpenAI compatible) Source: https://siper.gurubase.ai/docs/en/api/gateway/chat/createchatcompletion/ Compatible with OpenAI `POST /v1/chat/completions`. With masking enabled, detected PII fields in `messages` are replaced with placeholders before the model call. SSE streaming is supported with `stream: true`. POST `/v1/chat/completions` ## Request body required `application/json` `model` string required Target model identifier (defined in the panel). `messages` ChatMessage[] required min items 1 Array of `ChatMessage` `role` string required Allowed: `system` `user` `assistant` `tool` `content` string required Message text. With masking enabled, detected personal-data fields in all roles (`system`, `user`, `assistant`, `tool`) are replaced with placeholders inside the gateway. `stream` boolean If true, the response is returned as an SSE stream. default: false `temperature` number min 0 · max 2 · default: 1 `max_tokens` integer Maximum number of tokens to generate. min 1 `top_p` number min 0 · max 1 ## Responses 200 Successful response `id` string `object` string `created` integer `model` string `choices` ChatChoice[] Array of `ChatChoice` `index` integer `finish_reason` string `message` ChatMessage `role` string required Allowed: `system` `user` `assistant` `tool` `content` string required Message text. With masking enabled, detected personal-data fields in all roles (`system`, `user`, `assistant`, `tool`) are replaced with placeholders inside the gateway. `usage` Usage `prompt_tokens` integer `completion_tokens` integer `total_tokens` integer 401 Missing or invalid virtual key `error` object `message` string `type` string 413 The input exceeds the masking limit. The request is not forwarded to the model; split the text and retry. `error` object `message` string `type` string 429 Quota or rate limit exceeded `error` object `message` string `type` string 502 The masking step could not run. The request is **fail-closed** and is not forwarded to the model; there is no "send it unmasked" option. `error` object `message` string `type` string ### Request #### openai-python ``` from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) resp = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "user", "content": "Ayşe Demir'in talebini özetle."}, ], ) print(resp.choices[0].message.content) ``` #### python ``` import requests response = requests.post( "https://gw-tr.gurubase.io/v1/chat/completions", headers={ "Content-Type": "application/json" }, json={ "model": "gpt-4o-mini", "messages": [ { "role": "system", "content": "string" } ], "stream": False, "temperature": 1, "max_tokens": 0, "top_p": 0 }, ) ``` #### curl ``` curl -X POST "https://gw-tr.gurubase.io/v1/chat/completions" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [ { "role": "system", "content": "string" } ], "stream": false, "temperature": 1, "max_tokens": 0, "top_p": 0 }' ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "model": "gpt-4o-mini", "messages": [ { "role": "system", "content": "string" } ], "stream": false, "temperature": 1, "max_tokens": 0, "top_p": 0 }) }); ``` ### Response #### 200 ``` { "id": "chatcmpl-abc123", "object": "chat.completion", "created": 1718000000, "model": "gpt-4o-mini", "choices": [ { "index": 0, "finish_reason": "stop", "message": { "role": "system", "content": "string" } } ], "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 } } ``` #### 401 ``` { "error": { "message": "Sanal anahtar gerekli veya geçersiz.", "type": "invalid_request_error" } } ``` #### 413 ``` { "error": { "message": "string", "type": "string" } } ``` #### 429 ``` { "error": { "message": "string", "type": "string" } } ``` #### 502 ``` { "error": { "message": "string", "type": "string" } } ``` --- # List accessible models Source: https://siper.gurubase.ai/docs/en/api/gateway/models/listmodels/ OpenAI-compatible list of the models the virtual key can access. GET `/v1/models` ## Responses 200 Model list `object` string `data` Model[] Array of `Model` `id` string Model identifier; comes with the provider prefix (e.g. `openai/gpt-4o-mini`). `object` string `owned_by` string Owner field; usually returned empty in the gateway list. ### Request #### openai-python ``` from openai import OpenAI client = OpenAI( base_url="https://gw-tr.gurubase.io/v1", api_key="SANAL_ANAHTAR", ) for model in client.models.list(): print(model.id) ``` #### python ``` import requests response = requests.get( "https://gw-tr.gurubase.io/v1/models", ) ``` #### curl ``` curl -X GET "https://gw-tr.gurubase.io/v1/models" ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/v1/models", { method: "GET" }); ``` ### Response #### 200 ``` { "object": "list", "data": [ { "id": "openai/gpt-4o-mini", "object": "model", "owned_by": "" } ] } ``` --- # Gurubase Siper API Source: https://siper.gurubase.ai/docs/en/api/siper/ The Gurubase Siper API detects personal data in Turkish text, masks it according to the transform you choose, and returns the detected categories in the same response. In the gateway integration, Siper masks the text before it reaches the language model; it can also be used directly and on its own through the `/mask` and `/mask/batch` endpoints. > **Authentication:** the virtual key you generate in the panel is sent in > the `Authorization: Bearer ` header. The architecture is the > same in an on-premise installation: the Gateway and the panel ship with > the setup, and requests are still authorized with a virtual key. Version 1.0 Base URL `https://gw-tr.gurubase.io` ## Maskeleme Single and batch masking endpoints - [POST Mask text `/mask`](/docs/en/api/siper/maskeleme/mask/) - [POST Mask in batch `/mask/batch`](/docs/en/api/siper/maskeleme/maskbatch/) --- # Mask text Source: https://siper.gurubase.ai/docs/en/api/siper/maskeleme/mask/ Detects personal data in the given text and masks it according to the selected transform. The default transform is `placeholder` (a reversible placeholder). POST `/mask` ## Request body required `application/json` `text` string required The raw text to mask. `transform` string `placeholder` (reversible ``), `mask` (length-preserving `####`, irreversible). default: "placeholder" Allowed: `placeholder` `mask` `mask_char` string Fill character for transform=mask. default: "#" `return_vault` boolean Returns the placeholder to original value mapping (sensitive! off by default, never logged). default: false `categories` object Category filtering: `{preset, enable:[...], disable:[...]}`. preset values: ALL, IDENTITY, IDENTIFIERS, KVKK, KVKK_SENSITIVE. (KVKK = full scope; KVKK_SENSITIVE = only the Article 6 special categories.) `allow_patterns` string[] A list of regular expressions (Python `re` syntax) that exempt matches from masking (an allowlist). If the surface text of a detected field matches one of the patterns, that field is NOT masked. Use it when a public value such as an organization name is mistakenly taken for personal data. An invalid pattern returns 422. **Limits:** at most 25 patterns, at most 200 characters per pattern. There is a time budget for scanning. If an exemption pattern exceeds the budget it is NOT applied and the request completes normally: a rule that reduces masking should not take effect under uncertainty. `block_patterns` string | object[] A list of regular expressions; every matching piece of text is FORCE-masked even if the model did not detect it. Use it to guarantee identifiers specific to you, such as an internal registry or file number. A plain string gets the category `custom`; a `{pattern, category}` object assigns the category. A match that overlaps an existing detection is skipped (the detection wins). An invalid pattern returns 422. **Limits:** at most 25 patterns, at most 200 characters per pattern. There is a time budget for scanning; if the budget is exceeded the request returns 422. We prefer rejecting the request over silently masking less than we should. **Organization patterns:** the patterns defined for your organization in the panel are ADDED to the ones in this request and cannot be dropped by the request body. The result can only increase masking. Array of `string | object` One of: string `string` object `pattern` string required Regular expression (Python `re` syntax). `category` string Category to assign to the forced field (default `custom`). ## Responses 200 Masking result `masked_text` string The masked text. `transform` string `spans` Span[] Array of `Span` `category` string `start` integer `end` integer `score` number `timings_ms` object Total processing time (ms): only { total }. `vault` object If return_vault=true, the placeholder to original mapping (sensitive). 401 Missing or invalid virtual key `detail` string 413 Text exceeded the maximum length (split it or use /mask/batch) 422 Invalid request body `detail` ValidationError[] Array of `ValidationError` `loc` string | integer[] Array of `string | integer` Any of: string `string` integer `integer` `msg` string `type` string ### Request #### python ``` import requests response = requests.post( "https://gw-tr.gurubase.io/mask", headers={ "Content-Type": "application/json" }, json={ "text": "Ahmet Yılmaz, TC 10000000214.", "transform": "placeholder", "mask_char": "#", "return_vault": False, "categories": {}, "allow_patterns": [ "\\bDemo Kurum\\b" ], "block_patterns": [ "\\bPRJ-\\d{4}\\b", { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" } ] }, ) ``` #### curl ``` curl -X POST "https://gw-tr.gurubase.io/mask" \ -H "Content-Type: application/json" \ -d '{ "text": "Ahmet Yılmaz, TC 10000000214.", "transform": "placeholder", "mask_char": "#", "return_vault": false, "categories": {}, "allow_patterns": [ "\\bDemo Kurum\\b" ], "block_patterns": [ "\\bPRJ-\\d{4}\\b", { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" } ] }' ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/mask", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "text": "Ahmet Yılmaz, TC 10000000214.", "transform": "placeholder", "mask_char": "#", "return_vault": false, "categories": {}, "allow_patterns": [ "\\bDemo Kurum\\b" ], "block_patterns": [ "\\bPRJ-\\d{4}\\b", { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" } ] }) }); ``` ### Response #### 200 ``` { "masked_text": "string", "transform": "string", "spans": [ { "category": "person", "start": 0, "end": 0, "score": 0.85 } ], "timings_ms": {}, "vault": {} } ``` #### 401 ``` { "detail": "string" } ``` #### 413 Text exceeded the maximum length (split it or use /mask/batch) #### 422 ``` { "detail": [ { "loc": [ "string" ], "msg": "string", "type": "string" } ] } ``` --- # Mask in batch Source: https://siper.gurubase.ai/docs/en/api/siper/maskeleme/maskbatch/ Masks several texts in a single request. The response is mapped to the input order. The length limit is applied over the combined total text. POST `/mask/batch` ## Request body required `application/json` `texts` string[] required The list of texts to mask. `transform` string default: "placeholder" Allowed: `placeholder` `mask` `surrogate` `return_vault` boolean default: false ## Responses 200 Masking result for each input `results` MaskResponse[] Array of `MaskResponse` `masked_text` string The masked text. `transform` string `spans` Span[] Array of `Span` `category` string `start` integer `end` integer `score` number `timings_ms` object Total processing time (ms): only { total }. `vault` object If return_vault=true, the placeholder to original mapping (sensitive). 401 Missing or invalid virtual key 413 Too many texts, or the combined total text exceeded the length limit 422 Invalid request body `detail` ValidationError[] Array of `ValidationError` `loc` string | integer[] Array of `string | integer` Any of: string `string` integer `integer` `msg` string `type` string ### Request #### python ``` import requests response = requests.post( "https://gw-tr.gurubase.io/mask/batch", headers={ "Content-Type": "application/json" }, json={ "texts": [ "Ahmet Yılmaz aradı.", "IBAN: TR12 0001 0000 0000 0000 0000 01" ] }, ) ``` #### curl ``` curl -X POST "https://gw-tr.gurubase.io/mask/batch" \ -H "Content-Type: application/json" \ -d '{ "texts": [ "Ahmet Yılmaz aradı.", "IBAN: TR12 0001 0000 0000 0000 0000 01" ] }' ``` #### js ``` const response = await fetch("https://gw-tr.gurubase.io/mask/batch", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "texts": [ "Ahmet Yılmaz aradı.", "IBAN: TR12 0001 0000 0000 0000 0000 01" ] }) }); ``` ### Response #### 200 ``` { "results": [ { "masked_text": "string", "transform": "string", "spans": [ { "category": "person", "start": 0, "end": 0, "score": 0.85 } ], "timings_ms": {}, "vault": {} } ] } ``` #### 401 Missing or invalid virtual key #### 413 Too many texts, or the combined total text exceeded the length limit #### 422 ``` { "detail": [ { "loc": [ "string" ], "msg": "string", "type": "string" } ] } ```