{"openapi":"3.1.0","info":{"title":"Yarış Radarı Yarış API","version":"1.0.0","description":"Türkiye'deki yol ve patika koşusu, bisiklet, yüzme, triatlon ve HYROX yarışlarının günlük güncellenen takvim verisi. Okuma amaçlı, anahtarla erişilen JSON servisi.","contact":{"name":"Yarış Radarı","url":"https://yarisradari.com/iletisim"},"license":{"name":"Yarış Radarı API Kullanım Koşulları","url":"https://yarisradari.com/yaris-api#lisans"}},"servers":[{"url":"https://yarisradari.com/api/v1"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"paths":{"/races":{"get":{"summary":"Yarışları listele","operationId":"listRaces","parameters":[{"name":"scope","in":"query","required":false,"description":"local, national, international (virgülle çoklu)","schema":{"type":"string"}},{"name":"sport","in":"query","required":false,"description":"road_run, trail_run, cycling, swimming, triathlon, hyrox, duathlon, orienteering, obstacle_run (virgülle çoklu)","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"scheduled, tbc, postponed, cancelled, completed","schema":{"type":"string"}},{"name":"city","in":"query","required":false,"description":"Şehir tam eşleşme, büyük/küçük harf duyarsız","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"description":"Yarış adında kısmi arama","schema":{"type":"string"}},{"name":"from","in":"query","required":false,"description":"Başlangıç tarihi bu tarihten itibaren","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"description":"Başlangıç tarihi bu tarihe kadar","schema":{"type":"string","format":"date"}},{"name":"updated_since","in":"query","required":false,"description":"Artımlı senkron için değişiklik zamanı (yarış satırındaki updated_at; silinen/yayından kalkan kayıtlar delta ile gelmez, periyodik tam tarama önerilir)","schema":{"type":"string","format":"date-time"}},{"name":"distance_min","in":"query","required":false,"description":"En az bu mesafede parkuru olanlar (km); yanıttaki distances dizisi de bu filtreyle daralır","schema":{"type":"number"}},{"name":"distance_max","in":"query","required":false,"description":"En fazla bu mesafede parkuru olanlar (km); yanıttaki distances dizisi de bu filtreyle daralır","schema":{"type":"number"}},{"name":"sort","in":"query","required":false,"description":"start_date, -start_date, updated_at, -updated_at","schema":{"type":"string","default":"start_date"}},{"name":"limit","in":"query","required":false,"description":"Sayfa boyutu","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"offset","in":"query","required":false,"description":"Sayfalama kaydırması","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}}],"responses":{"200":{"description":"Yarış listesi","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"sport":{"type":"string","enum":["road_run","trail_run","cycling","swimming","triathlon","hyrox","duathlon","orienteering","obstacle_run"]},"scope":{"type":"string","enum":["local","national","international"]},"status":{"type":"string","enum":["scheduled","tbc","postponed","cancelled","completed"]},"city":{"type":"string"},"venue":{"type":"string","nullable":true},"country_code":{"type":"string","example":"TR"},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date","nullable":true},"latitude":{"type":"number","nullable":true},"longitude":{"type":"number","nullable":true},"website_url":{"type":"string","format":"uri","nullable":true},"results_url":{"type":"string","format":"uri","nullable":true},"photos_url":{"type":"string","format":"uri","nullable":true},"description_tr":{"type":"string","nullable":true},"description_en":{"type":"string","nullable":true},"distances":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"distance_km":{"type":"number","nullable":true},"elevation_gain_m":{"type":"integer","nullable":true},"itra_points":{"type":"integer","nullable":true},"price":{"type":"number","nullable":true},"currency":{"type":"string","nullable":true},"swim_km":{"type":"number","nullable":true},"bike_km":{"type":"number","nullable":true},"run_km":{"type":"number","nullable":true},"gpx_url":{"type":"string","format":"uri","nullable":true}}}},"registration":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["early_bird","standard","late"]},"opens_at":{"type":"string","format":"date-time","nullable":true},"closes_at":{"type":"string","format":"date-time","nullable":true,"description":"Geçmişte olabilir; pencerenin hâlâ açık olduğunu tüketici doğrulamalıdır"},"is_lottery":{"type":"boolean","description":"true ise yerler kurayla dağıtılıyor; opens_at/closes_at kura başvuru penceresidir, başvuru sırası sonucu etkilemez"},"registration_url":{"type":"string","format":"uri","nullable":true},"price":{"type":"number","nullable":true},"currency":{"type":"string","nullable":true}}}},"highlights":{"type":"object","description":"Yarışta gerçekten veri olan ek bloklar. Anahtar yoksa o veri yoktur; boş, null ya da false anahtar gönderilmez. Yeni anahtar eklenebilir, var olan anahtar yeniden adlandırılmaz. Hava durumu bu objeye girmez.","properties":{"route":{"type":"object","description":"En az bir parkurun GPX dosyası varsa gelir","properties":{"courses_with_gpx":{"type":"integer"},"gpx_url":{"type":"string","format":"uri","description":"GPX dosyası olan en uzun parkurun dosyası, organizatörün sunucusunda"},"map_image_url":{"type":"string","format":"uri","description":"Aynı parkurun Yarış Radarı tarafından çizilen rota ve yükseklik profili görseli (SVG). Kaynak GPX okunamazsa 404 döner, tüketici bu duruma düşebilir."}},"required":["courses_with_gpx","gpx_url","map_image_url"]},"briefing":{"type":"boolean","enum":[true],"description":"Yarışın en az bir parkurunda GPX yükseklik verisinden üretilmiş teknik toplantı (parkur analizi) varsa true gelir. Analiz yoksa anahtar hiç gönderilmez, false gönderilmez. Metnin tamamı yarış sayfasındadır: https://yarisradari.com/yaris/{slug}"},"checkpoints":{"type":"object","description":"Yarışın kontrol noktaları girilmişse gelir","properties":{"count":{"type":"integer"},"with_cutoff":{"type":"integer","description":"Kesme saati bilinen kontrol noktası sayısı"},"courses":{"type":"integer","description":"Kontrol noktası bilinen parkur sayısı"}},"required":["count","with_cutoff","courses"]},"results":{"type":"object","description":"Geçmiş sezonların toplu sonuçları arşivdeyse gelir","properties":{"editions":{"type":"integer","description":"Arşivde kaç ayrı yıl var"},"last_edition_year":{"type":"integer"},"courses":{"type":"integer","description":"Son sezonda sonucu olan parkur sayısı"}},"required":["editions","last_edition_year","courses"]},"participants":{"type":"object","description":"Son sezonun katılımcı sayıları biliniyorsa gelir","properties":{"last_edition_year":{"type":"integer"},"starters":{"type":"integer"},"finishers":{"type":"integer"}},"required":["last_edition_year"]}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"meta":{"type":"object","properties":{"total":{"type":"integer"},"count":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"request_id":{"type":"string"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/races/{slug}":{"get":{"summary":"Tek yarış","operationId":"getRace","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Yarış","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"sport":{"type":"string","enum":["road_run","trail_run","cycling","swimming","triathlon","hyrox","duathlon","orienteering","obstacle_run"]},"scope":{"type":"string","enum":["local","national","international"]},"status":{"type":"string","enum":["scheduled","tbc","postponed","cancelled","completed"]},"city":{"type":"string"},"venue":{"type":"string","nullable":true},"country_code":{"type":"string","example":"TR"},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date","nullable":true},"latitude":{"type":"number","nullable":true},"longitude":{"type":"number","nullable":true},"website_url":{"type":"string","format":"uri","nullable":true},"results_url":{"type":"string","format":"uri","nullable":true},"photos_url":{"type":"string","format":"uri","nullable":true},"description_tr":{"type":"string","nullable":true},"description_en":{"type":"string","nullable":true},"distances":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"distance_km":{"type":"number","nullable":true},"elevation_gain_m":{"type":"integer","nullable":true},"itra_points":{"type":"integer","nullable":true},"price":{"type":"number","nullable":true},"currency":{"type":"string","nullable":true},"swim_km":{"type":"number","nullable":true},"bike_km":{"type":"number","nullable":true},"run_km":{"type":"number","nullable":true},"gpx_url":{"type":"string","format":"uri","nullable":true}}}},"registration":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["early_bird","standard","late"]},"opens_at":{"type":"string","format":"date-time","nullable":true},"closes_at":{"type":"string","format":"date-time","nullable":true,"description":"Geçmişte olabilir; pencerenin hâlâ açık olduğunu tüketici doğrulamalıdır"},"is_lottery":{"type":"boolean","description":"true ise yerler kurayla dağıtılıyor; opens_at/closes_at kura başvuru penceresidir, başvuru sırası sonucu etkilemez"},"registration_url":{"type":"string","format":"uri","nullable":true},"price":{"type":"number","nullable":true},"currency":{"type":"string","nullable":true}}}},"highlights":{"type":"object","description":"Yarışta gerçekten veri olan ek bloklar. Anahtar yoksa o veri yoktur; boş, null ya da false anahtar gönderilmez. Yeni anahtar eklenebilir, var olan anahtar yeniden adlandırılmaz. Hava durumu bu objeye girmez.","properties":{"route":{"type":"object","description":"En az bir parkurun GPX dosyası varsa gelir","properties":{"courses_with_gpx":{"type":"integer"},"gpx_url":{"type":"string","format":"uri","description":"GPX dosyası olan en uzun parkurun dosyası, organizatörün sunucusunda"},"map_image_url":{"type":"string","format":"uri","description":"Aynı parkurun Yarış Radarı tarafından çizilen rota ve yükseklik profili görseli (SVG). Kaynak GPX okunamazsa 404 döner, tüketici bu duruma düşebilir."}},"required":["courses_with_gpx","gpx_url","map_image_url"]},"briefing":{"type":"boolean","enum":[true],"description":"Yarışın en az bir parkurunda GPX yükseklik verisinden üretilmiş teknik toplantı (parkur analizi) varsa true gelir. Analiz yoksa anahtar hiç gönderilmez, false gönderilmez. Metnin tamamı yarış sayfasındadır: https://yarisradari.com/yaris/{slug}"},"checkpoints":{"type":"object","description":"Yarışın kontrol noktaları girilmişse gelir","properties":{"count":{"type":"integer"},"with_cutoff":{"type":"integer","description":"Kesme saati bilinen kontrol noktası sayısı"},"courses":{"type":"integer","description":"Kontrol noktası bilinen parkur sayısı"}},"required":["count","with_cutoff","courses"]},"results":{"type":"object","description":"Geçmiş sezonların toplu sonuçları arşivdeyse gelir","properties":{"editions":{"type":"integer","description":"Arşivde kaç ayrı yıl var"},"last_edition_year":{"type":"integer"},"courses":{"type":"integer","description":"Son sezonda sonucu olan parkur sayısı"}},"required":["editions","last_edition_year","courses"]},"participants":{"type":"object","description":"Son sezonun katılımcı sayıları biliniyorsa gelir","properties":{"last_edition_year":{"type":"integer"},"starters":{"type":"integer"},"finishers":{"type":"integer"}},"required":["last_edition_year"]}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/tools/hazirlik-suresi":{"servers":[{"url":"https://yarisradari.com"}],"get":{"summary":"Hazırlığa başlama süresini hesapla","operationId":"trainingLeadTime","description":"Yarış slug ya da ham mesafe ile hazırlığın kaç hafta sürdüğünü, zirve haftayı ve en geç başlama gününü döndürür. Anahtar gerekmez.","security":[],"parameters":[{"name":"yaris","in":"query","required":false,"description":"Yarış slug; parkur verilmezse en uzun parkur alınır","schema":{"type":"string"}},{"name":"parkur","in":"query","required":false,"description":"Parkur etiketi (örn. 63K) ya da <yarisId>:<etiket>","schema":{"type":"string"}},{"name":"km","in":"query","required":false,"description":"Yarış seçilmediyse mesafe (km)","schema":{"type":"number"}},{"name":"tirmanis","in":"query","required":false,"description":"Yükseklik kazanımı (m)","schema":{"type":"number","default":0}},{"name":"haftalik","in":"query","required":false,"description":"Şu anki haftalık koşu (km)","schema":{"type":"number","default":30}}],"responses":{"200":{"description":"Hesap sonucu ve iki dilde cümle","content":{"application/json":{"schema":{"type":"object","properties":{"input":{"type":"object","properties":{"km":{"type":"number"},"elevation_gain_m":{"type":"number"},"weekly_km":{"type":"number"},"run_days":{"type":"integer"},"today":{"type":"string","format":"date"},"race":{"type":"object","nullable":true,"properties":{"name":{"type":"string"},"slug":{"type":"string"},"course":{"type":"string"},"start_date":{"type":"string","format":"date"}}}}},"result":{"type":"object","properties":{"weeks":{"type":"integer"},"months":{"type":"number"},"peak_weekly_km":{"type":"number"},"peak_long_run_km":{"type":"number"},"start_by":{"type":"string","format":"date","nullable":true},"weeks_left":{"type":"integer","nullable":true},"late":{"type":"boolean"},"volume_ready":{"type":"boolean"}}},"sentence":{"type":"object","properties":{"tr":{"type":"string"},"en":{"type":"string"}}},"page":{"type":"string","format":"uri"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"yr_live_..."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key"}},"responses":{"BadRequest":{"description":"Geçersiz parametre","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"request_id":{"type":"string"}}}}}},"Unauthorized":{"description":"Anahtar yok ya da hatalı"},"NotFound":{"description":"Yarış bulunamadı"},"RateLimited":{"description":"Aylık kota bitti ya da dakika limiti aşıldı"},"ServiceUnavailable":{"description":"Geçici hata, Retry-After başlığıyla tekrar dene"}}}}