{"openapi":"3.1.0","info":{"title":"Yarış Radarı Yarış API","version":"1.2.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. Her yarış nesnesindeki url alanı yarışın yarisradari.com sayfasıdır (İngilizcesi url_en); lisansın istediği siteye bağlantı yarış ekranında bu adrese verilebilir.","contact":{"name":"Yarış Radarı","url":"https://yarisradari.com/iletisim?konu=api"},"license":{"name":"Yarış Radarı API Kullanım Koşulları","url":"https://yarisradari.com/yaris-api#lisans"}},"externalDocs":{"description":"İnsan okunur doküman, örnekler ve lisans","url":"https://yarisradari.com/yaris-api"},"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 (virgülle çoklu)","schema":{"type":"string"}},{"name":"city","in":"query","required":false,"description":"Şehir tam eşleşme; büyük/küçük harf, Türkçe harf ve aksan fark etmez (Istanbul, istanbul ve İSTANBUL aynı şehri bulur)","schema":{"type":"string","maxLength":100}},{"name":"q","in":"query","required":false,"description":"Yarış adında kısmi arama; büyük/küçük harf, Türkçe harf ve aksan fark etmez","schema":{"type":"string","maxLength":120}},{"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","minimum":0,"maximum":10000}},{"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","minimum":0,"maximum":10000}},{"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","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-Quota-Limit":{"$ref":"#/components/headers/QuotaLimit"},"X-Quota-Remaining":{"$ref":"#/components/headers/QuotaRemaining"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"url":{"type":"string","format":"uri","description":"Yarışın yarisradari.com'daki sayfası (https://yarisradari.com/yaris/{slug}). Lisanstaki siteye bağlantı şartı yarış ekranında bu adresle karşılanabilir."},"url_en":{"type":"string","format":"uri","description":"Aynı sayfanın İngilizcesi (https://yarisradari.com/en/yaris/{slug}); İngilizce arayüzde bu adrese bağlan."},"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","null"]},"country_code":{"type":"string","example":"TR"},"start_date":{"type":"string","format":"date"},"end_date":{"type":["string","null"],"format":"date"},"latitude":{"type":["number","null"]},"longitude":{"type":["number","null"]},"website_url":{"type":["string","null"],"format":"uri"},"results_url":{"type":["string","null"],"format":"uri"},"photos_url":{"type":["string","null"],"format":"uri"},"price_excludes_federation_fee":{"type":"boolean","description":"true ise parkur ve kayıt ücretlerine kayıt sırasında federasyon ücreti eklenir; price alanı bu ücreti içermez"},"description_tr":{"type":["string","null"]},"description_en":{"type":["string","null"]},"distances":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"course_key":{"type":"string","description":"Kalıcı parkur anahtarı; rota ucunun adresinde kullanılır"},"has_route":{"type":"boolean","description":"true ise rota ucu bu parkur için rota döner (bu yılın ya da önceki edisyonun)"},"route_updated_at":{"type":["string","null"],"format":"date-time","description":"Dönecek rotanın son değiştiği an; önbelleği buna bakarak yenile"},"distance_km":{"type":["number","null"]},"start_date":{"type":["string","null"],"format":"date","description":"Parkurun koşulduğu gün; birden çok gün süren yarışlarda mesafeler farklı günlerde olabilir. null ise yarışın start_date alanı geçerlidir"},"start_time":{"type":["string","null"],"description":"Parkurun start saati, Türkiye saati (HH:MM:SS); bilinmiyorsa null"},"elevation_gain_m":{"type":["integer","null"]},"itra_points":{"type":["integer","null"]},"price":{"type":["number","null"]},"currency":{"type":["string","null"]},"swim_km":{"type":["number","null"]},"bike_km":{"type":["number","null"]},"run_km":{"type":["number","null"]},"gpx_url":{"type":["string","null"],"format":"uri"}}}},"registration":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["early_bird","standard","late"]},"opens_at":{"type":["string","null"],"format":"date-time"},"closes_at":{"type":["string","null"],"format":"date-time","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","null"],"format":"uri"},"price":{"type":["number","null"]},"currency":{"type":["string","null"]}}}},"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ı url alanındaki yarış sayfasındadır."},"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"]}}},"result_sources":{"type":"array","description":"Sonuç kaynakları, edisyon yılı başına: zamanlama sağlayıcısı, sayfa ve veri adresi, durum ve parkur eşlemesi. Yalnızca tekil yarış yanıtında gelir; dizi boş olabilir","items":{"$ref":"#/components/schemas/ResultSource"}},"results_summary":{"type":"array","description":"Sonuç arşivindeki parkur bazlı toplu sayılar: başlayan, bitiren, DNF ve bitiş süresi yüzdelikleri (saniye). Sporcu satırı içermez; yalnızca tekil yarış yanıtında gelir","items":{"$ref":"#/components/schemas/ResultSummary"}},"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,"description":"Yarışın slug değeri","schema":{"type":"string","maxLength":200,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}}],"responses":{"200":{"description":"Yarış","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-Quota-Limit":{"$ref":"#/components/headers/QuotaLimit"},"X-Quota-Remaining":{"$ref":"#/components/headers/QuotaRemaining"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"url":{"type":"string","format":"uri","description":"Yarışın yarisradari.com'daki sayfası (https://yarisradari.com/yaris/{slug}). Lisanstaki siteye bağlantı şartı yarış ekranında bu adresle karşılanabilir."},"url_en":{"type":"string","format":"uri","description":"Aynı sayfanın İngilizcesi (https://yarisradari.com/en/yaris/{slug}); İngilizce arayüzde bu adrese bağlan."},"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","null"]},"country_code":{"type":"string","example":"TR"},"start_date":{"type":"string","format":"date"},"end_date":{"type":["string","null"],"format":"date"},"latitude":{"type":["number","null"]},"longitude":{"type":["number","null"]},"website_url":{"type":["string","null"],"format":"uri"},"results_url":{"type":["string","null"],"format":"uri"},"photos_url":{"type":["string","null"],"format":"uri"},"price_excludes_federation_fee":{"type":"boolean","description":"true ise parkur ve kayıt ücretlerine kayıt sırasında federasyon ücreti eklenir; price alanı bu ücreti içermez"},"description_tr":{"type":["string","null"]},"description_en":{"type":["string","null"]},"distances":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"course_key":{"type":"string","description":"Kalıcı parkur anahtarı; rota ucunun adresinde kullanılır"},"has_route":{"type":"boolean","description":"true ise rota ucu bu parkur için rota döner (bu yılın ya da önceki edisyonun)"},"route_updated_at":{"type":["string","null"],"format":"date-time","description":"Dönecek rotanın son değiştiği an; önbelleği buna bakarak yenile"},"distance_km":{"type":["number","null"]},"start_date":{"type":["string","null"],"format":"date","description":"Parkurun koşulduğu gün; birden çok gün süren yarışlarda mesafeler farklı günlerde olabilir. null ise yarışın start_date alanı geçerlidir"},"start_time":{"type":["string","null"],"description":"Parkurun start saati, Türkiye saati (HH:MM:SS); bilinmiyorsa null"},"elevation_gain_m":{"type":["integer","null"]},"itra_points":{"type":["integer","null"]},"price":{"type":["number","null"]},"currency":{"type":["string","null"]},"swim_km":{"type":["number","null"]},"bike_km":{"type":["number","null"]},"run_km":{"type":["number","null"]},"gpx_url":{"type":["string","null"],"format":"uri"}}}},"registration":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["early_bird","standard","late"]},"opens_at":{"type":["string","null"],"format":"date-time"},"closes_at":{"type":["string","null"],"format":"date-time","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","null"],"format":"uri"},"price":{"type":["number","null"]},"currency":{"type":["string","null"]}}}},"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ı url alanındaki yarış sayfasındadır."},"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"]}}},"result_sources":{"type":"array","description":"Sonuç kaynakları, edisyon yılı başına: zamanlama sağlayıcısı, sayfa ve veri adresi, durum ve parkur eşlemesi. Yalnızca tekil yarış yanıtında gelir; dizi boş olabilir","items":{"$ref":"#/components/schemas/ResultSource"}},"results_summary":{"type":"array","description":"Sonuç arşivindeki parkur bazlı toplu sayılar: başlayan, bitiren, DNF ve bitiş süresi yüzdelikleri (saniye). Sporcu satırı içermez; yalnızca tekil yarış yanıtında gelir","items":{"$ref":"#/components/schemas/ResultSummary"}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"meta":{"type":"object","properties":{"request_id":{"type":"string"}}}}}}}},"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"}}}},"/races/{slug}/results":{"get":{"summary":"Göğüs numarasıyla kişisel sonuç","operationId":"lookupResult","description":"Verilen edisyonda göğüs numarasına ait sonucu sağlayıcıdan anlık okur. Sporcu adı maskelidir (Ahmet Y.), doğum yılı ve uyruk hiçbir zaman dönmez. Sıralama sağlayıcı verdiyse onundur, yoksa Yarış Radarı net süreye göre hesaplar, net süre yoksa brüte bakar. Sonuçlar final olana kadar ya da yarıştan 14 gün sonrasına kadar yoklanabilir; pending true ise Retry-After kadar bekleyip tekrar sor","parameters":[{"name":"slug","in":"path","required":true,"description":"Yarışın slug değeri","schema":{"type":"string","maxLength":200,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}},{"name":"bib","in":"query","required":true,"description":"Göğüs numarası; harf, rakam ve tire, en fazla 12 karakter","schema":{"type":"string","pattern":"^[0-9A-Za-z][0-9A-Za-z-]{0,11}$"}},{"name":"year","in":"query","required":false,"description":"Edisyon yılı; verilmezse başlamış en yeni edisyon","schema":{"type":"integer","minimum":2000}}],"responses":{"200":{"description":"Sorgu sonucu; bib listede yoksa ve edisyon final değilse result null döner","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-Quota-Limit":{"$ref":"#/components/headers/QuotaLimit"},"X-Quota-Remaining":{"$ref":"#/components/headers/QuotaRemaining"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ResultLookup"},"meta":{"type":"object","properties":{"request_id":{"type":"string"}}}}}}}},"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"}}}},"/races/{slug}/courses/{course_key}/route":{"get":{"summary":"Parkur rotası","operationId":"getCourseRoute","description":"Parkurun sadeleştirilmiş rotasını (Google encoded polyline, hassasiyet 5) ve 100 metrede bir yükseklik profilini döner. Rota günlük taramada organizatör dosyasından üretilir; istek kaynağa gitmez. Uzunluğu parkur mesafesinden %15 fazla sapan ya da şehir dışında başlayan dosya verilmez. Bu yılın dosyası yoksa önceki edisyonun aynı parkuru is_previous_edition true ile döner. ETag ve If-None-Match ile değişmeyen rota 304 döner.","parameters":[{"name":"slug","in":"path","required":true,"description":"Yarışın slug değeri","schema":{"type":"string","maxLength":200,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}},{"name":"course_key","in":"path","required":true,"description":"Parkur anahtarı (distances[].course_key); etiket değişse de aynı kalır","schema":{"type":"string","maxLength":100,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}},{"name":"year","in":"query","required":false,"description":"Edisyon yılı; verilmezse yarışın yılı, o yılın rotası yoksa önceki edisyon","schema":{"type":"integer","minimum":2000}},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Parkur rotası","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-Quota-Limit":{"$ref":"#/components/headers/QuotaLimit"},"X-Quota-Remaining":{"$ref":"#/components/headers/QuotaRemaining"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"ETag":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CourseRoute"},"meta":{"type":"object","properties":{"request_id":{"type":"string"}}}}}}}},"304":{"description":"Rota If-None-Match ile gönderilen ETag sonrasında değişmedi","headers":{"ETag":{"schema":{"type":"string"}}}},"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"}}}},"/races/{slug}/results/search":{"post":{"summary":"İsimle aday sporcu arama","operationId":"searchAthleteByName","description":"Yarış edisyonunda ad ve soyad ile eşleşen sporcuları arar. İsim URL yerine POST gövdesinde gönderilir ve sunucuda loglanmaz. En fazla 5 aday döner; dönen isimler maskelidir. Daha fazlası eşleşirse 409 too_many_matches döner.","parameters":[{"name":"slug","in":"path","required":true,"description":"Yarışın slug değeri","schema":{"type":"string","maxLength":200,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Aranacak sporcu adı ve soyadı; en az iki kelime önerilir","minLength":2,"maxLength":100},"year":{"type":"integer","minimum":2000,"description":"Edisyon yılı; verilmezse en yeni edisyon"},"course":{"type":"string","description":"Parkur filtresi (sağlayıcı parkur adı ya da Yarış Radarı etiketi)"}},"required":["name"]}}}},"responses":{"200":{"description":"Aday listesi","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-Quota-Limit":{"$ref":"#/components/headers/QuotaLimit"},"X-Quota-Remaining":{"$ref":"#/components/headers/QuotaRemaining"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ResultSearch"},"meta":{"type":"object","properties":{"request_id":{"type":"string"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"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. Yalnız bugün ve sonrasındaki, iptal edilmemiş yol ve patika koşuları bulunur","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","null"],"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","null"],"format":"date"},"weeks_left":{"type":["integer","null"]},"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"}},"schemas":{"ApiError":{"type":"object","description":"Tüm hata yanıtlarının ortak gövdesi","properties":{"error":{"type":"string","description":"Makine okunur hata kodu"},"message":{"type":"string","description":"Sorunun İngilizce açıklaması"},"documentation_url":{"type":"string","format":"uri","description":"Dokümanın bu hatayı anlatan bölümü"},"request_key_url":{"type":"string","format":"uri","description":"Anahtar isteme formu; yalnız 401 yanıtlarında gelir"},"request_id":{"type":"string","description":"Log korelasyonu için istek kimliği, X-Request-Id başlığıyla aynı"}},"required":["error","message","documentation_url","request_id"]},"ResultSource":{"type":"object","properties":{"edition_year":{"type":"integer","description":"Edisyon yılı; sorguda year olarak kullanılır"},"provider":{"type":"string","description":"Zamanlama sağlayıcısı: g-live, raceresult, plustiming, hurra, splittime, livetrail, ttf, oe, ironman, utmb, other"},"format":{"type":"string","description":"Veri biçimi; clax, raceresult, plustiming ve hurra bib sorgusuyla okunabilir, diğerleri yalnız bağlantıdır"},"status":{"type":"string","enum":["start_list","live","final","blocked"],"description":"start_list: liste var, bitiren yok; live: sonuçlar geliyor; final: sonuçlar kesinleşti; blocked: sağlayıcı bot erişimine kapalı, yalnız page_url verilir"},"name_lookup":{"type":"boolean","description":"true ise isimle aday arama (results/search) desteklenir"},"bib_lookup":{"type":"boolean","description":"true ise göğüs numarasıyla sorgulama (results) desteklenir"},"final_at":{"type":["string","null"],"format":"date-time","description":"Durumun final olduğu an; final değilse null"},"last_checked_at":{"type":["string","null"],"format":"date-time","description":"Kaynağın son yoklandığı an"},"event_date":{"type":["string","null"],"format":"date","description":"Edisyonun yarış günü"},"page_url":{"type":"string","format":"uri","description":"Sağlayıcının insan okunur sonuç sayfası"},"data_url":{"type":["string","null"],"format":"uri","description":"Ham veri adresi (örneğin .clax dosyası); yoksa null"},"provider_ids":{"type":"object","additionalProperties":true,"description":"Sağlayıcıya özel kimlikler: RaceResult event_id ve liste adları, PlusTiming cid/rid/eid, Hurra events_id ve parkur kimlikleri"},"course_map":{"type":"object","additionalProperties":{"type":"string"},"description":"Sağlayıcı parkur adından Yarış Radarı parkur etiketine (distances[].label) eşleme"},"lookup_url":{"type":"string","format":"uri","description":"Bu edisyon için bib sorgusu adresi; sonuna göğüs numarasını ekle"}},"required":["edition_year","provider","format","status","name_lookup","bib_lookup","page_url","provider_ids","course_map","lookup_url"]},"ResultSummary":{"type":"object","description":"Bir edisyon ve parkur için toplu sonuç sayıları","properties":{"edition_year":{"type":"integer"},"provider":{"type":"string"},"course_label":{"type":"string","description":"Sağlayıcının parkur adı"},"label":{"type":["string","null"],"description":"Eşleşen Yarış Radarı parkur etiketi; eşleşmediyse null"},"distance_km":{"type":["number","null"]},"registered":{"type":"integer"},"starters":{"type":["integer","null"]},"finishers":{"type":"integer"},"dnf":{"type":["integer","null"]},"fastest_seconds":{"type":["integer","null"]},"slowest_seconds":{"type":["integer","null"]},"p10_seconds":{"type":["integer","null"]},"p25_seconds":{"type":["integer","null"]},"p50_seconds":{"type":["integer","null"]},"p75_seconds":{"type":["integer","null"]},"p90_seconds":{"type":["integer","null"]},"page_url":{"type":"string","format":"uri"}},"required":["edition_year","provider","course_label","registered","starters","finishers","dnf","page_url"]},"ResultLookup":{"type":"object","description":"Sorgu sonucu; bib listede yoksa ve edisyon final değilse result null döner","properties":{"status":{"type":"string","enum":["start_list","live","final","blocked"],"description":"Edisyonun durumu: start_list, live, final ya da blocked"},"pending":{"type":"boolean","description":"true ise sağlayıcı listesi henüz tamamen okunmadı; Retry-After başlığındaki süre sonra tekrar dene"},"client_fetch":{"type":["object","null"],"description":"Sağlayıcı sunucu IP'lerine bot duvarı döndüğü için sonucu sunucu okuyamadıysa (status blocked) doluysa: istemci bu GET isteğini kullanıcının cihazından yapar ve sağlayıcının sayfasını kendisi ayrıştırır (format plustiming_search). Diğer durumlarda null","properties":{"reason":{"type":"string","enum":["provider_blocks_servers"]},"provider":{"type":"string"},"format":{"type":"string","enum":["plustiming_search"]},"method":{"type":"string","enum":["GET"]},"url":{"type":"string","format":"uri"}},"required":["reason","provider","format","method","url"]},"edition_year":{"type":"integer","description":"Yanıtın ait olduğu edisyon yılı"},"final_at":{"type":["string","null"],"format":"date-time"},"fetched_at":{"type":["string","null"],"format":"date-time","description":"Sağlayıcı verisinin okunma anı"},"source":{"type":"object","description":"Kullanılan kaynağın sağlayıcısı ve sayfası","properties":{"provider":{"type":"string"},"page_url":{"type":"string","format":"uri"}},"required":["provider","page_url"]},"result":{"type":["object","null"],"description":"Sporcunun sonucu; listede yoksa ya da kaynak engelliyse null","properties":{"bib":{"type":"string"},"name":{"type":"string","description":"Maskeli ad: ilk ad ve soyadın baş harfi"},"finished":{"type":"boolean","description":"true ise bitiş süresi var"},"course":{"type":"object","description":"Koşulan parkur: Yarış Radarı etiketi, mesafe, sağlayıcı adı ve eşleşme bayrağı","properties":{"label":{"type":"string"},"distance_km":{"type":["number","null"]},"provider_name":{"type":"string"},"mapped":{"type":"boolean","description":"false ise parkur Yarış Radarı parkurlarıyla eşleştirilemedi, label sağlayıcı adıdır"}},"required":["label","distance_km","provider_name","mapped"]},"category":{"type":["string","null"]},"gender":{"type":["string","null"],"enum":["M","F",null]},"team":{"type":["string","null"]},"result_status":{"type":["string","null"],"enum":["finished","dnf","dns","dsq",null]},"pace_seconds_per_km":{"type":["integer","null"]},"start_time":{"type":["string","null"],"format":"date-time"},"finish_time":{"type":["string","null"],"format":"date-time"},"wave":{"type":["string","null"]},"certificate_url":{"type":["string","null"],"format":"uri"},"net_seconds":{"type":["integer","null"],"description":"Net (çip) süre, saniye; yoksa null"},"gross_seconds":{"type":["integer","null"],"description":"Brüt (tabanca) süre, saniye; yoksa null"},"rankings":{"type":"object","description":"Genel, cinsiyet ve kategori sırası, her biri o gruptaki bitiren sayısıyla; bilinmeyen grup null","properties":{"overall":{"type":["object","null"],"properties":{"rank":{"type":"integer"},"total":{"type":"integer"}},"required":["rank","total"]},"gender":{"type":["object","null"],"properties":{"rank":{"type":"integer"},"total":{"type":"integer"},"value":{"type":"string"}},"required":["rank","total","value"]},"category":{"type":["object","null"],"properties":{"rank":{"type":"integer"},"total":{"type":"integer"},"value":{"type":"string"}},"required":["rank","total","value"]}},"required":["overall","gender","category"]},"ranking_basis":{"type":["string","null"],"enum":["provider","gross","net",null],"description":"provider: sağlayıcının sırası; gross/net: Yarış Radarı süreye göre hesapladı; null: bitiren yok"},"splits":{"type":"array","description":"Ara geçişler: nokta adı, km ve geçiş süresi (saniye)","items":{"type":"object","properties":{"name":{"type":"string"},"km":{"type":["number","null"]},"seconds":{"type":"integer"},"rank":{"type":["integer","null"]},"pace_seconds_per_km":{"type":["integer","null"]}},"required":["name","km","seconds"]}},"page_url":{"type":"string","format":"uri"}},"required":["bib","name","finished","course","net_seconds","gross_seconds","category","gender","team","result_status","pace_seconds_per_km","start_time","finish_time","wave","certificate_url","rankings","ranking_basis","splits","page_url"]}},"required":["status","pending","client_fetch","edition_year","final_at","fetched_at","source","result"]},"ResultCandidate":{"type":"object","properties":{"bib":{"type":"string","description":"Adayın göğüs numarası"},"name":{"type":"string","description":"Maskeli ad"},"course":{"type":"object","description":"Adayın parkuru","properties":{"label":{"type":"string"},"distance_km":{"type":["number","null"]}},"required":["label","distance_km"]},"match":{"type":"string","enum":["exact","partial"],"description":"Eşleşme türü: exact (birebir kelime eşleşmesi) ya da partial (en az iki ortak kelime)"},"category":{"type":["string","null"],"description":"Kategori; bilinmiyorsa null"},"finished":{"type":"boolean","description":"Bitirdiyse true; start listesinde false"},"net_seconds":{"type":["integer","null"],"description":"Net süre (saniye); bitirmediyse null"}},"required":["bib","name","match","course","category","finished","net_seconds"]},"ResultSearch":{"type":"object","description":"Aday listesi","properties":{"status":{"type":"string","enum":["start_list","live","final","blocked"]},"edition_year":{"type":"integer"},"candidates":{"type":"array","items":{"$ref":"#/components/schemas/ResultCandidate"}},"client_fetch":{"type":["object","null"],"description":"Sağlayıcı sunucu IP'lerine bot duvarı döndüğü için sonucu sunucu okuyamadıysa (status blocked) doluysa: istemci bu GET isteğini kullanıcının cihazından yapar ve sağlayıcının sayfasını kendisi ayrıştırır (format plustiming_search). Diğer durumlarda null","properties":{"reason":{"type":"string","enum":["provider_blocks_servers"]},"provider":{"type":"string"},"format":{"type":"string","enum":["plustiming_search"]},"method":{"type":"string","enum":["GET"]},"url":{"type":"string","format":"uri"}},"required":["reason","provider","format","method","url"]}},"required":["status","edition_year","candidates","client_fetch"]},"CourseRoute":{"type":"object","description":"Parkur rotası","properties":{"course_key":{"type":"string","description":"Kalıcı parkur anahtarı; rota ucunun adresinde kullanılır"},"label":{"type":"string"},"edition_year":{"type":"integer"},"is_previous_edition":{"type":"boolean","description":"true ise rota önceki edisyonundur; edition_year rotanın yılını gösterir"},"distance_km":{"type":"number","description":"Rotanın ölçülen uzunluğu (km)"},"polyline":{"type":"string","description":"Google encoded polyline, hassasiyet 5 (1e5); en fazla 1500 nokta, 5 m tolerans"},"point_count":{"type":"integer"},"elevation_gain_m":{"type":["integer","null"]},"elevation_loss_m":{"type":["integer","null"]},"start":{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"}},"required":["lat","lng"]},"finish":{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"}},"required":["lat","lng"]},"is_loop":{"type":"boolean","description":"Başlangıç ve bitiş 200 metreden yakınsa true"},"profile":{"type":["array","null"],"description":"Her 100 metrede bir [mesafe_m, irtifa_m]; dosyada güvenilir yükseklik yoksa null","items":{"type":"array","items":{"type":"integer"},"minItems":2,"maxItems":2}},"source_url":{"type":"string","format":"uri","description":"Rotanın üretildiği organizatör dosyası"},"updated_at":{"type":"string","format":"date-time"},"checksum":{"type":"string","description":"Rota içeriğinin SHA-1 özeti"}},"required":["course_key","label","edition_year","is_previous_edition","distance_km","polyline","point_count","elevation_gain_m","elevation_loss_m","start","finish","is_loop","profile","source_url","updated_at","checksum"]}},"headers":{"RequestId":{"description":"Log korelasyonu için istek kimliği","schema":{"type":"string"}},"RetryAfter":{"description":"Tekrar denemeden önce beklenecek saniye","schema":{"type":"integer"}},"QuotaLimit":{"description":"Anahtarın aylık istek kotası","schema":{"type":"integer"}},"QuotaRemaining":{"description":"Bu ay kalan istek sayısı","schema":{"type":"integer"}},"RateLimitLimit":{"description":"Anahtarın dakikalık istek sınırı","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Bu dakika kalan istek sayısı","schema":{"type":"integer"}}},"responses":{"BadRequest":{"description":"Geçersiz parametre ya da aralık; message geçerli değerleri söyler","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ApiError"},{"type":"object","properties":{"error":{"type":"string","enum":["invalid_scope","invalid_sport","invalid_status","invalid_from","invalid_to","invalid_date_range","invalid_updated_since","invalid_distance_min","invalid_distance_max","invalid_distance_range","invalid_city","invalid_q","invalid_sort","invalid_limit","invalid_offset","invalid_slug","invalid_bib","invalid_year","invalid_name","bad_request"]}}}]}}}},"Unauthorized":{"description":"Anahtar yok ya da hatalı; request_key_url anahtar isteme formuna götürür","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ApiError"},{"type":"object","properties":{"error":{"type":"string","enum":["missing_api_key","invalid_api_key"]}}}]}}}},"NotFound":{"description":"Yarış bulunamadı (not_found), bu yıl için sonuç kaynağı yok (no_result_source), göğüs numarası kesin listede yok (bib_not_found) hazırlık süresi ucunda eşleşen yarış veya parkur yok (race_not_found), parkur anahtarı yok (course_not_found) ya da parkurun rotası yok (route_not_available)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ApiError"},{"type":"object","properties":{"error":{"type":"string","enum":["not_found","no_result_source","bib_not_found","name_not_found","course_not_found","route_not_available","name_lookup_unsupported","race_not_found"]}}}]}}}},"Conflict":{"description":"5 adaydan fazlası eşleşti (too_many_matches); göğüs numarasıyla sorgulayın","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ApiError"},{"type":"object","properties":{"error":{"type":"string","enum":["too_many_matches"]}}}]}}}},"RateLimited":{"description":"Aylık kota bitti (quota_exceeded, ay başında UTC yenilenir) ya da dakika limiti aşıldı (rate_limit_exceeded); Retry-After bekleme süresini verir","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ApiError"},{"type":"object","properties":{"error":{"type":"string","enum":["quota_exceeded","rate_limit_exceeded"]}}}]}}}},"ServiceUnavailable":{"description":"Geçici hata, Retry-After başlığıyla tekrar dene","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ApiError"},{"type":"object","properties":{"error":{"type":"string","enum":["service_unavailable","lookup_failed","rate_limit_failed","usage_failed","results_unavailable","unavailable"]}}}]}}}}}}}