ÜcretliYol API Dokümantasyonu

ÜcretliYol API iki farklı çalışma modelini destekler: (1) hazır rotayı ücretlendirme — rotayı siz oluşturursunuz, bize geometriyi ve araç bilgisini gönderirsiniz, biz otoyol/köprü/geçiş ücretini döneriz (POST /toll); (2) rota çizerek hesaplama — yalnızca başlangıç/varış noktası verirsiniz, rotayı sunucu tarafında biz çizeriz (POST /route). Hangi endpoint'i kullanırsanız kullanın, ücret her zaman gönderdiğiniz veya bizim çizdiğimiz gerçek güzergâh üzerinden hesaplanır. POST /toll bugün 7 ülkenin tümünü kapsar: Türkiye, Yunanistan, Bulgaristan, Arnavutluk, Kuzey Makedonya, Sırbistan ve Karadağ — hepsi aynı basit istek/yanıt modelinde. POST /classify de aynı 7 ülkenin tümü için sınıf üretir.

API anahtarı nasıl alınır? Üye girişi yapıp API Hizmeti sekmesinden talep oluşturun. Erişiminiz açıldıktan sonra kendi anahtarınızı oluşturabilirsiniz. 14 günlük deneme sonrası ücretli pakete geçmek için bizimle iletişime geçin.
📌 Sürüm notu (08.09.2026): POST /toll artık Arnavutluk (AL), Kuzey Makedonya (MK) ve Sırbistan (RS) için de gerçek ücret üretir — önceden yalnızca BG/GR/TR desteklenirdi. API Pro ve Enterprise paketleri artık varsayılan olarak tüm ülkelere erişebilir (bkz. Limitler bölümü). Entegrasyonunuzu sabit bir ülke listesine göre yazdıysanız, GET /countries'i kontrol ederek yeni ülkeleri otomatik yakalayabilirsiniz.
📌 Sürüm notu (10.09.2026): Karadağ (ME) eklendi. POST /toll, /site-hesapla ve /site-maliyet Karadağ için gerçek ücret üretir — ayrıntı için aşağıdaki "KARADAĞ" bölümüne bakın. GET /countries'te status: "development" olarak görünür (bu, canlı rota testiyle doğrulanana kadar geçici bir etikettir — capabilities.toll: true olduğu için uç nokta bugün de kullanılabilir).
📌 Sürüm notu (11.09.2026): POST /classify artık Karadağ (ME) için de sınıf üretir — Karadağ'ın resmi 5 kademeli tarife kategorisini (ME_CAT_1..ME_CAT_5) fiziksel araç profilinizden hesaplar (bkz. aşağıdaki "Sınıflandırma özeti" tablosu). GET /countries'te artık ME için de capabilities.classify: true görünür.
📌 Sürüm notu (11.09.2026): POST /toll'da Arnavutluk (AL), Kuzey Makedonya (MK), Sırbistan (RS) ve Karadağ (ME) için sinif alanı artık koşullu zorunlu — geçerli bir ülke-kendi kategorisi (me_kategori / rs_kategori / mk_kategori, Arnavutluk'ta al_kategori VE al_kategori5 ikisi birden) gönderdiğinizde sinif hiç göndermenize gerek yok. Sadece sinif gönderen mevcut entegrasyonlar hiç etkilenmez.

Kimlik Doğrulama

Her istekte API anahtarınızı X-API-Key başlığında gönderin:

X-API-Key: wt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Anahtarınız yalnızca talep sırasında seçtiğiniz (veya admin tarafından onaylanan) ülkeler için geçerlidir. İzinsiz ülke için istek atarsanız ulke_izni_yok hatası alırsınız. Anahtarınız ayrıca aktif olmalı, süresi dolmamış olmalı ve saatlik/günlük/aylık kullanım limitlerini aşmamış olmalıdır.

Bir hesapta yalnızca tek bir aktif anahtar bulunabilir. Panelden "Yeni Anahtar Oluştur" dediğinizde önceki anahtarınız hemen geçersiz olur ve yeni bir anahtar üretilir — bu bir anahtar yenileme işlemidir, sıfırdan başlamak değildir. Kalan saatlik/günlük/aylık kullanım hakkınız kaybolmaz: limitler anahtar bazında değil hesap bazında sayılır, bu yüzden yenileme kullanım sayaçlarınızı sıfırlamaz. Anahtarınızı iptal ederseniz hem panelde hem sunucuda anında devre dışı kalır.
⚠️ Yalnızca sunucudan sunucuya kullanım için tasarlanmıştır. API anahtarınızı tarayıcıda/mobil istemcide açığa çıkmayacak şekilde kendi sunucunuzda saklayın ve isteği oradan atın. Ayrıca CORS (tarayıcı Origin) yalnızca ucretliyol.com için açıktır — kendi domaininizden doğrudan tarayıcı JavaScript'i ile çağırmayı planlıyorsanız CORS hatası alırsınız; isteği kendi backend'inizden atın.

Uç Noktalar

Aşağıdaki iki uç nokta grubu için ana adres:

Ana adreshttps://api.ucretliyol.com
FormatJSON (istek ve yanıt, application/json; charset=utf-8)

Anahtar gerektirmeyen uç noktalar

Uç noktaYöntemAçıklama
/GETAPI adı, sürümü ve endpoint listesi
/statusGETVeritabanı ve rota servisinin sağlık durumu
/countriesGETÜlke listesi ve her ülkenin hangi uç noktaları desteklediği (aşağıda detaylı)

API anahtarı gerektiren uç noktalar

Uç noktaYöntemKullanım
/tollPOSTGönderdiğiniz rotayı ücretlendirir — bu dokümanın odağı. TR, GR, BG, AL, MK, RS, ME
/routePOSTİki nokta arasında rota çizer, Türkiye (ve rota Yunanistan'a giriyorsa Yunanistan) ücretini döner
/classifyPOSTTek bir fiziksel araç profilinden ülkelerin kendi sınıf karşılıklarını üretir

/site-hesapla ve /site-maliyet uç noktaları da teknik olarak aynı anahtarla çalışır (yakıt/lojistik maliyeti ve tüm ülkeleri tek istekte birden dönen zengin site ekranı için), ancak bunlar genel üçüncü taraf entegrasyonu için tasarlanmamıştır ve önceden haber verilmeden değişebilir. Artık /toll tek başına 7 ülkenin tümünü kapsadığı için kendi entegrasyonunuz için /toll, /route ve /classify kullanmanızı öneririz.

GET /countries — ülke ve yetenek listesi

Anahtar gerektirmez. Her ülke için genel olgunluk durumunu (status) ve o an gerçekten kullanılabilir uç noktaları (capabilities) döner. status: "development" o ülkenin hiç çalışmadığı anlamına gelmez — bir ülkenin bazı yetenekleri true iken durumu hâlâ "development" olabilir; hangi uç noktanın gerçekten kullanılabilir olduğuna her zaman capabilities alanına bakarak karar verin.

{
  "countries": [
    { "code": "TR", "name": "Türkiye", "status": "active",
      "capabilities": { "toll": true, "site_hesapla": true, "site_maliyet": true, "classify": true } },
    { "code": "GR", "name": "Greece", "status": "active",
      "capabilities": { "toll": true, "site_hesapla": true, "site_maliyet": true, "classify": true } },
    { "code": "BG", "name": "Bulgaria", "status": "development",
      "capabilities": { "toll": true, "site_hesapla": true, "site_maliyet": true, "classify": true } },
    { "code": "AL", "name": "Albania", "status": "active",
      "capabilities": { "toll": true, "site_hesapla": true, "site_maliyet": true, "classify": true } },
    { "code": "MK", "name": "North Macedonia", "status": "active",
      "capabilities": { "toll": true, "site_hesapla": true, "site_maliyet": true, "classify": true } },
    { "code": "RS", "name": "Serbia", "status": "active",
      "capabilities": { "toll": true, "site_hesapla": true, "site_maliyet": true, "classify": true } },
    { "code": "ME", "name": "Montenegro", "status": "development",
      "capabilities": { "toll": true, "site_hesapla": true, "site_maliyet": true, "classify": true } }
  ]
}
AlanAnlamı
capabilities.tolltrue ise o ülke POST /toll tarafından kabul edilir
capabilities.classifytrue ise POST /classify çıktısında o ülke için sınıf üretilebilir
capabilities.site_hesapla / site_maliyetÜcretliYol'un kendi iç formatlarında bu ülke için gerçek ücret üretildiği bilgisi (üçüncü taraf entegrasyonu için referans değildir)
plannedBu ülkede şu an hiçbiri aktif olmayan, ileride eklenmesi planlanan yetenekler için kullanılan opsiyonel bir alan (bugün 7 ülkenin de tüm yetenekleri aktif olduğundan şu an hiçbir ülkede görünmez — yeni bir ülke eklendiğinde canlıya alınana kadar bu alan üzerinden görünür olabilir)
Bu listeyi kodunuza sabit yazmak yerine /countries'i periyodik çağırıp kontrol etmenizi öneririz — yeni bir ülke eklendiğinde entegrasyonunuzu değiştirmeden fark edebilirsiniz. Romanya, Hırvatistan, Macaristan ve Bosna-Hersek üzerinde çalışıyoruz/yol haritamızdadır — bu ülkeler canlıya alındığında yine önce burada, capabilities.toll:true ile görünecektir.

GET /status — sağlık kontrolü

Anahtar gerektirmez. İzleme/uptime araçlarınızda kullanabileceğiniz basit bir sağlık uç noktasıdır; veritabanı ve rota servisine (Valhalla) erişilebildiğini doğrular.

GET /status

{ "status": "ok", "database": true, "valhalla": true }

database her zaman true'dur (veritabanına erişilemiyorsa API zaten 503 ile başka hiçbir isteği kabul etmez — bu yüzden /status'a kadar gelebiliyorsanız veritabanı zaten çalışıyordur). valhalla:false ise rota servisi geçici olarak yanıt vermiyor demektir; bu durumda /route, /site-hesapla ve /site-maliyet gibi sunucunun rota ÇİZDİĞİ uç noktalar etkilenebilir — /toll rota çizmediği için (siz gönderirsiniz) bundan etkilenmez.

Rota Gönderimi

Rotanızı iki biçimde gönderebilirsiniz:

koordinatlar (önerilen)

Rota noktalarınız [boylam, enlem] sırasıyla. Önce boylam!

"koordinatlar": [[27.9624, 43.2180], [27.9700, 43.2200], [28.5582, 43.7360]]
geometri (ileri seviye)

Google/Valhalla algoritmasıyla aynı yöntemle üretilmiş, precision 6 (1e6) encoded polyline.

"geometri": "quwdI..._encoded_polyline_p6_..."
⚠️ Google Directions/Maps API'sinden aldığınız overview_polyline veya steps[].polyline değerini doğrudan geometri alanına yapıştırmayın. Google'ın kendi API'si polyline'ı varsayılan olarak precision 5 (1e5) ile kodlar; bu API ise precision 6 (1e6) bekler. Precision uyuşmazlığı sessizce yanlış (tamamen alakasız) koordinatlara çözülür — hata vermez, sadece rota yanlış yerde eşleşir. Google'dan gelen bir rotayı kullanacaksanız ya kendi tarafınızda precision 6 ile yeniden kodlayın ya da (çok daha güvenli ve basit) rota noktalarını çözüp koordinatlar dizisi olarak gönderin — precision sorununu tamamen ortadan kaldırır.
Koordinatlar WGS84 ondalık derece formatındadır ve rota en az iki nokta içermelidir. Rotanızı ne kadar sık noktayla gönderirseniz hesap o kadar doğru olur — ideal: yaklaşık her 50–100 metrede bir nokta. Sistem gişe/segment kesişimini yakınlık toleransı OLMADAN, tam geometrik kesişimle arar; çok seyrek bir rota bir gişeyi veya köprü hattını kaçırabilir.
⚠️ koordinatlar ve geometri aynı istekte birlikte gönderilirse ülkeye göre hangisinin kullanılacağı değişebilir (Bulgaristan için gönderilen geometri, diğer ülkeler için koordinatlar kullanılır). İki alan aynı rotayı temsil etmiyorsa farklı ülkeler farklı sonuç üretebilir — tek istekte yalnızca birini göndermeniz en güvenlisidir.

Ondalık sayılarda JSON standardına uygun olarak nokta kullanın ("co2_sinifi": 1, 380.5 gibi); virgüllü ondalık string'ler ("380,5") güvenilir bir sözleşme değildir.

Kendi uygulamanızda oluşturduğunuz rotayı nasıl iletmelisiniz?

Firmanızın kendi navigasyon/harita altyapısı zaten bir rota üretiyorsa (Google Directions, Mapbox Directions, HERE, kendi OSRM/Valhalla sunucunuz, bir filo takip sisteminin GPS kayıtları vb.), POST /toll tam olarak bunun için tasarlanmıştır — API kendi rotasını ÇİZMEZ, sizin gönderdiğiniz güzergâhı ücretlendirir. Yapmanız gereken:

  1. Kendi rota kaynağınızdan (harita SDK'sı, yön API'si, GPS logu) rotanın izlediği gerçek yolu temsil eden, sıralı nokta listesini çıkarın — yalnızca başlangıç ve varış noktasını değil, aradaki tüm güzergâhı. Örneğin Google Directions'ın overview_polyline'ını çözüp (decode) elde ettiğiniz [enlem, boylam] noktalarını alın.
  2. Her noktayı [boylam, enlem] sırasına çevirin (çoğu harita SDK'sı [enlem, boylam] sırasıyla verir — ÜcretliYol'un beklediği sıra bunun tersidir, GeoJSON standardıyla aynıdır).
  3. Bu diziyi koordinatlar alanına, ücretini almak istediğiniz ülkenin araç bilgileriyle birlikte POST /toll'a gönderin.
  4. Rota birden fazla ülkeden geçiyorsa (ör. Türkiye'den çıkıp Yunanistan'a giren bir güzergâh), aynı koordinat dizisini her ülke için ayrı bir istekte, o ülkenin kendi ulke ve arac alanlarıyla gönderin — /toll tek istekte yalnızca tek bir ülkeyi ücretlendirir.
Kendi rotanız yoksa (yalnızca başlangıç/varış noktanız varsa) rotayı sizin yerinize sunucu tarafında biz çizeriz — bkz. aşağıdaki POST /route bölümü. Rota SİZDE varsa /toll, rota SİZDE yoksa /route kullanın; ikisini karıştırmayın.

Fiziksel Araç Profili

Ülkeler arasında tutarlı entegrasyon için sisteminizde aracın fiziksel bilgilerini tek bir profil olarak saklamanızı öneririz — bu profil özellikle /classify uç noktasında kullanılır:

AlanTipAçıklama
vehicle_typestringmotorcycle, car, van, bus, truck
axle_countintegerToplam aks/dingil sayısı
front_axle_height_cmnumberÖn aks yüksekliği (cm) — toplam araç yüksekliğiyle karıştırılmamalıdır
total_height_cmnumberToplam araç yüksekliği (cm)
max_weight_tonsnumberAzami ağırlık (ton)
seat_countintegerOtobüs/minibüs ayrımı için koltuk sayısı
emission_classstringeuro_3, euro_4, euro_5, euro_6 gibi
Önemli kural: Ücret sınıfını etkileyen bir fiziksel bilgiyi bilmiyorsanız tahmini bir değer göndermeyin — alanı boş bırakın ve gerekiyorsa kullanıcıdan isteyin. Bir ülkenin sınıf numarasını (örn. Türkiye sinif) başka bir ülkeye doğrudan kopyalamayın; her ülkenin kendi sınıflandırma mantığı vardır (bkz. aşağıda).

Para Birimi ve Döviz Kuru

Sonuç hangi para biriminde döner, bir ülkeden diğerine değişir. Aşağıdaki tablo hangi ülkenin yanıtında hangi para birimi alan(lar)ının bulunduğunu gösterir — bir "para birimi seçme" parametresi yoktur, her ülke kendi motorunun ürettiği alanların TAMAMINI her zaman döner; hangisini kullanacağınıza siz karar verirsiniz.

ÜlkeYerel para birimiYanıttaki alan(lar)TL karşılığı
Türkiye (TR)TRYtoll.tryzaten TL, ayrı alan yok
Yunanistan (GR)EURtoll.eurtoll.tl
Bulgaristan (BG)EURtoll.eurtoll.tl
Arnavutluk (AL)ALL (Lek)toll.eur ve toll.lek (ikisi birden, her zaman)toll.tl
Kuzey Makedonya (MK)MKD (Denar)toll.eur ve toll.denar (ikisi birden, her zaman)toll.tl
Sırbistan (RS)RSD (Dinar)toll.eur ve toll.rsd (ikisi birden, her zaman)toll.tl
Karadağ (ME)EURtoll.eurtoll.tl
EUR istemiyorsanız, sadece yerel para biriminde tutar mı istiyorsunuz? Arnavutluk, Kuzey Makedonya ve Sırbistan için yanıt her zaman hem EUR (toll.eur) hem de o ülkenin kendi yerel para birimini (toll.lek / toll.denar / toll.rsd) içerir — ekstra bir parametre göndermenize gerek yoktur, sadece ihtiyacınız olan alanı okuyun. Yunanistan, Bulgaristan ve Karadağ'da (Karadağ resmen euroize edilmiş bir ülkedir) yerel para birimi zaten EUR olduğu için ayrı bir "yerel para birimi" alanı yoktur (toll.eur her üçü için de zaten yereldir). Türkiye'de sonuç zaten TL'dir.
⚠️ Bir geçiş/tesis için eur alanı 0 ama yerel para birimi alanı 0'dan büyükse — bu bir hata değildir, o spesifik gişe/tesisin EUR tarifesi henüz veri tabanımıza girilmemiş demektir; o kayıt için yerel para birimi alanı (lek/denar/ rsd) geçerli/yetkili değerdir, EUR'u değil onu kullanın. Bu durumu fark ederseniz bize bildirin, ilgili tarife satırını tamamlarız.

Döviz kuru alanları (eur_kur, lek_kur, denar_kur, rsd_kur) o spesifik yanıtta TL karşılığını hesaplamak için kullanılan güncel kuru gösterir. Kur, Türkiye Cumhuriyet Merkez Bankası günlük bülteninden (EUR ve diğer majör para birimleri için) ve tamamlayıcı bir kaynaktan (ALL/MKD/RSD gibi TCMB bülteninde yer almayan para birimleri için çapraz kur olarak) periyodik güncellenir; taze bir kur alınamazsa sistem son bilinen geçerli kuru kullanır — tl alanı bu yüzden neredeyse hiçbir zaman boş kalmaz. Kendi tarafınızda kur önbelleklemeyin — her yanıtın kendi *_kur alanını okuyun, farklı isteklerde kur küçük farklarla değişebilir.

Ülkeye Göre Zorunlu Bilgiler ve Yanıt Alanları

POST /toll için her ülkenin ücret mantığı farklıdır. Hangi ülke için hesap istiyorsanız, o ülkenin gerektirdiği araç bilgilerini göndermelisiniz. Eksik bilgi gönderirseniz API hesaplama yapmaz; hangi alanın eksik olduğunu ve geçerli değerleri döner — böylece yanlış ücret hesaplanmaz.

BG Bulgaristan — mesafe bazlı ücretli yol (ağır araç)

Ücret, aracın kat ettiği gerçek yol mesafesine ve emisyon sınıfına göre hesaplanır.

AlanZorunluDeğerler
kategoriEvetkamyon_3_5_12, kamyon_12_2_3aks, kamyon_12_4aks, otobus_3_5_12, otobus_12
emisyonEveteuro_0_i_ii, euro_iii_iv, euro_v, euro_vi_eev, zev
co2_sinifiOpsiyonel1–4 (yalnız euro_vi_eev'de fark eder); zev için motor otomatik 5 kullanır; eksik/aralık dışı değer 1'e çekilir

Tonaj/aks bilgisi kategoriye gömülüdür — ayrıca göndermeyin. Kategori isimleri metin olarak birebir gönderilmelidir; Türkiye sinif numarası Bulgaristan'a gönderilmez.

// İstek
{
  "ulke": "BG",
  "koordinatlar": [[27.9624, 43.2180], [28.1000, 43.4000], [28.5582, 43.7360]],
  "arac": { "kategori": "kamyon_12_4aks", "emisyon": "euro_vi_eev", "co2_sinifi": 1 }
}

// Yanıt
{
  "ok": true,
  "ulke": "BG",
  "toll": {
    "eur": 22.96,
    "tl": 1287.72,
    "toll_km": 109.33,
    "ucretsiz_km": 1.29,
    "dagilim_km": { "otoyol_am": 109.33, "frc1": 0.0, "frc2": 0.0 },
    "birim_eur_km": [0.17, 0.15, 0.14]
  },
  "eur_kur": 56.08,
  "kaynak": "wayid"
}
Yanıt alanıAçıklama
toll.eur / toll.tlHesaplanan geçiş ücreti (EUR ve güncel kurla TL karşılığı)
toll.toll_km / toll.ucretsiz_kmÜcretli sınıflı yol ve ücretsiz yol kilometresi
toll.dagilim_kmOtoyol (AM/FRC0), FRC1, FRC2 kilometre kırılımı
toll.birim_eur_kmSabit sırayla [AM/FRC0, FRC1, FRC2] birim fiyat dizisi
eur_kurTL karşılığında kullanılan güncel EUR kuru
kaynakGenellikle wayid; servis erişilemezse segment veya eski_motor olabilir

Binek araçlar ve motosikletler için /toll BG'de yukarıdaki ağır araç kategorilerini kabul eder; binek araç vinyet modeli bu genel API sözleşmesinin bir parçası değildir.

GR Yunanistan — Otoyol + Köprü

Otoyol geçişleri için kategori zorunludur. Rota, çok kategorili özel bir tesisten (ör. Rio–Antirrio köprüsü) geçiyorsa, doğru kategoriyi belirleyebilmemiz için ek araç bilgileri gerekebilir.

AlanZorunluDeğerler / Açıklama
kategoriEvet1 = Motosiklet · 2 = Otomobil/binek · 3 = Minibüs/kamyonet/3-aks · 4 = Kamyon/TIR (4+ aks)
arac_tipiÖzel tesis varsabinek, motosiklet, kamyon, otobus — tesis veritabanının kanonik tipi
koltuk_sayisiOtobüs/minibüs iseGerçek koltuk sayısı — köprü ücreti buna göre değişebilir
aks_sayisiKamyon ise2, 3, 4, 5…
yukseklik_cmGerekebilirAracın toplam yüksekliği, santimetre (API içeride metreye çevirir — 3.80 göndermek "3,80 cm" olarak yorumlanır)
romork_varGerekebilir0 / 1
engelliOpsiyoneltrue / false — binek araç için engelli/mavi kart kategorisi talep eder

arac_tipi gönderilmezse sistem Türkiye sınıfından veya aks sayısından kaba bir tahmin üretir; doğru tesis kategorisi için açıkça göndermeniz önerilir.

// Otoyol isteği
{
  "ulke": "GR",
  "koordinatlar": [[21.3200, 38.3200], [21.7800, 38.2500]],
  "arac": { "kategori": 3 }
}

// Özel tesis (köprü) için tam araç profili
{
  "ulke": "GR",
  "koordinatlar": [[21.7600, 38.3000], [21.7800, 38.2500]],
  "arac": {
    "kategori": 3, "arac_tipi": "otobus", "koltuk_sayisi": 50,
    "aks_sayisi": 2, "yukseklik_cm": 380, "romork_var": 0
  }
}
⚠️ Önemli — Yunanistan köprüleri: Rio–Antirrio gibi bazı köprülerde ücret 9'a varan kategoriye ayrılır (araç tipi, koltuk sayısı, aks, yükseklik, römork durumuna göre) — bu liste tesis veritabanı içeriğine bağlıdır ve değişebilir, sabit varsaymayın. Eksik bilgi gönderirseniz aşağıdaki gibi bir yanıt alırsınız:
{
  "ok": false,
  "hata": "kopru_bilgi_eksik",
  "ulke": "GR",
  "eksik": ["koltuk_sayisi"],
  "mesaj": "Rio-Antirrio için aracınızın koltuk sayısı nedir.",
  "kopru": "Rio-Antirrio",
  "secenekler": [
    { "etiket": "Otobüs 20-50 koltuk", "deger": "20", "ucret": 18.0, "kategori_id": 101 },
    { "etiket": "Otobüs 51+ koltuk", "deger": "51", "ucret": 25.0, "kategori_id": 102 }
  ]
}

secenekler tesis veritabanındaki gerçek aktif kategorilerden üretilir. Akış: (1) eksik alanını kullanıcıya sorun, (2) gerçek fiziksel değeri arac içine koyun, (3) aynı isteği tam profille tekrar gönderin. secenekler[].ucret değerini kendi başınıza toplama eklemeyin — yetkili sonuç başarılı isteğin toll.koprular alanıdır.

Binek (otomobil) araçlar için sistem hiçbir zaman ek soru sormaz: engelli alanını göndermezseniz (veya bilinmiyorsa) otomatik olarak standart/engelsiz kategori uygulanır; gerçekten engelli/mavi kartlı bir araç için engelli:true gönderirseniz doğru (indirimli) kategori seçilir.

// Başarılı yanıt
{
  "ok": true, "ulke": "GR", "arac": { "kategori": 3 },
  "toll": {
    "eur": 46.5, "tl": 2607.12, "gecis_sayisi": 3,
    "gecisler": [
      { "otoyol": "Olympia Odos", "tip": "cift", "giris": "Gişe A", "cikis": "Gişe B", "normal": 28.5, "pass": 25.0 }
    ],
    "koprular": [
      { "tesis_id": 12, "tesis_adi": "Rio-Antirrio", "kategori": "Otobüs 20-50 koltuk", "ucret": 18.0, "para_birimi": "EUR", "ucret_eur": 18.0 }
    ]
  },
  "eur_kur": 56.067, "kaynak": "gr_kavsak"
}
gecisler[].tipAçıklama
singleTek nokta tarifesi
ciftGiriş ve çıkış gişesi eşleşmiş mesafe tarifesi
eksikYalnız tek normal gişe bulundu, giriş/çıkış çifti oluşmadı; ücret 0 döner

Ücretli geçiş bulunmayan bir rotada ok:true, gecis_sayisi:0, boş gecisler/koprular dizileri ve bilgilendirici bir mesaj döner — bu bir hata değildir.

TR Türkiye — Gişe (sınıf bazlı)

HGS/OGS gişe sınıfı zorunludur.

AlanZorunluDeğerler
sinifEvet1 = Otomobil · 2 = Ara sınıf/minibüs · 3 = 2-3 aks · 4 = 4-5 aks · 5 = 6+ aks · 6 = Motosiklet
// İstek
{
  "ulke": "TR",
  "koordinatlar": [[29.0000, 40.9500], [29.1000, 41.0000]],
  "arac": { "sinif": 1 }
}

// Yanıt
{
  "ok": true, "ulke": "TR", "arac": { "sinif": 1 },
  "toll": {
    "try": 185.5, "gise_sayisi": 2,
    "giseler": [
      { "tip": "GIRIS_CIKIS", "otoyol": "Otoyol adı", "giris_gise": "Giriş gişesi", "cikis_gise": "Çıkış gişesi", "ucret": 160.0, "aciklama": "" },
      { "tip": "TEK_NOKTA", "otoyol": "Köprü veya tünel", "giris_gise": "Geçiş adı", "cikis_gise": null, "ucret": 25.5, "aciklama": "" }
    ]
  },
  "kaynak": "tr_gise"
}
giseler[].tipAnlamıToplama dahil mi?
GIRIS_CIKISGiriş ve çıkış gişesi eşleştiEvet
TEK_NOKTATek nokta/köprü/tünel tarifesiEvet
TARIFE_YOKGişe kesişti fakat aktif tarife bulunamadıucret null döner — ücretsiz geçiş olarak yorumlamayın

Türkiye toplamı toll.try alanındadır, para birimi TL'dir.

AL Arnavutluk — Gişe/tesis (tek nokta)

Kategori Türkiye sinif'inden türetilir — motor, geçilen her gişe/tesisin kendi tarife satırının 4'lü mü 5'li şemalı mı olduğunu (ör. Llogara Tüneli gibi bağımsız tesisler) kendisi tespit edip doğru kategoriyi seçer. Elle seçim isterseniz al_kategori (1-4) ve/veya al_kategori5 (1-5) gönderebilirsiniz — ikisini de geçerli gönderirseniz sinif hiç gerekmez (rota hangi şemalı tesisten geçerse geçsin doğru kategori bu ikisinden doğrudan belirlenir; yalnızca biri gönderilirse — rota diğer şemadaki bir tesisten de geçebileceği için — sinif yine zorunludur).

AlanZorunluDeğerler
sinifŞartlı*1 = Otomobil · 2 = Ara sınıf/minibüs · 3 = 2-3 aks · 4 = 4-5 aks · 5 = 6+ aks · 6 = Motosiklet (Türkiye ile aynı sınıflandırma — motor buradan Arnavutluk'un kendi kategorisini türetir)
al_kategoriOpsiyonel1-4 — tesisin 4'lü şemalı tarifesinde elle kategori seçimi
al_kategori5Opsiyonel1-5 — tesisin 5'li şemalı tarifesinde (ör. Llogara Tüneli) elle kategori seçimi

* al_kategori VE al_kategori5 ikisi birden geçerli gönderilirse sinif zorunlu değildir; aksi halde (biri veya ikisi de eksikse) zorunludur.

// İstek
{
  "ulke": "AL",
  "koordinatlar": [[19.9200, 40.2700], [19.7300, 40.1900]],
  "arac": { "sinif": 3 }
}

// Yanıt
{
  "ok": true, "ulke": "AL",
  "arac": { "sinif": 3, "kullanilan_kategori": 2, "kategori_sema": 5 },
  "toll": {
    "eur": 8.0,
    "lek": 985.0,
    "tl": 448.8,
    "gecis_sayisi": 1,
    "gecisler": [
      { "tesis_adi": "Llogara Tüneli", "kategori": 2, "sema": 5, "eur": 8.0, "lek": 985.0 }
    ]
  },
  "eur_kur": 56.1, "lek_kur": 0.61, "kaynak": "al_gise"
}
Yanıt alanıAçıklama
toll.eur / toll.lekToplam ücret; her ikisi de her zaman doludur (bkz. yukarıdaki "Para Birimi ve Döviz Kuru")
toll.tlEUR varsa ondan, yoksa Lek'ten hesaplanan TL karşılığı
arac.kullanilan_kategori / kategori_semaMotorun otomatik seçtiği (veya elle override edilen) kategori ve şema — birden fazla geçiş farklı şemadan olabilir, ayrıntı için her gecisler[] öğesinin kendi alanına bakın
eur_kur / lek_kurTL karşılığında kullanılan güncel kurlar

Ücretli geçiş bulunmayan bir rotada ok:true, toll.eur/lek/tl:0, boş gecisler ve bilgilendirici bir mesaj döner — bu bir hata değildir.

MK Kuzey Makedonya — Gişe (tek nokta, tam eşleşme)

Kategori Türkiye sinif'inden türetilir (resmi aks + ön aks yüksekliği kuralı bugünkü araç profilinde henüz kullanılmıyor). Elle seçim isterseniz mk_kategori gönderebilirsiniz — geçerli bir mk_kategori gönderirseniz sinif hiç gerekmez.

AlanZorunluDeğerler
sinifŞartlı*1 = Otomobil · 2 = Ara sınıf/minibüs · 3 = 2-3 aks · 4 = 4-5 aks · 5 = 6+ aks · 6 = Motosiklet
mk_kategoriOpsiyonel1-5 (sayı) veya resmi Kuzey Makedonya plaka şeması "1a"/"1b"/"2"/"3"/"4" (metin)

* Geçerli bir mk_kategori gönderilirse sinif zorunlu değildir; aksi halde zorunludur.

// İstek
{
  "ulke": "MK",
  "koordinatlar": [[22.5479, 41.1352], [21.4233, 42.0151]],
  "arac": { "sinif": 3 }
}

// Yanıt
{
  "ok": true, "ulke": "MK",
  "arac": { "sinif": 3, "kullanilan_kategori": "2" },
  "toll": {
    "eur": 4.5,
    "denar": 277.0,
    "tl": 252.5,
    "gecis_sayisi": 2,
    "gecisler": [
      { "tesis_adi": "Kumanovo", "kategori": "2", "eur": 2.2, "denar": 135.0 },
      { "tesis_adi": "Miladinovci", "kategori": "2", "eur": 2.3, "denar": 142.0 }
    ]
  },
  "eur_kur": 56.1, "denar_kur": 0.91, "kaynak": "mk_gise"
}
Yanıt alanıAçıklama
toll.eur / toll.denarToplam ücret; her ikisi de her zaman doludur
toll.tlEUR varsa ondan, yoksa Denar'dan hesaplanan TL karşılığı
eur_kur / denar_kurTL karşılığında kullanılan güncel kurlar

Ücretli geçiş bulunmayan bir rotada ok:true, toll.eur/denar/tl:0, boş gecisler ve bilgilendirici bir mesaj döner — bu bir hata değildir.

RS Sırbistan — Gişe (giriş-çıkış, mesafe bazlı)

Kategori Türkiye sinif'inden türetilir (resmi aks + ön aks yüksekliği + römork kuralı bugünkü araç profilinde henüz kullanılmıyor). Elle seçim isterseniz rs_kategori gönderebilirsiniz — geçerli bir rs_kategori gönderirseniz sinif hiç gerekmez.

AlanZorunluDeğerler
sinifŞartlı*1 = Otomobil · 2 = Ara sınıf/minibüs · 3 = 2-3 aks · 4 = 4-5 aks · 5 = 6+ aks · 6 = Motosiklet
rs_kategoriOpsiyonel1-5 (sayı) veya resmi Sırbistan plaka şeması "1a"/"1"/"2"/"3"/"4" (metin)

* Geçerli bir rs_kategori gönderilirse sinif zorunlu değildir; aksi halde zorunludur.

// İstek
{
  "ulke": "RS",
  "koordinatlar": [[22.81005, 43.00236], [21.92940, 43.35077]],
  "arac": { "sinif": 1 }
}

// Yanıt
{
  "ok": true, "ulke": "RS",
  "arac": { "sinif": 1, "kullanilan_kategori": "1" },
  "toll": {
    "eur": 6.8,
    "rsd": 797.0,
    "tl": 381.5,
    "gecis_sayisi": 1,
    "gecisler": [
      { "giris": "Dimitrovgrad", "cikis": "Niš İstok", "kategori": "1", "eur": 6.8, "rsd": 797.0 }
    ]
  },
  "eur_kur": 56.1, "rsd_kur": 0.47, "kaynak": "rs_gise"
}
Yanıt alanıAçıklama
toll.eur / toll.rsdToplam ücret; her ikisi de her zaman doludur. EUR, Sırbistan'ın resmi/güvenilir kaynağıdır
toll.tlEUR varsa ondan, yoksa RSD'den hesaplanan TL karşılığı
eur_kur / rsd_kurTL karşılığında kullanılan güncel kurlar

Ücretli geçiş bulunmayan bir rotada ok:true, toll.eur/rsd/tl:0, boş gecisler ve bilgilendirici bir mesaj döner — bu bir hata değildir.

ME Karadağ — Gişe (tek nokta ve giriş-çıkış, karışık model)

Kategori Türkiye sinif'inden türetilir (resmi aks + ön aks yüksekliği + römork kuralı bugünkü araç profilinde henüz kullanılmıyor). Elle seçim isterseniz me_kategori gönderebilirsiniz — geçerli bir me_kategori gönderirseniz sinif hiç gerekmez. Karadağ zaten EUR bazlı bir ülke olduğu için yanıtta ayrı bir yerel para birimi alanı yoktur (bkz. yukarıdaki "Para Birimi ve Döviz Kuru" bölümü).

AlanZorunluDeğerler
sinifŞartlı*1 = Otomobil · 2 = Ara sınıf/minibüs · 3 = 2-3 aks · 4 = 4-5 aks · 5 = 6+ aks · 6 = Motosiklet
me_kategoriOpsiyonel1-5 (sayı veya metin) — Karadağ'ın resmi 5 kademeli tarife kategorisi

* Geçerli bir me_kategori gönderilirse sinif zorunlu değildir; aksi halde zorunludur.

// İstek
{
  "ulke": "ME",
  "koordinatlar": [[19.0904, 42.7731], [19.0187, 42.4304]],
  "arac": { "sinif": 1 }
}

// Yanıt
{
  "ok": true, "ulke": "ME",
  "arac": { "sinif": 1, "kullanilan_kategori": "1" },
  "toll": {
    "eur": 3.5,
    "tl": 196.4,
    "gecis_sayisi": 1,
    "gecisler": [
      { "otoyol": "Bar–Boljare", "tip": "cift", "giris": "Smokovac", "cikis": "Mateševo", "kategori": "1", "eur": 3.5 }
    ]
  },
  "eur_kur": 56.1, "kaynak": "me_gise"
}
Yanıt alanıAçıklama
toll.eurToplam ücret (EUR) — Karadağ'ın tek ve resmi para birimi
toll.tleur_kur ile hesaplanan TL karşılığı
eur_kurTL karşılığında kullanılan güncel kur
gecisler[].tipsingle: tek noktalı geçiş (ör. Sozina Tüneli) · cift: giriş-çıkış zonlu mesafe modeli (ör. Bar-Boljare otoyolunun zonları)

Ücretli geçiş bulunmayan bir rotada ok:true, toll.eur/tl:0, boş gecisler ve bilgilendirici bir mesaj döner — bu bir hata değildir.

AL/MK/RS/ME'de sinif, kategoriyi birebir kopyalamaz — gönderirseniz motor onu kendi resmi kategori şemasına (Arnavutluk 4'lü/5'li, Kuzey Makedonya 1a/1b/2/3/4, Sırbistan 1a/1/2/3/4, Karadağ 1-5) otomatik çevirir. Bu bir tahmindir ve gerçek yerel plaka sınıfıyla her zaman birebir örtüşmeyebilir. Aracınızın gerçek yerel kategorisini biliyorsanız (ör. filo yönetiminizde zaten kayıtlıysa), doğruluğu artıran al_kategori / al_kategori5 / mk_kategori / rs_kategori / me_kategori override alanlarını kullanın — geçerli bir override gönderdiğinizde sinif hiç gerekmez (Arnavutluk'ta yalnızca al_kategori VE al_kategori5 ikisi birden gönderilirse; diğer üç ülkede tek alan yeterlidir). Böylece o ülkenin kendi kategori sistemini bilen bir entegrasyon, Türkiye sınıflandırmasını hiç öğrenmek zorunda kalmaz.

POST /classify — evrensel araç sınıflandırma

Yukarıdaki "Fiziksel Araç Profili"ni gönderin, her ülkenin kendi sınıf karşılığını tek istekte alın. Bu, tek bir araç profilini ülke sınıflarına dönüştürmek isteyen entegrasyonlar için kullanışlıdır.

// İstek
{
  "vehicle_type": "truck", "axle_count": 5, "front_axle_height_cm": 135,
  "total_height_cm": 400, "max_weight_tons": 40, "seat_count": 2,
  "emission_class": "euro_5"
}

// Yanıt
{
  "vehicle": { "vehicle_type": "truck", "axle_count": 5, "front_axle_height_cm": 135,
               "total_height_cm": 400, "max_weight_tons": 40, "seat_count": 2, "emission_class": "euro_5" },
  "classes": {
    "TR": { "durum": "tamam", "sinif": "CLASS_4", "eksik": [] },
    "BG": { "durum": "tamam", "sinif": "BG_TRUCK_4AXLE_PLUS_EURO_5", "eksik": [] },
    "GR": { "durum": "tamam", "sinif": "GR_CAT_4", "eksik": [] },
    "AL": { "durum": "tamam", "sinif": "AL_CAT_5", "eksik": [] },
    "MK": { "durum": "tamam", "sinif": "MK_CAT_4", "eksik": [] },
    "RS": { "durum": "tamam", "sinif": "RS_CAT_4", "eksik": [] },
    "ME": { "durum": "tamam", "sinif": "ME_CAT_5", "eksik": [] }
  }
}

classes yalnızca API anahtarınızın izinli olduğu ülkeleri içerir. durum: "tamam" o ülke için sınıf üretilebildiğini, eksik listesi doluysa hangi alan(lar) olmadan sonucun güvenilir olmadığını gösterir.

ÜlkeSınıflandırma özeti
TürkiyeMotosiklet→CLASS_6 · 2 aks + ön aks ≥130cm→CLASS_2 · 2 aks + bilinmiyor/<130cm→CLASS_1 · 3 aks→CLASS_3 · 4-5 aks→CLASS_4 · 6+ aks→CLASS_5
BulgaristanMotosiklet→muaf · ≤3.5 ton→binek vinyet · >3.5 ton otobüs→BG_BUS_<EURO> · diğer ağır araç 2/3/4+ aks→BG_TRUCK_<N>AXLE_<EURO>. Emisyon bilinmiyorsa resolver EURO_6 varsayar — ücret hesabı için gerçek emisyonu mutlaka /toll'a açıkça gönderin.
YunanistanMotosiklet→GR_CAT_1 · ≤3.5 ton ve yükseklik ≤220cm→GR_CAT_2 · 2-3 aks→GR_CAT_3 · 4+ aks→GR_CAT_4
ArnavutlukMotosiklet→AL_CAT_1 · otomobil ≤3.5 ton→AL_CAT_2 · van/otobüs ≤23 koltuk→AL_CAT_3 · >23 koltuk veya 2 aks kamyon→AL_CAT_4 · diğer 3+ aks ağır araç→AL_CAT_5
Kuzey MakedonyaAğırlık ve yükseklik eşiklerinden resmi 1a/1b/2/3/4 plaka şemasına yaklaşık eşleme (net ayrım bilgisi eksikse ağırlık eşikleri kullanılır)
SırbistanAğırlık, yükseklik ve römork bilgisinden resmi 1a/1/2/3/4 plaka şemasına yaklaşık eşleme
KaradağMotosiklet→ME_CAT_1 · >3.5 ton, 2-3 aks→ME_CAT_4 · >3.5 ton, 4+ aks→ME_CAT_5 · ≤3.5 ton (veya bilinmiyor), 3+ aks→ME_CAT_3 · ≤3.5 ton, 2 aks, ön aks <130cm (veya toplam yükseklik ≤190cm)→ME_CAT_2 · ≤3.5 ton, 2 aks, ön aks ≥130cm (veya toplam yükseklik >190cm)→ME_CAT_3. Resmi Autoput Bar-Boljare 5 kademeli tarifesiyle birebir aynı kural (bkz. monteput.me/cjenovnik/).

Eksik alanları açıkça göndermek en doğru yöntemdir; geriye dönük uyumluluk için vehicle_type yoksa car, axle_count yoksa/2'den küçükse 2 kabul edilir — bu nedenle eksik profille alınan sonuç fiziksel gerçeği garanti etmez, üretim entegrasyonunuzda sınıflandırma öncesi tam profil zorunlu tutun.

POST /route — iki nokta arasında rota ve Türkiye ücreti

Hazır geometri göndermeden, yalnızca başlangıç/varış vererek rota oluşturmak ve Türkiye gişe ücretini hesaplamak için kullanılır. Kendi rotanız yoksa (yalnızca iki koordinatınız varsa) bu endpoint tam size göre — rotayı Valhalla/OSRM ile biz çizeriz.

// İstek
{
  "from": { "lat": 41.0082, "lon": 28.9784 },
  "to":   { "lat": 38.4237, "lon": 27.1428 },
  "vehicle_class": 1
}

// Yanıt
{
  "distance_km": 485.2, "duration_min": 321, "vehicle_class": 1,
  "tolls": [
    { "tip": "GIRIS_CIKIS", "otoyol": "Otoyol adı", "giris_gise": "Giriş", "cikis_gise": "Çıkış", "ucret": 250.0, "aciklama": "" }
  ],
  "total": 250.0, "currency": "TRY"
}

vehicle_class 1–6 aralığına sıkıştırılır; gönderilmezse 1 kullanılır. Rota otomobil (auto) profiliyle çizilir — ağır araç güzergah kısıtlarını yansıtmaz, bu yüzden ağır araçlar için gerçek rotanızı kendiniz oluşturup /toll'a göndermeniz daha doğru sonuç verir. Anahtarınızın GR izni varsa ve rota Yunanistan'a giriyorsa yanıta ek olarak bir greece bölümü eklenebilir; anahtarınızın TR izni yoksa tr_izin_yok:true dönebilir. /route yalnızca Türkiye (+opsiyonel Yunanistan) ücretlendirir — Bulgaristan/Arnavutluk/Kuzey Makedonya/Sırbistan için rotanızı kendiniz oluşturup ülke başına ayrı /toll isteği atmanız gerekir.

Kod Örnekleri

curl -X POST https://api.ucretliyol.com/toll \
  -H "X-API-Key: SIZIN_ANAHTARINIZ" \
  -H "Content-Type: application/json" \
  -d '{
    "ulke": "BG",
    "koordinatlar": [[27.9624,43.2180],[28.5582,43.7360]],
    "arac": {"kategori":"kamyon_12_4aks","emisyon":"euro_vi_eev","co2_sinifi":1}
  }'

Java: kendi rotanızı gönderen yeniden kullanılabilir bir istemci

Aşağıdaki sınıf, kendi navigasyon/harita altyapınızın (Google Directions, Mapbox, HERE, kendi OSRM/Valhalla sunucunuz, filo GPS logunuz vb.) ürettiği rotayı alıp yedi ülkenin herhangi biri için ücretlendiren, yeniden kullanılabilir bir örnektir. arac haritasını ülkeye göre siz doldurursunuz (yukarıdaki "Ülkeye Göre Zorunlu Bilgiler" tablolarına bakın).

import org.json.JSONArray;
import org.json.JSONObject;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.Map;

public class UcretliYolClient {

    private final String baseUrl;
    private final String apiKey;
    private final HttpClient http = HttpClient.newHttpClient();

    public UcretliYolClient(String baseUrl, String apiKey) {
        this.baseUrl = baseUrl;
        this.apiKey = apiKey;
    }

    /**
     * Kendi uygulamanızda ürettiğiniz rotayı ücretlendirir. "rota" parametresi
     * rota üzerindeki NOKTALARIN SIRALI listesidir — yalnızca başlangıç/bitiş
     * DEĞİL, rotanın gerçekten izlediği yoldur. Her nokta {boylam, enlem}
     * sırasıyla (dikkat: çoğu harita SDK'sı enlem/boylam sırasıyla verir, bu
     * API'nin beklediği sıra TERSİDİR).
     *
     * @param ulke "TR" | "GR" | "BG" | "AL" | "MK" | "RS"
     * @param rota Rota noktaları, her eleman {boylam, enlem}
     * @param arac Ülkeye göre değişen araç bilgisi (örn. TR icin "sinif",
     *             BG icin "kategori"+"emisyon")
     */
    public JSONObject hesaplaToll(String ulke, List rota, Map arac) throws Exception {
        JSONArray koordinatlar = new JSONArray();
        for (double[] nokta : rota) {
            koordinatlar.put(new JSONArray(new double[]{nokta[0], nokta[1]}));
        }

        JSONObject govde = new JSONObject()
                .put("ulke", ulke)
                .put("koordinatlar", koordinatlar)
                .put("arac", new JSONObject(arac));

        HttpRequest istek = HttpRequest.newBuilder()
                .uri(URI.create(baseUrl + "/toll"))
                .header("Content-Type", "application/json")
                .header("X-API-Key", apiKey)
                .POST(HttpRequest.BodyPublishers.ofString(govde.toString()))
                .build();

        HttpResponse yanit = http.send(istek, HttpResponse.BodyHandlers.ofString());
        JSONObject sonuc = new JSONObject(yanit.body());

        if (yanit.statusCode() != 200 || !sonuc.optBoolean("ok", false)) {
            // 400/401/403/422 gibi durumlarda sonuc icinde "hata"/"eksik"/"gecerli_degerler"
            // alanlarini kontrol edin — korlemesine tekrar denemeyin (bkz. HTTP Durum Kodlari).
            throw new RuntimeException("ÜcretliYol hatası (" + yanit.statusCode() + "): " + sonuc);
        }
        return sonuc;
    }
}

// ---- Kullanım ----
UcretliYolClient istemci = new UcretliYolClient("https://api.ucretliyol.com", "SIZIN_ANAHTARINIZ");

// Kendi navigasyon SDK'nizden gelen, rotanın izlediği yolu temsil eden noktalar
List rota = List.of(
    new double[]{27.9624, 43.2180},
    new double[]{28.1000, 43.4000},
    new double[]{28.5582, 43.7360}
);

// TR — sinif zorunlu
JSONObject tr = istemci.hesaplaToll("TR", rota, Map.of("sinif", 1));

// GR — kategori zorunlu (1-4)
JSONObject gr = istemci.hesaplaToll("GR", rota, Map.of("kategori", 3));

// BG — kategori + emisyon zorunlu
JSONObject bg = istemci.hesaplaToll("BG", rota, Map.of(
    "kategori", "kamyon_12_4aks", "emisyon", "euro_vi_eev", "co2_sinifi", 1));

// AL — sinif zorunlu; yanıt EUR VE Lek'i her zaman birlikte döner
JSONObject al = istemci.hesaplaToll("AL", rota, Map.of("sinif", 3));
System.out.println("Arnavutluk: " + al.getJSONObject("toll").getDouble("eur") + " EUR / "
    + al.getJSONObject("toll").getDouble("lek") + " Lek");

// MK — sinif zorunlu; yanıt EUR VE Denar'ı her zaman birlikte döner
JSONObject mk = istemci.hesaplaToll("MK", rota, Map.of("sinif", 3));

// RS — sinif zorunlu; yanıt EUR VE RSD'yi her zaman birlikte döner
JSONObject rs = istemci.hesaplaToll("RS", rota, Map.of("sinif", 1));

HTTP Durum Kodları ve Hata Yönetimi

HTTPAnlamıNe yapmalı
200Başarılı hesap (ücretli geçiş bulunamamış da olabilir)Yanıt alanlarını kontrol edin
204CORS OPTIONS ön isteğiGövde beklemeyin
400İstek/alan/kategori/geometri hatasıhata, eksik, gecerli_degerler alanlarını gösterin
401API anahtarı eksik/geçersizAnahtarı kontrol edin
403Ülke yetkisi yokAnahtara ülke izni tanımlatın
404Endpoint veya rota bulunamadıURL'yi ve rota durumunu kontrol edin
422Ücret motoru hesaplayamadıLogladıktan sonra isteği körlemesine tekrarlamayın
429Saatlik/günlük/aylık limit dolduİlgili pencere sıfırlanana kadar bekleyin
502Rota servisi yanıt vermiyorKontrollü backoff ile tekrar deneyin
503Veritabanı/servis geçici kullanım dışıKontrollü backoff ile tekrar deneyin
⚠️ Yanıt gövdesinin şekli endpoint'e göre değişir — hepsi aynı sözleşmeyi paylaşmaz: /toll ve /classify hata durumunda {"ok":false,"hata":"..."} döner; /route yalnızca {"error":"..."} döner (ok veya hata alanı YOKTUR); /site-hesapla ve /site-maliyet yalnızca {"hata":"..."} döner (ok veya error alanı YOKTUR). Hata ayrıştırma kodunuzu buna göre yazın — tek bir endpoint'e göre yazıp diğerlerine kopyalamayın.
KodhataAnlamı
400eksik_parametreÜlke için zorunlu alan eksik (yanıtta eksik alanlar + geçerli değerler)
400kopru_bilgi_eksikÇok kategorili köprü için araç detayı eksik (koltuk/aks/yükseklik)
400gecersiz_kategoriKategori değeri geçersiz
400gecersiz_sinifSınıf 1–6 aralığı dışında
400gecersiz_emisyonEmisyon değeri geçersiz
400geometri_eksikNe koordinat ne polyline gönderildi
400gecersiz_ulkeulke alanı TR/GR/BG/AL/MK/RS dışında bir değer
401Geçersiz veya eksik API anahtarı
403ulke_izni_yokAnahtarınız bu ülke için yetkili değil
422hesaplama_hatasiMotor/harita/veri hesabı başarısız oldu
429Saatlik istek limitiniz doldu
429gunluk_limit_asildiGünlük istek limitiniz doldu
429aylik_limit_asildiAylık istek limitiniz doldu
{
  "ok": false,
  "hata": "eksik_parametre",
  "ulke": "BG",
  "eksik": ["kategori", "emisyon"],
  "mesaj": "Bulgaristan hesabı için bu alanlar zorunludur.",
  "gecerli_degerler": {
    "kategori": ["kamyon_3_5_12", "kamyon_12_2_3aks", "kamyon_12_4aks", "otobus_3_5_12", "otobus_12"],
    "emisyon": ["euro_0_i_ii", "euro_iii_iv", "euro_v", "euro_vi_eev", "zev"]
  }
}
Hata ile "sıfır ücret" arasındaki fark: HTTP 400/401/403/422/5xx işlemin başarısız olduğu anlamına gelir. HTTP 200 + ok:true + eur:0 ise rota üzerinde ücret bulunamamış olabilir (hata değildir). Türkiye'de giseler[].tip = "TARIFE_YOK" geçişi tespit edilmiş ama tarifesi tanımlanmamış demektir — ücretsiz geçiş olarak yorumlamayın. Yunanistan'da gecis_sayisi:0 ücretli geçiş bulunmadığını belirten başarılı bir sonuçtur.

Tekrar deneme stratejisi: 400/401/403/422 için tekrar denemeyin (istek gövdesini düzeltmeden tekrar etmek aynı hatayı verir); 429 için ilgili pencere sıfırlanmadan tekrar denemeyin; yalnızca 502/503 ve ağ zaman aşımlarında kontrollü (exponential) backoff ile tekrar deneyin.

Limitler

Her API anahtarı üç bağımsız pencereyle sınırlıdır: saatlik, günlük ve aylık (son 30 gün, takvim ayı değil). Herhangi biri dolarsa 429 alırsınız; yanıttaki hata alanı hangi pencerenin dolduğunu belirtir.

PaketSaatlikGünlükAylıkErişilebilir ülkeler
API Deneme (ücretsiz)1001003.000Yalnız TR
API Basic1.500— (tavan yok)50.000TR, GR (varsayılan — talep formunda farklı ülkeler de seçilebilir, onay admine bağlıdır)
API Pro6.000— (tavan yok)500.000Tüm ülkeler (TR, GR, BG, AL, MK, RS, ME)
API Enterprise25.000— (tavan yok)5.000.000Tüm ülkeler (TR, GR, BG, AL, MK, RS, ME)

Ücretli paketlerde aylık limit dolunca, paketinizde seçtiğiniz tercihe göre (talep formunda belirlersiniz) hizmet ya durur ya da aşım ücretiyle devam eder. Ücretsiz deneme paketinde limit dolunca hizmet her zaman durur. Anahtarınızı yenilerseniz bu sayaçlar sıfırlanmaz — limitler hesap bazında sayılır (yukarıdaki Kimlik Doğrulama bölümüne bakın). Limit yükseltme için iletişime geçin.

Önerilen Entegrasyon Akışı

  1. Araç kaydı: Her aracınızı yukarıdaki "Fiziksel Araç Profili" alanlarıyla kendi sisteminizde saklayın; ülke sınıflarını sabit bir tahminle değil, gerçek fiziksel veriden üretin.
  2. /classify ile kontrol: Tam profili gönderip her ülke için durum: "tamam" döndüğünü doğrulayın; eksik listesi doluysa o ülke için sınıf güvenilir değildir.
  3. Ülke bazlı /toll isteği: Aynı rotayı her ülke için ayrı istek gövdesiyle, o ülkenin kendi alanlarıyla gönderin (TR/AL/MK/RS→sinif, GR→kategori+gerekiyorsa köprü alanları, BG→kategori+emisyon+co2_sinifi). Bir ülkeden gelen kategori değerini diğerine kopyalamayın; AL/MK/RS'de gerçek yerel kategoriyi biliyorsanız al_kategori/mk_kategori/rs_kategori override alanlarıyla belirtin.
  4. Yanıtı yorumlama: Önce HTTP durumunu, sonra hata/eksik alanlarını kontrol edin; toplamı ülkenin kendi para birimi alanından okuyun (bkz. "Para Birimi ve Döviz Kuru"), TL karşılıklarını yalnızca bilgi amaçlı kullanın; TARIFE_YOK kayıtlarını ücretsiz saymayın; kopru_bilgi_eksik durumunda kullanıcıdan tahmin değil gerçek fiziksel veri isteyin.
  5. Tekrar deneme: Yalnızca 502, 503 ve ağ zaman aşımlarında, exponential backoff ile tekrar deneyin; 400/401/403/422 ve limit dolu 429 için tekrar denemeyin. API'de yazılı kullanım kaydı tutulduğundan, bir isteğin zaman aşımı sonrası işlenip işlenmediğinden emin değilseniz körlemesine tekrar göndermeyin.

Sık Sorulan Sorular

Bulgaristan'da geçiş ücreti, aracın kat ettiği gerçek yol mesafesine göre hesaplanır (Türkiye ve Yunanistan'daki sabit gişe/köprü sisteminden farklı olarak). ÜcretliYol bu mesafeyi kendi bağımsız motoruyla ve gerçek GPS koordinatları üzerinden ölçer — yolu düz çizgilerle tahmin etmez, gerçek geometrisini takip eder. Bulgaristan'ın resmi sistemi bazı durumlarda güzergâhı farklı bölümleyebilir, bazı bağlantı/kavşak noktalarını farklı değerlendirebilir ya da mesafeyi basitleştirebilir. Bu nedenle iki sonuç santim santim aynı olmayabilir; ancak fark son derece küçüktür ve bizim değerimiz gerçek yol uzunluğuna dayanır. Türkiye ve Yunanistan gişeli/sabit ücretli sistem kullandığından orada böyle bir fark oluşmaz — sonuçlar birebir eşleşir.

Rota kaynağınız ne olursa olsun (Google Directions, Mapbox, HERE, kendi OSRM/Valhalla sunucunuz, GPS logu), rotanın izlediği yolu temsil eden sıralı nokta listesini çıkarıp koordinatlar alanına [boylam, enlem] sırasıyla gönderin — sadece başlangıç/bitiş değil, aradaki tüm güzergâhı. Detaylı adımlar ve bir Java örneği için yukarıdaki "Kendi uygulamanızda oluşturduğunuz rotayı nasıl iletmelisiniz?" ve "Kod Örnekleri" bölümlerine bakın. Kendi rotanız yoksa /route kullanın, rotayı biz çizeriz.

[boylam, enlem] — yani önce boylam (longitude), sonra enlem (latitude). Örnek: [27.9624, 43.2180]. Bu sıra GeoJSON standardıyla aynıdır ama çoğu harita SDK'sının (Google, Mapbox vb.) size verdiği [enlem, boylam] sırasının TERSİDİR — dönüştürmeyi unutmayın. Ters gönderirseniz rota yanlış yerde eşleşir, hata dönmez.

POST /toll bugün 7 ülkenin tamamını destekler: Türkiye (TR), Yunanistan (GR), Bulgaristan (BG), Arnavutluk (AL), Kuzey Makedonya (MK), Sırbistan (RS), Karadağ (ME). POST /classify de aynı 7 ülkenin tamamı için sınıf üretir. Bunu sabit varsaymak yerine GET /countries'in capabilities.toll/capabilities.classify alanlarını kontrol etmenizi öneririz — yeni bir ülke veya yetenek eklendiğinde otomatik fark edersiniz (Romanya, Hırvatistan, Macaristan ve Bosna-Hersek üzerinde çalışıyoruz). Her istekte ulke alanıyla belirtirsiniz; anahtarınız yalnızca izinli olduğu ülkeler için çalışır.

Ekstra bir parametre göndermenize gerek yok. Arnavutluk, Kuzey Makedonya ve Sırbistan için yanıt her zaman hem EUR hem de o ülkenin yerel para birimini birlikte içerir — toll.lek (Arnavutluk), toll.denar (Kuzey Makedonya) veya toll.rsd (Sırbistan) alanını doğrudan okuyun, EUR'u görmezden gelebilirsiniz. Yunanistan ve Bulgaristan'da yerel para birimi zaten EUR'dur. Türkiye'de sonuç zaten TL'dir. Ayrıntılar için yukarıdaki "Para Birimi ve Döviz Kuru" bölümüne bakın.

Hayır — toll.eur/toll.lek alanları API sözleşmesinde HER ZAMAN mevcuttur, motor asla bu alanları eksik bırakmaz. Eğer belirli bir gişe/tesis için EUR değeri 0 ama Lek değeri 0'dan büyükse, bu o spesifik tarife satırının EUR karşılığının veri tabanımıza henüz girilmediği anlamına gelir — motor veya API'nin bir kusuru değil, o tek kayda özel bir veri eksikliğidir. Böyle bir durumda Lek değeri geçerli/yetkili tutardır, onu kullanın; bize bildirirseniz ilgili tarifeyi tamamlarız.

/toll — rotayı SİZ oluşturursunuz, biz yalnızca ücretlendiririz (API rota çizmez), 7 ülkenin tamamı. /route — yalnızca başlangıç/varış koordinatı verirsiniz, rotayı biz çizeriz; yalnızca Türkiye (+opsiyonel Yunanistan) ücretini döner. /classify — rota gerektirmez; 7 ülkenin tamamı için kendi sınıf karşılığını tek bir fiziksel araç profilinden üretir, genellikle /toll'a göndereceğiniz alanı belirlemek için ön adım olarak kullanılır.

Hayır. Panelden yeni anahtar oluşturduğunuzda önceki anahtarınız hemen geçersiz olur (bir hesapta yalnızca tek aktif anahtar bulunabilir), ama kalan saatlik/günlük/aylık kullanım hakkınız kaybolmaz — limitler anahtar değil hesap bazında sayılır. Yani yenileme, sınırınızı sıfırlamanın bir yolu değildir.

Anahtarınız, başvuru sırasında seçtiğiniz (veya admin onayıyla eklenen) ülkelerle sınırlıdır. Kapsam dışı bir ülke için istek atarsanız ulke_izni_yok hatası alırsınız. API Pro ve Enterprise paketleri varsayılan olarak tüm ülkelere erişebilir. Ek ülke için bizimle iletişime geçebilirsiniz.

Deneme süresi bitince anahtarınız pasif olur. Kesintisiz kullanım, daha yüksek istek limiti ve ek ülkeler için ücretli pakete geçmeniz gerekir — iletişime geçin, anahtarınızı yeniden aktifleştirelim.

Üç bağımsız limit vardır: saatlik, günlük ve aylık (bkz. yukarıdaki Limitler tablosu). Hangisi dolarsa 429 yanıtı ve ilgili hata kodunu (gunluk_limit_asildi / aylik_limit_asildi) alırsınız; ilgili pencere sıfırlanınca istekleriniz tekrar kabul edilir. Ücretsiz deneme paketinde asıl sınırlayıcı günlük 100 istek hakkıdır. Yoğun kullanım için limit yükseltme talep edebilirsiniz.

Rio–Antirrio gibi bazı Yunan köprülerinde ücret, araç tipine, koltuk sayısına, aks sayısına, yüksekliğe ve römork durumuna göre 9'a varan kategoriye ayrılır. Doğru köprü ücretini hesaplayabilmemiz için bu bilgileri göndermeniz gerekir; eksikse kopru_bilgi_eksik yanıtıyla hangi alanın gerektiğini, gerçek aktif kategorileri (secenekler) ile birlikte bildiririz. İstisna: binek (otomobil) araçlar için hiçbir zaman ek soru sorulmaz — engelli alanını göndermezseniz otomatik olarak standart kategori uygulanır, yalnızca gerçekten engelli/mavi kartlı bir araç için engelli:true göndermeniz yeterlidir.

Ne kadar sık nokta gönderirseniz mesafe ölçümü o kadar doğru olur. İdeal olarak yaklaşık her 50–100 metrede bir nokta önerilir. Çok seyrek noktalar (örn. sadece dönüşler) mesafeyi olduğundan kısa gösterebilir.

Ülkeye göre değişir: Türkiye→TL, Yunanistan/Bulgaristan→EUR (+ TL karşılığı), Arnavutluk/Kuzey Makedonya/Sırbistan→hem EUR hem yerel para birimi (Lek/Denar/RSD, ikisi de her zaman birlikte, + TL karşılığı). Bir "para birimi seçme" parametresi yoktur — her zaman ilgili ülkenin ürettiği tüm alanları alırsınız. Güncel döviz kuru her yanıtta eur_kur (ve varsa lek_kur/denar_kur/rsd_kur) alanında verilir. Tam tablo için yukarıdaki "Para Birimi ve Döviz Kuru" bölümüne bakın.

Ücretli pakete geçiş: Deneme sürenizde tüm özellikleri test edebilirsiniz. Kalıcı erişim, yüksek limit ve ek ülkeler için bizimle iletişime geçin.