Turasistan API v2
Hızlı başlangıç Uç noktalar Swagger
B2B entegrasyon

Giriş

Turasistan API; tur kataloğu, cari kayıtları, rezervasyon, tahsilat–ödeme ve muhasebe aktarımlarını tek bir REST arayüzünde sunar. Bu doküman kimlik doğrulama, uç noktalar, veri modelleri ve canlıya geçiş adımlarını kapsar.

Base URL
prod.turasistan.com
Yol öneki
/api/v2
Kimlik
APIKEY · Bearer JWT
Biçim
application/json
Limit
100 istek / dakika
Tarih
ISO-8601
Beş dakika

Hızlı başlangıç

Aşağıdaki dört adımı tamamladığınızda canlı veriye erişen çalışan bir istemciniz olur.

  1. Anahtar üretin

    Turasistan uygulamasında Ayarlar → API Anahtarlarım → API Anahtarı Üret. Form iki zorunlu alan ister:

    • Şirket(ler) — anahtarın hangi şirket kapsamında veri göreceği.
    • İzin verilen IP adresleri — isteği yapacak sunucunuzun çıkış (egress) IP'si, virgülle ayrılmış.

    Anahtar üretimi kullanıcı oturumu (JWT) gerektirir; bir API Key ile yeni API Key üretilemez. Firma (tenant) başına en fazla 5 aktif anahtar tutulabilir ve profilden üretilen anahtarların ömrü 1 yıldır.

  2. Bağlantıyı doğrulayın

    Hafif bir uç ile başlayın. 200 dönüyorsa anahtar geçerli, IP izinli ve uç erişiminize açıktır.

    curl -s -i "https://prod.turasistan.com/api/v2/UsedCurrencies?take=5" \
      -H "APIKEY: $TURASISTAN_API_KEY" \
      -H "Accept: application/json"
    // Minimal connectivity check.
    package main
    
    import (
    	"fmt"
    	"net/http"
    	"os"
    	"time"
    )
    
    func main() {
    	client := &http.Client{Timeout: 30 * time.Second}
    
    	req, _ := http.NewRequest(http.MethodGet,
    		"https://prod.turasistan.com/api/v2/UsedCurrencies?take=5", nil)
    	req.Header.Set("APIKEY", os.Getenv("TURASISTAN_API_KEY"))
    	req.Header.Set("Accept", "application/json")
    
    	resp, err := client.Do(req)
    	if err != nil {
    		panic(err)
    	}
    	defer resp.Body.Close()
    
    	fmt.Println("status:", resp.StatusCode)
    }
    // Minimal connectivity check.
    const res = await fetch(
      "https://prod.turasistan.com/api/v2/UsedCurrencies?take=5",
      { headers: { APIKEY: process.env.TURASISTAN_API_KEY, Accept: "application/json" } }
    );
    
    console.log(res.status, await res.json());
    # Minimal connectivity check.
    import os, requests
    
    res = requests.get(
        "https://prod.turasistan.com/api/v2/UsedCurrencies",
        params={"take": 5},
        headers={"APIKEY": os.environ["TURASISTAN_API_KEY"]},
        timeout=30,
    )
    print(res.status_code, res.json())
    // Minimal connectivity check.
    using var client = new HttpClient { BaseAddress = new Uri("https://prod.turasistan.com/") };
    client.DefaultRequestHeaders.Add("APIKEY", Environment.GetEnvironmentVariable("TURASISTAN_API_KEY"));
    
    var response = await client.GetAsync("api/v2/UsedCurrencies?take=5");
    Console.WriteLine((int)response.StatusCode);
  3. Bir liste ucundan veri çekin

    Liste uçları aynı ızgara (grid) sözleşmesini kullanır: skip/take ile sayfalama, alan_operatör biçiminde filtre, alan_sort ile sıralama.

    curl -s "https://prod.turasistan.com/api/v2/Tours?take=20&skip=0&isActive_eq=true&startDate_gte=2026-08-01&startDate_sort=asc" \
      -H "APIKEY: $TURASISTAN_API_KEY"
    {
      "data": [
        {
          "id": 4821,
          "name": "Umre Programı — Ağustos",
          "tourCode": "UMR-0825",
          "startDate": "2026-08-14T00:00:00",
          "finishDate": "2026-08-28T00:00:00",
          "capacity": 90,
          "customerCount": 63,
          "remainingQuota": 27,
          "currencyId": 2,
          "currencySymbol": "$",
          "isActive": true,
          "isClosed": false,
          "tourPricePackages": [
            { "id": 9912, "name": "4 Kişilik Oda", "price": 1850, "discountStudentPrice": 1700 }
          ]
        }
      ],
      "count": 137
    }
  4. Yazma işlemine geçin

    Yazma uçları application/json gövde bekler ve doğrulama hatalarını gövdede döner. Rezervasyon akışının tamamı için Rezervasyon oluşturma senaryosuna bakın.

    curl -s -X POST "https://prod.turasistan.com/api/v2/Customers" \
      -H "APIKEY: $TURASISTAN_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "name": "Ahmet", "surname": "Yılmaz", "isActive": true, "isDealer": false }'
    { "id": 51204, "customerNumber": 10387 }
Güvenlik

Kimlik doğrulama

API iki şema destekler. Sunucudan sunucuya entegrasyonlarda API Key kullanın; JWT yalnızca son kullanıcı oturumu olan uygulamalar içindir.

Şemalar

Şema Başlık Kullanım
API Key APIKEY: trs_...
Authorization: ApiKey trs_...
Sunucudan sunucuya entegrasyon. İki biçim de kabul edilir; APIKEY başlığı öncelikli okunur.
Bearer JWT Authorization: Bearer eyJ... Kullanıcı oturumu gerektiren işlemler (ör. yeni API Key üretimi). Kullanıcı bağlamı taşır.

Başlıkta anahtar yoksa istek anonim sayılır ve korumalı uçlar 401 döner.

API Key gizli bir kimlik bilgisidir. Tarayıcıda çalışan koda (SPA, mobil uygulama içi WebView) koymayın; yalnızca kendi sunucunuzdan yapılan isteklerde kullanın. Tam anahtarı destek dahil kimseyle paylaşmayın. Anahtarınızla yapılan tüm istekler sizin adınıza yapılmış sayılır.

Yetki kapsamı

Anahtar, oluşturulduğu tenant ve seçilen şirketler ile sınırlıdır. İsteklerde tenant veya şirket parametresi göndermezsiniz; kapsam anahtardan çözülür. Farklı şirketler için ayrı anahtar üretin — bu, bir anahtarın sızması durumundaki etkiyi de sınırlar.

IP kısıtlaması

  • Liste virgülle ayrılır: 203.0.113.10,203.0.113.11
  • Karşılaştırma birebir metin eşleşmesidir. CIDR (203.0.113.0/24), aralık veya joker desteklenmez.
  • Sunucunun gördüğü istemci IP'si ile karşılaştırılır. NAT, proxy veya yük dengeleyici arkasındaysanız listeye çıkış (egress) IP'nizi yazın, yerel adresi değil.
  • IPv6 üzerinden çıkıyorsanız IPv6 adresini de ekleyin; aksi halde istek bloklanır.

IP değiştirme: profil akışında var olan bir anahtarın IP listesini güncelleyen bir uç yoktur. Çıkış IP'niz değişecekse yeni IP ile ikinci bir anahtar üretip geçiş yapın, sonra eskisini silin. Silme anında etkilidir.

Otomatik ölçeklenen veya IP'si değişken ortamlarda (Kubernetes, serverless, otomatik ölçeklenen VM havuzu) çalışıyorsanız isteklerinizi sabit IP'li bir NAT gateway veya çıkış proxy'si üzerinden yönlendirin. Aksi halde yeni pod/örnek ilk isteğinde 401 alır.

Anahtar yaşam döngüsü

Konu Kural
Adet Firma (tenant) başına en fazla 5 aktif anahtar.
Süre Profilden üretilen anahtarlar 1 yıl geçerlidir. Süre dolmadan önce otomatik uyarı gönderilmez; takip size aittir.
Rotasyon Yeni anahtarı üretin → dağıtımı yapın → trafiğin yeni anahtardan geldiğini doğrulayın → eskisini silin.
Sızıntı Şüphe halinde yeni anahtar üretip devreye alın, ardından eskisini silin. Silme anında etkilidir.
Saklama Anahtarı ortam değişkeni veya gizli anahtar deposunda tutun; depoya (repo), log'a veya hata izlerine yazmayın.
Sözleşme

İstek kuralları

Adresleme

Tüm uçlar https://prod.turasistan.com/api/v2 altındadır. Yol segmentleri büyük/küçük harf duyarlıdır: /api/v2/Tours doğrudur, /api/v2/tours yönlendirme yapılandırmasına göre farklı davranabilir — spesifikasyondaki yazımı birebir kullanın.

Başlıklar

Başlık Zorunlu Açıklama
APIKEY Evet* API anahtarı. Alternatifi: Authorization: ApiKey {key} veya Authorization: Bearer {jwt}.
Content-Type Gövdeli isteklerde application/json. Yalnızca /Customers/web-online-form uçları multipart/form-data kullanır.
Accept-Language Hayır Yerelleştirilmiş içerikte kullanılır (/AdminDatas/cache, /Translates/locale-messages, autocomplete uçları). Değer yoksa varsayılan dile düşer.
X-Target-Saas-Id Hayır Sistem yöneticileri için hedef firma kimliği (impersonation). Standart B2B anahtarlarında kullanılmaz; kapsam anahtardan çözülür.
X-Mobile-Reader-Code Hayır Mobil cihazlar için 5 haneli tenant PIN kodu. Pasaport okuyucu senaryolarına özgüdür.

* Anonim erişime açık bir uç kullanmıyorsanız zorunludur.

Veri türleri

Tür Biçim Örnek
Tarih (yalnız gün) YYYY-MM-DD documentDate_gte=2026-04-01
Tarih-saat ISO-8601 2026-04-01T09:30:00+03:00
Tutar Ondalık sayı, nokta ayraçlı 1850.75
Boole (filtrede) "true" / "false" metni isActive_eq=true
Çoklu kimlik Virgülle ayrılmış tam sayılar tourIds_in=1,2,3
Dosya Base64 (toplu görsel uçları) veya multipart {"imageName":"...","imageBase64":"..."}
Saat dilimi. Operasyon verileri Türkiye saatiyle (UTC+3) üretilir. Tarih-saat alanlarını gönderirken ofseti açıkça belirtin; ofsetsiz gönderilen değerler sunucu yerel saatine göre yorumlanır. Uçuş/transfer bacaklarında ayrıca startDate_Tz / finishDate_Tz ofset alanları taşınır.
Sözleşme

Yanıt biçimleri

API'de üç yanıt kalıbı vardır. İstemcinizde önce HTTP durum kodunu, sonra gövdeyi okuyun; gövde biçimi kalıba göre değişir.

1 · Izgara sonucu (GridResult)

Sayfalanabilir tüm liste uçları bu kalıbı döner. count filtreye uyan toplam satır sayısıdır, sayfadaki satır sayısı değil.

{
  "data": [ { "id": 1, "name": "..." } ],
  "count": 137
}

/AccountingDebitCredits gibi bazı uçlar ek olarak bir summary nesnesi taşır:

{
  "data": [ /* ... */ ],
  "count": 4210,
  "summary": {
    "totalDebit": 1284500.00,
    "totalCredit": 1190320.50,
    "totalBalance": 94179.50,
    "currencyId": 1,
    "currencyCode": "TRY"
  }
}

2 · Servis sonucu (ServiceResult)

Zarflı kalıp. /Tours/active-tours gibi uçlarda ve doğrulama geri bildiriminde kullanılır.

{
  "isSuccess": true,
  "message": "İşlem başarılı",
  "data": [ /* ... */ ],
  "meta": { "totalCount": 137, "page": 1, "pageSize": 20, "totalPages": 7, "hasNext": true, "hasPrevious": false },
  "validationErrors": null
}

3 · Çıplak nesne / dizi

Detay uçları (GET /Tours/{id}), autocomplete uçları ve hesaplama uçları zarfsız döner: doğrudan nesne, dizi veya skaler (ör. /ExChangeRates/rate bir double döner).

Boş yanıtlar

Durum Anlam Nerede
200 Başarılı; gövde olabilir veya olmayabilir Çoğu okuma ve bazı yazma uçları
204 Başarılı, gövde yok PUT /Customers/{id}, POST /Customers/import-with-tour, PUT /AccountingDebitCreditsBeyGroup/{id}
Boş dizi Kayıt bulunamadı — hata değildir Autocomplete ve arama uçları
Autocomplete uçlarında boş arama metni boş liste döndürür; bunu hata olarak işlemeyin. /Airports/AutoCompleteSearch en fazla 20 sonuç döner.
Sorgulama

Sayfalama, filtreleme ve sıralama

Izgara uçları tek bir sorgu dili paylaşır: alan + _operatör. Aynı kural bütün liste uçlarında geçerlidir; alan adları yanıt DTO'sundaki alan adlarıyla birebir aynıdır.

Ortak parametreler

Parametre Tür Varsayılan Açıklama
skip int 0 Atlanacak kayıt sayısı (sayfalama ofseti).
take int 20 Sayfa boyutu. Büyük değerler yanıt süresini ve limit tüketimini artırır.
count bool false true iken satır dönmez, yalnızca toplam sayı hesaplanır. Sayfalama arayüzü kurarken ucuz yoldur.
includeInactive bool false Pasif kayıtları da getirir. Varsayılan olarak yalnızca aktif kayıtlar döner.
includeSummary bool false Ucun desteklediği durumda filtrelenmiş küme için özet hesaplar.

Operatör soneki tablosu

Alan türü Sonekler Örnek
Sayısal _eq _ne _gt _gte _lt _lte _sort capacity_gte=50
Metin _contains _startswith _endswith _eq _ne _sort name_contains=umre
Boole _eq _ne _sort isArchive_eq=false
Tarih _eq _gt _gte _lt _lte _sort documentDate_gte=2026-01-01
Çoklu değer _in customerTypeIds_in=52,33
Sıralama _sort=asc|desc startDate_sort=desc

Örnekler

# Belirli tarih aralığında, kotası kalan, arşivlenmemiş turlar
GET /api/v2/Tours?startDate_gte=2026-08-01&startDate_lte=2026-09-30
    &remainingQuota_gt=0&isArchive_eq=false&startDate_sort=asc&take=50

# Yalnızca toplam sayı (satır dönmez)
GET /api/v2/Customers?count=true&isBlacklist_eq=true

# TCKN ile cari hareket araması, tur adına göre azalan
GET /api/v2/AccountingDebitCredits?customerNationalityNumber_eq=11111111110
    &documentDate_gte=2026-01-01&tourName_sort=desc&take=100

# Çoklu kimlik filtresi + özet
GET /api/v2/AccountingDebitCredits?accountingTagIds_in=1,2,7&includeSummary=true
    &summaryCurrencyId=2
Sayfalamayı doğru kurun. Toplam sayfa sayısını count alanından türetin: ceil(count / take). Büyük kümelerde skip arttıkça sorgu maliyeti yükselir; toplu veri çekiminde tarih aralığına bölerek ilerlemek skip=200000 gibi derin ofsetlerden daha hızlıdır.

Deterministik sayfalama

Sıralama vermezseniz sayfalar arasında satır tekrarlanabilir veya atlanabilir. Sayfalı gezinmede daima tekil bir alan üzerinden sıralayın — genelde id_sort=asc yeterlidir.

Dayanıklılık

Hata yönetimi

Durum kodları

Kod Anlam Ne yapmalı
200 / 204 Başarılı
400 Doğrulama veya iş kuralı hatası Gövdedeki alan adlarına göre isteği düzeltin. Tekrar denemek işe yaramaz.
401 Anahtarınızla ilgili: geçersiz, pasif, silinmiş, süresi dolmuş veya IP izinli değil Anahtarı, başlık adını ve çıkış IP'sini doğrulayın.
403 Uçla ilgili: anahtar geçerli ama o uç public API kapsamında değil Swagger'daki listeye bakın; farklı bir uç kullanın.
404 Kayıt bulunamadı Kimliği ve kapsamı (şirket) doğrulayın.
429 Limit aşıldı Kısa bekleme sonrası tekrar deneyin; istek hızını düşürün.
5xx Sunucu tarafı Üstel geri çekilme ile en fazla 3 deneme; yazma işlemlerinde çift kayıt riskine dikkat.
401 ile 403 ayrımı önemlidir. 401 anahtarınızla ilgilidir (geçersiz, süresi dolmuş, IP). 403 uçla ilgilidir (anahtarınız geçerli, ama o uç public API kapsamında değil). İki durumu ayrı loglayın; ilki rotasyon/altyapı, ikincisi kapsam sorunudur.

Hata gövdeleri

Kimlik doğrulama hataları ile iş katmanı hataları farklı gövde biçimi kullanır.

Durum HTTP Gövde
Anahtar bulunamadı, pasif veya silinmiş 401 {"error":"Unauthorized","message":"Invalid API key.","statusCode":401}
IP izinli değil 401 {"error":"Unauthorized","message":"Access denied from your IP address.","statusCode":401}
Başlık hiç gönderilmedi 401 {"error":"Unauthorized","message":"Unauthorized access.","statusCode":401}
Anahtarın süresi dolmuş 400 {"isSuccess":false,"message":"Api key süresi doldu."}
Doğrulama hatası 400 {"isSuccess":false,"message":"...","validationErrors":{"alan":["mesaj"]}}
Genel hata (ProblemDetails) 4xx/5xx {"type":"...","title":"...","status":400,"detail":"...","instance":"..."}

Yeniden deneme politikası

  • Tekrar deneyin: 429 (kısa bekleme sonrası), 500/502/503/504, ağ zaman aşımları. Üstel geri çekilme + jitter kullanın.
  • Tekrar denemeyin: 400, 401, 403, 404. Bunlar istek düzeltilmeden çözülmez.
  • Yazma uçlarında dikkat: API sunucu tarafı idempotency anahtarı taşımaz. Zaman aşımına uğrayan bir POST'u körlemesine tekrarlamak çift kayıt üretebilir. Önce ilgili liste ucunda kendi referans numaranızla (documentNumber, transactionNumber, voucherNo) arama yapıp kaydın oluşup oluşmadığını doğrulayın.
// Retry policy: only transient failures are retried.
func shouldRetry(status int) bool {
	return status == 429 || status >= 500
}

// Before retrying a write, verify the record was not already created.
// Search by your own reference: documentNumber / transactionNumber / voucherNo.
Kapasite

Limitler ve performans

Hız limiti

Konu Değer
Varsayılan limit Dakikada 100 istek — anahtar bazında, sabit pencere
Aşım davranışı 429 Too Many Requests. Kuyruk yoktur; fazla istek doğrudan reddedilir.
Retry-After Dönmez. Pencere bir dakikalık olduğundan kısa bir bekleme yeterlidir.
Kapsam Limit istemci IP'sine değil anahtara bağlıdır; aynı anahtarı birden çok sunucuda kullanmak limiti paylaştırır.

Hacim sınırları

Sınır
GET /AccountingDebitCreditsBeyGroup/GetLogoTransferDatas En fazla 10.000 kayıt; daha büyük sonuç kümeleri reddedilir. Tarih aralığını daraltın.
GET /Tours/active-tours Take en fazla 500.
GET /Airports/AutoCompleteSearch En fazla 20 sonuç.

Verimli kullanım

  • Referans verisini önbellekleyin. /AdminDatas/cache, /Places/from-cache, /Languages, /UsedCurrencies ve /Translates/locale-messages nadiren değişir; günde bir kez çekip kendi tarafınızda saklayın.
  • Delta çekin. Tam senkron yerine createdDate_gte / editedDate_gte ile son çalıştırmadan bu yana değişenleri alın.
  • Toplu uçları tercih edin. Gider, virman ve görsel yüklemeleri dizi kabul eder; N istek yerine tek istek gönderin.
  • Sadece sayıyı istiyorsanız count=true kullanın; satır taşımayın.
  • Toplu veri çekiminde istekler arasına gecikme koyun ve skip/take ile sayfalayın.
Uygulama

Uçtan uca senaryolar

B2B entegrasyonlarının büyük çoğunluğu aşağıdaki altı akıştan birine denk gelir. Her akış, çağrı sırası ve dikkat edilecek noktalarla birlikte verilmiştir.

1 · Tur kataloğu senkronu

Kendi web sitenizde veya acente panelinizde satılabilir turları göstermek için.

Sıra Çağrı Amaç
1 GET /Tours/sales Satışa açık turlar: aktif, arşivlenmemiş, kapatılmamış ve başlangıcı gelecekte olanlar. Uygun olduğunda bayi (dealer) bölgesine göre kapsanır.
2 GET /Tours/{id} Fiyat paketleri, güzergâh, otel konaklamaları, vize tipleri, çocuk yaş aralıkları ve hediyeler dahil tam detay.
3 GET /UsedCurrencies currencyId → sembol/kod eşlemesi.
4 GET /AdminDatas/cache?dataType=RoomType Oda tipi gibi sabit listelerin görünen adları.

Kendi web sitenizi besliyorsanız domain tabanlı uç daha pratiktir: GET /Tours/tourism-web?domain=example.com lisansı domainden çözer ve web'de gösterilmek üzere işaretlenmiş turları tam fiyat/güzergâh grafiğiyle döner. Kontenjan göstergeleri için GET /Tours/tourism-web/reservation-counts?domain=example.com.

curl -s "https://prod.turasistan.com/api/v2/Tours/sales?StartDate=2026-08-01&Category=umre" \
  -H "APIKEY: $TURASISTAN_API_KEY"
Kontenjan. remainingQuota anlık değerdir ve rezervasyon oluşturulduğunda değişir. Satış ekranında göstermeden önce tazeleyin; kontenjanı yalnızca kendi tarafınızda tuttuğunuz kopyaya güvenerek satmayın.

2 · Rezervasyon oluşturma

Turasistan'da rezervasyon TravelGroup (seyahat grubu) olarak modellenir: bir fatura müşterisi, bir tur ve bir veya daha fazla yolcu satırı.

Sıra Çağrı Amaç
1 GET /Tours/active-tours?Search=... Tur ve fiyat paketi kimliklerini bulun.
2 GET /Customers/autocomplete?search=... veya POST /Customers/search Var olan cariyi bulun; yoksa yolcu nesnesini gövde içinde göndererek oluşturabilirsiniz.
3 POST /TravelGroups/set-default-tour-options Turun varsayılan otel/uçuş/paket satırlarını forma doldurur.
4 POST /TravelGroups/calculate-amount?withDiscount=true Tutarı sunucuda hesaplatın. Fiyatı kendiniz hesaplamayın.
5 POST /TravelGroups Rezervasyonu kaydedin. En az bir yolcu satırı zorunludur.
6 GET /TravelGroups/{id} Kaydı ve voucher numarasını doğrulayın.
{
  "tourId": 4821,
  "dealerId": 3310,
  "tourReservationStatusId": 121,
  "invoiceCustomer": {
    "id": 0,
    "name": "Ahmet",
    "surname": "Yılmaz",
    "nationalityNumber": "11111111110",
    "gsm": "5321112233",
    "email": "ahmet@example.com"
  },
  "travelGroupCustomers": [
    {
      "tourId": 4821,
      "tourPricePackageId": 9912,
      "noBed": false,
      "customer": {
        "id": 0,
        "name": "Ahmet",
        "surname": "Yılmaz",
        "nationalityNumber": "11111111110",
        "birthDate": "1985-03-14T00:00:00",
        "genderId": 41,
        "passportNumber": "U01234567",
        "passportExpiryDate": "2030-06-01T00:00:00"
      },
      "travelGroupCustomer_VisaTypes": [ { "tourVisaTypeId": 77 } ],
      "travelGroupCustomer_TourExtras": [ { "tourTourExtraId": 512 } ]
    }
  ],
  "travelGroupHotelInfos": [],
  "travelGroupFlightInfos": []
}
  • tourPricePackageId, satır isDelete ile işaretlenmediği sürece zorunludur.
  • Var olan müşteri için customerId gönderin; yeni müşteri için customer nesnesini id: 0 ile gönderin.
  • mahramId / mahramTypeId, mahramControl açık turlarda gereklidir.
  • calculate-amount yanıtındaki totalAmount ve satır amount/discount değerlerini olduğu gibi kaydetme isteğine taşıyın.
Çift rezervasyon riski. POST /TravelGroups idempotent değildir. Zaman aşımı alırsanız yeniden göndermeden önce GET /TravelGroups?voucherNo_eq=... veya filterCustomerId ile kaydın oluşup oluşmadığını kontrol edin.

3 · Tahsilat ve ödeme kaydı

Ödeme aracına göre ayrı uçlar vardır; hepsi aynı borç/alacak gövdesini paylaşır.

Araç Ek alanlar
Kasa (nakit) POST /CaseDebitCredits
Banka POST /BankDebitCredits exchangeAccountId, exchangeDate
POS POST /PosDebitCredits POS hesabı accountCasePosId
Kredi kartı POST /CreditCardDebitCredits Kart hesabı
Çek POST /CheckDebitCredits checkDate (vade)
Senet POST /DebentureDebitCredits checkDate (vade)
Gider POST /Expenses Dizi kabul eder (toplu)
Cari virman POST /MoneyTransfers Dizi kabul eder; her satırda ya borç ya alacak
Fatura POST /Invoices Kalemler + vergi/indirim toplamları

Hesap (kasa/banka/POS) kimliklerini önce çözün:

GET /api/v2/AccountCasePoses?isActive_eq=true&companyId_eq=7&take=100
GET /api/v2/AccountCasePoses/my-account-cases?typeId=3
// POST /api/v2/CaseDebitCredits — cash collection
{
  "documentNumber": "THS-2026-000412",
  "transactionNumber": "ERP-88121",
  "documentDate": "2026-07-31T00:00:00+03:00",
  "description": "Umre programı 1. taksit",
  "isCollect": true,
  "debit": null,
  "credit": 15000.00,
  "currencyId": 1,
  "exchangeRate": 1,
  "accountCasePosId": 44,
  "customerId": 51204,
  "tourId": 4821,
  "companyId": 7,
  "isLegal": true,
  "tags": [ { "id": 0, "accountingTagId": 3 } ]
}
  • isCollect: true → tahsilat (makbuz); false → ödeme.
  • Bir satırda ya debit ya da credit dolu olur.
  • Yabancı para girişlerinde currencyId + exchangeRate gönderin; raporlama tutarını sunucunun hesaplaması için reportingCurrencyId bırakılabilir.
  • documentNumber kendi referansınızdır; mutabakat ve tekrar denemede bunu kullanın.

4 · Cari hareket ve bakiye

Muhasebe hareketleri tek bir ızgara ucundan okunur; özet blok filtrelenmiş küme için toplam borç, alacak ve bakiyeyi verir.

GET /api/v2/AccountingDebitCredits
    ?customerId_eq=51204
    &documentDate_gte=2026-01-01&documentDate_lte=2026-12-31
    &includeSummary=true&summaryCurrencyId=1
    &documentDate_sort=desc&take=100
İhtiyaç
Hareket detayı (müşteri, tur, ilişkili belge, etiketler) GET /AccountingDebitCredits/{id}
TCKN listesiyle müşteri özeti ve bakiye kırılımı GET /Customers/info?nationalityNumbers=111...,222...
Müşterinin kayıtlı olduğu turlar GET /Customers/{id}/tours
Kasa/banka/POS bakiyeleri GET /AccountCasePoses
Para birimi. Bakiyeler para birimi bazında tutulur (customerBalances). Tek bir toplam görmek istiyorsanız summaryCurrencyId verin; verilmezse temel para birimi kullanılır.

5 · Kur ve parite

Döner Kural
GET /ExChangeRates/rate?currencyId=&date=&exChangeType= Kur değeri exChangeType: ToBase (yabancı→temel), FromBase (temel→yabancı). Yerel para birimi istenirse 1 döner. Verilen tarihte veya öncesindeki en güncel kur kullanılır.
GET /ExChangeRates/parity?fromCurrencyId=&toCurrencyId=&date= Parite Temel para birimi üzerinden hesaplanır. Kaynak ve hedef aynıysa 1.
GET /ExChangeRates/calculate?amount=&fromCurrencyId=&toCurrencyId=&date= Çevrilen tutar Gerektiğinde temel para birimi üzerinden geçer. Aynı para biriminde orijinal tutarı döner. Hesaplanan tutar 0 çıkarsa 1 döner.
Son kural sürprizli olabilir: calculate ucu sıfır sonucu 1'e yuvarlar. Sıfır tutarları API'ye göndermeden kendi tarafınızda ayıklayın.
Dizin

Uç nokta dizini

Tüm public uçlar. Bir satırı açtığınızda solda parametreler ve yanıt tipi, sağda çalıştırılabilir kod örneği (cURL · Node.js · Python · C#) görünür. Genel ızgara parametreleri (skip, take, count, includeInactive, includeSummary) ve operatör sonekleri her liste ucunda geçerlidir — tekrar edilmemiştir.

Örneklerdeki gövdeler temsilîdir: sık kullanılan alanları gösterir, şemanın tamamı değildir. Alanların tam listesi için Swagger şemasına bakın. Anahtarı ortam değişkeninden okuyun (TURASISTAN_API_KEY); koda gömmeyin.

Şema

Veri modelleri

En sık kullanılan gövde ve yanıt nesneleri. Alan adları yanıtta ve filtrede birebir aynıdır.

Tur (TourResponseDto — liste)

Alan Tür Açıklama
id int Tur kimliği
name / tourCode string Görünen ad ve tur kodu
startDate / finishDate date-time Başlangıç ve bitiş
night / dayCount int Gece ve gün sayısı
capacity / customerCount / remainingQuota int Kapasite, kayıtlı yolcu, kalan kontenjan
currencyId / currencySymbol int / string Fiyat para birimi
isActive / isArchive / isClosed / isPastTour bool Durum bayrakları
hasVisa / hasAccommodation / mahramControl bool İçerik ve kural bayrakları
showWebSite / publishStartDate / publishFinishDate bool / date Web yayın penceresi
ownerCompanyId / ownerCompanyName int / string Sahip şirket
tourPricePackages[] dizi id, name, price, discountStudentPrice

Detay yanıtı (TourReadDto) bunlara ek olarak tourItineraries, tourHotelItineraries, tourTravelPackages, tourVisaTypes, tourChildAges, tourGifts ve tour_Dealers koleksiyonlarını taşır.

Müşteri (CustomerResponseDto — liste)

Alan Tür Açıklama
id / customerNumber int Kimlik ve atanmış müşteri numarası
name / surname / tradeName string Ad, soyad, ticari unvan
nationalityNumber / passportNumber string TCKN ve pasaport
passportExpiryDate / birthDate date-time Pasaport geçerlilik, doğum tarihi
gsm / phone / eMail string İletişim
isDealer / dealerId / dealerZoneId bool / int Bayi ilişkisi
buyer / seller bool Alıcı / satıcı rolü
isBlacklist / blacklistNote / isArchive bool / string Kara liste ve arşiv
taxNumber / taxOffice / accountingCode string Mali bilgiler
customerBalances[] dizi Para birimi bazında bakiye kırılımı
tourIds[] / customerCompanyTypeIds[] int[] Kayıtlı olduğu turlar, tedarikçi tipi bağları

Borç/alacak gövdesi (tahsilat–ödeme uçları)

Alan Tür Not
documentNumber / transactionNumber string Belge ve işlem referansı
documentDate date-time Belge tarihi
debit / credit double Biri dolu olur
isCollect bool true tahsilat, false ödeme
currencyId / exchangeRate int / double İşlem para birimi ve kur
reportingAmount / reportingCurrencyId double / int Raporlama para birimi karşılığı
calculatedAmount / calculatedCurrencyId double / int Gösterim para birimi karşılığı
accountCasePosId int Kasa / banka / POS hesabı
customerId / tourId / companyId int İlişkiler
accountingDCTypeId int Muhasebe işlem tipi (AdminDataType=AccountingDCType)
checkDate date-time Çek/senet vadesi
isLegal bool Resmî (kurumsal) kayıt
tags[] dizi { "id": 0, "accountingTagId": n }

Rezervasyon (TravelGroup)

Alan Tür Not
voucherNo string Rezervasyon voucher numarası
tourId / dealerId / companyId int Tur, bayi, şirket
invoiceCustomerId / invoiceCustomer int / nesne Fatura müşterisi; kimlik yoksa nesne gönderin
totalAmount / customerCount double / int Hesaplanan toplam, yolcu sayısı
tourReservationStatusId / reservationRecordTypeId int Durum ve kayıt tipi (sabit liste)
travelGroupCustomers[] dizi Yolcu satırları; en az bir tane zorunlu
travelGroupHotelInfos[] dizi Otel konaklama satırları
travelGroupFlightInfos[] dizi Uçuş / transfer bacakları
travelGroup_TravelPackages[] dizi Gezi paketi bağları

Yolcu satırı (travelGroupCustomers[]) başlıca alanları: customerId veya customer, tourPricePackageId, amount, discount, noBed, mahramId, mahramTypeId, togetherCustomerId, nearsideCode, vehicleNumber, giftId, notlar (flightDescription, roomingDescription, visaDescription, invoiceDescription) ve bağ dizileri (_VisaTypes, _TourExtras, _Discounts, customerVisaDocuments).

Sabitler

Sabit listeler

Kimlik değerleri tenant'a göre değişebildiğinden sayısal kimlikleri koda gömmeyin. Sabit listeleri ilgili uçtan çekip önbelleğe alın.

Nereden çekilir

Kaynak Kapsam
Sistem sabitleri GET /AdminDatas/cache?dataType={tip} Turasistan tarafından tanımlı, tüm tenant'larda ortak
Coğrafya GET /Places/from-cache?placeType=1, GET /Places/states?countryId= Ülke / il / ilçe / mahalle
Diller GET /Languages Aktif diller
Para birimleri GET /UsedCurrencies Kullanımdaki para birimleri
Metin anahtarları GET /Translates/locale-messages?startsWith=error. Hata mesajları ve arayüz etiketleri

dataType değerleri (AdminDataType)

Unit MartialStatus CompanyType TransportType Gender AccountCaseType MilitaryStatus HRStatus DisabledStatus Graduation HotelContractType HotelContractPriceCalculateMethod PricePreference CustomerTitle ItineraryType MofaAccountType SalaryPeriod WorkingMode HotelRequestStatus TaskList TypeByAge MahramType PassportStatus VisaSalesStatus FlyingType ReservationStatus MealBoardType TourReservationStatus RoomType Meal CustomerType AccountingDCType Education FormType DayType ChatType TourType OfferStatus DiscountType EmailType PassportType SaleType StokActionType StokType AccountActionType DibAccountType OperationType QueryType InvoiceType StokKind FlightPassengerType GearBoxType FuelType CustomerRecordType ReservationRecordType TypeOfModule ContractType Priority TourDiscountType VisaEntryType VehicleType PricingTiers RavzaPricingTiers RavzaAppointmentStatus CouponSaasAppFilterType RavzaGroupStatus ConversationStatus ConversationType HowFindUs Job

Ayrıca tenant'a özel listeler (SaasAppDataType) vardır: AccountingTag, DealerZone, RoomKind, VisaType, TourSeason, DocumentName, CustomerGroup, MealFood, LeavesType vb.

Kod içi sabitler

Enum Değerler Kullanım
PlaceType 1 Country · 2 State (il) · 3 District (ilçe) · 4 Neighborhood /Places, placeType parametresi
ExChangeType ToBase (1) · FromBase (2) /ExChangeRates/rate
TourPriceType Visa · Trip · Tour_Price · TourExtra · Discount · Flight · Highway Fiyat paketi türü
ItinearyPlaceEnum airport · city · supplier · place /Tours/autocomplete?searchType=
VisaAccountType None · MOFA · Diyanet Vize hesabı türü
VirtualPosTypeEnum Ziraat Sanal POS sağlayıcısı
Terimler

Alan sözlüğü

API'de sık geçen ve alan adından anlaşılmayan kavramlar.

Terim Anlamı
Tenant / saasAppId Firma (kiracı) kapsamı. Anahtardan çözülür; istekte göndermezsiniz.
Company / companyId Tenant altındaki tüzel şirket. Bir anahtar birden fazla şirketi kapsayabilir.
Customer (cari) Tek bir kayıt tipi yolcuyu, kurumsal müşteriyi, tedarikçiyi, oteli ve bayiyi temsil eder; roller isDealer, buyer, seller, customerTypeId ile ayrışır.
Dealer (bayi/acente) isDealer=true olan cari. dealerZoneId ile bölgeye bağlanır; tur görünürlüğü bölgeye göre kapsanabilir.
TravelGroup Rezervasyon. Bir tur + bir fatura müşterisi + yolcu satırları.
AccountCasePos Kasa, banka hesabı, kart veya POS. Türü accountCaseTypeId belirler.
Cari virman Cariler/hesaplar arası para aktarımı — /MoneyTransfers.
Çek / Senet Vadeli ödeme araçları; vade checkDate alanındadır.
isLegal Kaydın resmî (kurumsal) muhasebeye dahil olup olmadığı.
isCollect Tahsilat mı ödeme mi olduğunun ayrımı.
Mahram Refakatçi/mahrem ilişkisi. mahramControl açık turlarda yolcu satırında zorunludur.
Diyanet grubu Resmî hac/umre organizasyon grubu; diyanetGroupIds_in ile filtrelenir.
Voucher Rezervasyonun operasyonel belge numarası (voucherNo).
Logo Muhasebe programı entegrasyonu; logoRefCode aktarılan kaydın karşılığıdır.
Nearside code Otobüs/uçak oturma tarafı kodu.
Yayın

Canlıya geçiş kontrol listesi

Kimlik & erişim

Anahtar gizli anahtar deposunda · çıkış IP'si sabit ve listede · IPv6 varsa eklendi · anahtar bitiş tarihi takvime işlendi · rotasyon prosedürü yazılı.

Doğruluk

Sabit liste kimlikleri koda gömülmedi · para birimi ve kur alanları doldruluyor · tarihler ofsetli gönderiliyor · tutarlar sunucuda hesaplatılıyor.

Dayanıklılık

429 ve 5xx için geri çekilmeli tekrar deneme · 4xx tekrar denenmiyor · yazma öncesi referans numarasıyla mükerrer kontrolü · zaman aşımı 30 sn.

Verim

Referans verisi önbellekte · delta senkron kuruldu · sayfalama id_sort=asc ile deterministik · dakikada 100 istek bütçesi izleniyor.

Gözlemlenebilirlik

İstek zamanı (UTC+3), yol, durum kodu ve yanıt gövdesi loglanıyor · anahtar log'a yazılmıyor · 401/403 ayrı alarmlar.

Veri koruma

TCKN, pasaport ve görseller şifreli saklanıyor · gereksiz kişisel veri çekilmiyor · saklama süresi tanımlı.

Sık sorulanlar

SSS

Base URL /api/v2 ama sürüm v3 yazıyor, hangisi doğru?

Yol öneki /api/v2'dir ve tüm uçlar bunun altındadır. Spesifikasyon başlığındaki sürüm etiketi dokümantasyon sürümüdür; istek adresini değiştirmez.

Bir anahtarla birden fazla şirketin verisini görebilir miyim?

Evet, anahtar üretilirken seçilen şirketler kapsam olur. Ancak izolasyon ve sızıntı etkisini sınırlamak için şirket başına ayrı anahtar önerilir.

Var olan bir anahtarın IP listesini nasıl güncellerim?

Profil akışında güncelleme ucu yoktur. Yeni IP ile ikinci bir anahtar üretip geçiş yapın, sonra eskisini silin.

Bir uç 403 dönüyor, anahtarım geçerli.

403 ucun public API kapsamında olmadığını gösterir. Swagger'daki listeyi kontrol edin; benzer işi yapan bir public uç genellikle vardır (ör. dahili ızgara yerine /Tours/sales).

Fiyatı kendim hesaplayabilir miyim?

Hesaplamayın. İndirim, çocuk fiyatı, yataksız, vize ve ekstra kombinasyonları sunucuda çözülür. POST /TravelGroups/calculate-amount ile hesaplatın ve dönen değerleri kaydedin.

count alanı sayfadaki satır sayısıyla uyuşmuyor.

Beklenen davranış. count, filtreye uyan toplam satır sayısıdır; data ise geçerli sayfadır.

Sayfalar arasında aynı kaydı iki kez görüyorum.

Sıralama vermemişsiniz. id_sort=asc ekleyin.

Yeni bir müşteri oluşturduğumda customerNumber neden bazen boş?

Müşteri numarası atama, mükerrer numarayı önlemek için dağıtık kilit altında serileştirilir. Yanıtta gelmezse kaydı id ile tekrar okuyun.

Görselleri nasıl yüklerim?

Toplu uçlar Base64 kabul eder: /Customers/images/batch, /passport-images/batch, /residence-permit-images/batch, /vaccination-images/batch. Web formu uçları ise multipart/form-data kullanır.

Zaman aşımına uğrayan bir tahsilat isteğini tekrar gönderebilir miyim?

Önce GET /AccountingDebitCredits?documentNumber_eq=... ile kaydın oluşup oluşmadığını doğrulayın. API idempotency anahtarı taşımaz.

İletişim

Destek ve sürüm

Sorun bildirirken

Aşağıdaki bilgileri iletmek çözüm süresini belirgin şekilde kısaltır:

  • İstek zamanı (UTC+3) ve endpoint yolu
  • HTTP durum kodu ve yanıt gövdesi
  • İstek yapan sunucunun çıkış (egress) IP'si
  • Gönderilen gövdenin kişisel veri maskelenmiş hâli
Destek talebinde anahtarınızı paylaşmayın. Anahtarın yalnızca ilk 8 karakteri tanımlama için yeterlidir.

Sürüm politikası

Değişiklik Nasıl uygulanır
Yeni uç veya yeni opsiyonel alan Uyarısız eklenebilir. İstemciniz bilmediği alanları yok saymalıdır.
Alan kaldırma / anlam değişikliği Yeni yol öneki ile yayınlanır; mevcut /api/v2 davranışı korunur.
Sabit liste değerleri Değişebilir. Kimlikleri koda gömmeyin, ilgili uçtan okuyun.

Canlı ve her zaman güncel şema: Swagger arayüzü · docs.turasistan.com