API belgeleri
Türkiye il ve ilçeleri için 7 günlük sıcaklık tahmini (en yüksek, en düşük, ortalama; kalibre edilmiş %90 aralıkla). Her şey statik JSON dosyasıdır: sunucu yok, SDK yok, kayıt gerekmez. Tahminler anahtarsızdır; uyarılar ve doğrulama için API anahtarı gerekir.
Hızlı başlangıç
- Yerinizin
pathdeğerini /v1/places.json'dan bulun (ör. Bodrum içinmugla/bodrum). - Tahmini alın:
GET https://havatahmin.abso.net/v1/forecast/mugla/bodrum.json daysdizisindeki 7 günü okuyun:tmax.value,tmin.value,tmean.value(°C).
curl https://havatahmin.abso.net/v1/forecast/ankara.json
curl https://havatahmin.abso.net/v1/forecast/mugla/bodrum.json
API anahtarı
Tahmin uç noktaları anahtar gerektirmez. Uyarılar (/v1/alerts) ve doğrulama (/v1/verification) için anahtar gerekir.
API anahtarı iste: iletişim formu →
Formda konu olarak API anahtarı yazın; adınızı, kullanım amacınızı (uygulama, web sitesi, araştırma…) ve tahmini günlük istek sayınızı belirtin.
Anahtarı gönderme
İki yoldan biriyle: x-api-key başlığı (önerilen) ya da ?key= sorgu parametresi. İkisi birden varsa başlık esas alınır.
curl -H "x-api-key: ANAHTARINIZ" https://havatahmin.abso.net/v1/alerts/erzurum/aziziye.json
curl "https://havatahmin.abso.net/v1/alerts/erzurum.json?key=ANAHTARINIZ"
Anahtarı herkese açık bir web sayfasının JavaScript'ine koymayın; herkes görebilir. Tarayıcı uygulamalarında anahtarlı istekleri kendi sunucunuz üzerinden yapın. Anahtarınız sızarsa aynı formdan yenisini isteyin; eskisi iptal edilir.
Temel bilgiler
| Taban adres | https://havatahmin.abso.net (yalnızca HTTPS) |
|---|---|
| Biçim | UTF-8 JSON, sıkıştırılmış (gzip/brotli) sunulur |
| Güncelleme | Günde en çok iki çalıştırma: 00Z koşusu genellikle 10:30–11:00, 12Z koşusu 20:30–23:00 arasında (İstanbul saati) yayınlanır; sabit bir saat yoktur ve bazı günler tek koşu yayınlanır. Yeni veri olup olmadığını /v1/status.json'daki latest_run söyler. |
| Tahmin ufku | 7 gün; lead 1, issued tarihinden sonraki gündür |
| Birimler | Sıcaklıklar °C, mesafeler km, rakımlar m |
| Saat dilimi | issued ve valid İstanbul (UTC+3) takvim günüdür. cycle (00Z/12Z) ECMWF koşusunun UTC saatidir. produced_at, status.time ve next_run_expected İstanbul saatidir ve +03:00 farkını taşır. Tek kural: tüm tarihler İstanbul'dur; bir gün için valid'i o güne eşit olan kaydı seçin; lead = valid − issued (gün). |
| Lisans | Tahmin verileri CC BY 4.0 ile sunulur: kaynak olarak havatahmin.abso.net'i gösterin; yer adları GeoNames (CC BY 4.0). |
| CORS | Açık (*); tarayıcıdan doğrudan çağrılabilir |
| Sürüm | /v1 altındaki alanlar geriye uyumlu kalır; yeni alanlar eklenebilir, kırıcı değişiklik yeni bir sürüm yoluyla gelir |
| Kapsam | 81 il (76'sı istasyon modeli, 5'i en yakın istasyondan aktarım: Bitlis, Kahramanmaraş, Karabük, Sivas, Şırnak) ve 973 ilçe sunulur; bu çalıştırmada tahmini olan ilçe sayısı ve eksik olanların listesi /v1/status.json'da (districts_with_forecast, missing) yazar |
Uç noktalar
| Yol | Döndürür | Erişim |
|---|---|---|
/v1/status.json | Son çalıştırma (latest_run), model sürümü, kapsam sayıları, veri tazeliği. /latest.json aynısıdır. | anahtarsız |
/v1/places.json | Tüm iller ve ilçeleri: name, slug, path, enlem, boylam, rakım | anahtarsız |
/v1/search/{abc}.json | Ad arama: iller, ilçeler, ~54.000 köy ve mahalle; nasıl kullanılır | anahtarsız |
/v1/districts/{il}.json | Bir ilin ilçeleri; her biri path ve has_forecast ile | anahtarsız |
/v1/forecast/{il}.json | İlin 7 günlük tahmini ve ildeki her istasyonun tahmini | anahtarsız |
/v1/forecast/{il}/{ilce}.json | İlçenin 7 günlük tahmini (her gün ayrıca raw ham HRES alanları ve precip yağış bloğu taşır; ürünler) | anahtarsız |
/v1/hourly/{il}.json/v1/hourly/{il}/{ilce}.json | 7 günün her biri için 24 saatlik sıcaklık eğrisi (t düzeltilmiş, t_raw ham ECMWF) | anahtarsız |
/v1/aq/{il}.json/v1/aq/stations.json | Hava kalitesi: ildeki ölçüm istasyonlarında PM2.5, PM10, NO2, O3, SO2, CO günlük ortalamaları, D+1..D+3 (µg/m³); istasyon listesi | anahtarsız |
/v1/alerts/{il}.json/v1/alerts/{il}/{ilce}.json | Hafta için don, sıcak hava ve ani değişim uyarıları | API anahtarı |
/v1/verification/{il}.json/v1/verification/all.json | Son 30 günde, termometrelere karşı gün başına ortalama mutlak hata (MAE), ham HRES hatasıyla birlikte | API anahtarı |
Yer adları ve path
Adresler (slug) küçük harf ASCII ve tiredir: istanbul, ankara/cankaya, sanliurfa/birecik, giresun/sebin-karahisar. Kural: ad NFKD ile ayrıştırılıp işaretler atılır (ç→c, ğ→g, ş→s, ö→o, ü→u, â→a), ı ve İ → i, küçük harf; a–z ve 0–9 dışındaki her şey (boşluk, /, nokta…) tek bir - olur (Muradiye / Berkri → muradiye-berkri). Yine de tahmin etmeyin; /v1/places.json'daki her kayıt, doğrudan kullanılacak bir path taşır:
{"name": "Bodrum", "slug": "bodrum", "path": "mugla/bodrum", "lat": 37.065, "lon": 27.498, "elev_m": 331.0}
→ GET /v1/forecast/mugla/bodrum.json
- Bazı ilçe adları birden çok ilde geçer (Gölbaşı, Kemer, Yenişehir…). Aramayı il ile birlikte yapın.
namealanı iller için ASCII'dir ("Istanbul", "Sanliurfa"), ilçelerde karışıktır; görüntülemek için Türkçe yazımlıdisplay_namealanını kullanın, eşleştirmek içinslug'ı.- Tüm istasyonlara 80 km'den uzak ilçelerin tahmini yoktur;
/v1/districts/{il}.json'dahas_forecast: falsegörünür.
Mahalle ve köy arama
Türkiye'deki ~54.000 köy, belde ve mahalle (GeoNames) aranabilir. Bir yerin tahmini, bağlı olduğu ilçenin tahmininin o yerin rakımına göre düzeltilmiş hâlidir. API statik olduğu için arama iki adımda yapılır:
- Adı sadeleştirin (küçük harf; ç→c, ğ→g, ı/İ→i, ö→o, ş→s, ü→u; yalnızca a–z ve 0–9) ve ilk 3 harfini alın:
Yaşamkent → yas. GET /v1/search/yas.jsonile o harflerle başlayan tüm yerleri alın; adı eşleşen kaydı seçin. Aynı ad birden çok yerde olabilir:districtveprovinceile ayırın.- Kaydın
path'i ilçedir:GET /v1/forecast/{path}.json. Her gününtmax,tmin,tmeandeğerlerininvalue,p05vep95'ine kaydınoffsetdeğerini ekleyin.
// GET /v1/search/yas.json (kısaltılmış)
{"prefix": "yas", "entries": [
{"name": "Yaşamkent", "kind": "neighbourhood", "district": "Çankaya", "province": "Ankara",
"path": "ankara/cankaya", "slug": "yasamkent", "lat": 39.86139, "lon": 32.65889, "elev_m": 1100.0,
"elev_diff_m": 1, "offset": {"tmax": 0.0, "tmin": 0.0, "tmean": 0.0}, "has_forecast": true}, …]}
kind:province,district,settlement(köy, belde) ya daneighbourhood(mahalle). İl ve ilçeler de aynı dosyalardadır (düzeltme 0).offset: rakım farkının (elev_diff_m, ±1500 m ile sınırlı) standart düşüş oranıyla sıcaklık karşılığı (100 m başına en yüksek 0,65, en düşük 0,45, ortalama 0,6 °C). Uyarı kurallarını düzeltilmiş değerlere uygulayın.has_forecast: false: ilçenin bu çalıştırmada tahmini yok.- İkinci örnek, sıfır olmayan düzeltme: Yaşlıkavak (Çatak, Van), ilçesinden 1171 m yukarıda;
GET /v1/forecast/van/catak.jsonalın ve her güne{"tmax": -7.6, "tmin": -5.3, "tmean": -7.0}ekleyin. - Sadeleştirmede â/î/û gibi diğer işaretler de atılır (NFKD: Hakkâri → hakkari); 2 harfli adların parçası 2 harflidir (
/v1/search/of.json). Eşleştirmeyinamedeğilslugile yapın. Koordinat uç noktası yok: /v1/places.min.json'daki en yakın satırı alın. - Kurallar ve harf listesi: /v1/search/index.json. Sonuçlar hesaplayıcının kendi aramasından yuvarlama nedeniyle 0,1 °C farklı olabilir.
- Ana sayfadaki arama kutusu da bu dosyaları kullanır; bir yerin adresi
/#ankara/cankaya/yasamkentbiçimindedir. - Yer adları: GeoNames, CC BY 4.0. GeoNames köyleri iyi kapsar ama şehir mahallelerinin yalnızca bir kısmını (~275) adıyla içerir.
Tahmin yanıtı
{
"place": "Çankaya", "province": "Ankara", "kind": "district", "lat": 39.86, "lon": 32.84,
"issued": "2026-09-24", "cycle": "00Z", "model_version": "v1_20260924_0952", "produced_at": "2026-09-24T11:47:43+03:00",
"method": "transfer", "elev_diff_m": 0.0,
"verified_against": { "station": "17131", "distance_km": 11.5 },
"days": [
{ "valid": "2026-09-25", "lead": 1,
"tmax": { "value": 19.1, "p05": 17.5, "p95": 20.9 },
"tmin": { "value": 6.3, "p05": 4.2, "p95": 10.2 },
"tmean": { "value": 12.7, "p05": 11.7, "p95": 15.6 },
"raw_hres": { "tmax": 17.7, "tmin": 6.5, "tmean": 12.1 } }
// … 7 gün
]
}
| Alan | Anlamı |
|---|---|
kind | "place" (il) ya da "district" (ilçe) |
method | İller: "station model" (76 il) ya da "transfer" (kendi istasyonu olmayan 5 il: Bitlis, Kahramanmaraş, Karabük, Sivas, Şırnak; verified_against aktarılan istasyonu ve uzaklığını gösterir). İlçeler: "transfer" (referans istasyondan, HRES'teki fark kullanılarak aktarım) ya da "transfer+lapse" (ayrıca rakım düzeltmesi) |
elev_diff_m | İlçe ile referans istasyon arasındaki rakım farkı; yalnızca transfer+lapse'ta uygulanır |
verified_against | Tahminin dayandığı WMO istasyonu ve uzaklığı |
days[].value | Nokta tahmini (°C) |
days[].p05, p95 | Kalibre edilmiş %90 aralığın alt ve üst sınırı; her zaman p05 ≤ value ≤ p95 |
days[].raw_hres | Modelin başladığı düzeltilmemiş ECMWF HRES değeri; karşılaştırma için |
stations | Yalnızca il yanıtlarında: WMO istasyon numarası → o istasyonun kendi days dizisi |
Sıcaklık dışındaki ürünler (2026-10-10)
Tahmin dosyalarındaki her days[] satırı iki ek blok taşır; saatlik eğri ve hava kalitesi ayrı dosyalardır. Hangi koşunun neyi taşıdığı /v1/status.json içindeki products alanında yazar (raw, precip, hourly, aq).
Ham ECMWF alanları: days[].raw
Yer ve yerel gün için ECMWF HRES koşusunun kendi değerleri: gust_max_ms (günün en yüksek hamlesi), wind_ms ve wind_dir_deg (ortalama rüzgâr; yön, rüzgârın geldiği taraf), cloud_pct, rh_mean_pct, rh_min_pct, precip_mm (günlük toplam), snowfall_mm (su eşdeğeri), snow_depth_cm, solar_kwh_m2, msl_hpa, cape_jkg, precip_type (none / rain / freezing rain / snow / wet snow / rain-snow mix / ice pellets). Düzeltilmemiş ve doğrulanmamış: adındaki raw bunun etiketidir; sıcaklıklar gibi istasyonlara karşı skorlanmaz. Depoda o koşu yoksa null.
Yağış: days[].precip
Her günün 06–06 UTC penceresi (09:00–09:00 İstanbul) için: pop_01, pop_1, pop_5 (≥ 0,1 / 1 / 5 mm olasılıkları, 0–1), mm (beklenen miktar, medyan), q90 (90. yüzdelik), method (model: istasyon satırı; anchor: ilçe için en yakın istasyonun değeri, yağış yereldir). Pencere sıcaklıkların takvim gününden farklıdır; window alanı bunu her satırda tekrar eder.
Saatlik sıcaklık: /v1/hourly/{il}.json, /v1/hourly/{il}/{ilce}.json
Her lead için 24 yerel saat: t servis edilen eğri (HRES'in saatlik şekli, günün en düşük/en yüksek değeri bizim Tmin/Tmax'ımıza eşitlenmiş, artı termometre raporlarına göre saat başına düzeltme), t_raw ECMWF HRES'in kendi eğrisi. Doğrulanmış hata (Eyl–Ekim 2026, 100 istasyon): t 1,57 °C, t_raw 2,15 °C. Köy ve mahalleler için arama kaydındaki offset.tmean her saate eklenir.
curl -s https://havatahmin.abso.net/v1/hourly/ankara/cankaya.json | python3 -c 'import json,sys; d=json.load(sys.stdin)["days"][0]; print(d["valid"], d["t"])'
Hava kalitesi: /v1/aq/{il}.json, /v1/aq/stations.json
İldeki SİM/UHKİA istasyonları için D+1..D+3 günlük ortalama PM2.5, PM10, NO2, O3, SO2 ve CO (µg/m³), 00Z koşusuyla günde bir kez, D−1 sonuna kadarki gözlemlerden. persistence D−1'in gözlenen ortalamasıdır (karşılaştırma için). İstasyonu olmayan il 404 döner; hangi ilin dosyası olduğu /v1/aq/stations.json içindeki file alanında yazar. İstasyonlar koordinatlarıyla ilçe poligonlarına yerleştirilir.
curl -s https://havatahmin.abso.net/v1/aq/izmir.json | python3 -c 'import json,sys; a=json.load(sys.stdin); print(a["issued"], [(s["name"], s["days"][0]["pm25"]) for s in a["stations"]])'
Önümüzdeki iki saat için yağmur (nowcast) API anahtarıyla sunulacak; henüz yayında değil.
Uyarılar (API anahtarı)
Yanıt, tahminle aynı üst bilgiyi ve bir alerts dizisini içerir. Kurallar:
| type | level | Koşul | Ek alan |
|---|---|---|---|
frost | likely | en düşük ≤ 0 °C | tmin |
frost | possible | en düşüğün p05'i ≤ 0 °C | tmin_p05 |
heat | likely | en yüksek ≥ 35 °C | tmax |
heat | possible | en yükseğin p95'i ≥ 35 °C | tmax_p95 |
sudden_change | (yok) | günlük ortalama bir önceki güne göre ≥ 6 °C değişir | delta_tmean |
// GET /v1/alerts/erzurum/aziziye.json
{"place": "Aziziye", "province": "Erzurum", …,
"alerts": [{"valid": "2026-09-29", "type": "frost", "level": "possible", "tmin_p05": -0.3}, …]}
İl uyarısı yalnızca ilin ana istasyonundaki noktaya bakar. "Erzurum'da herhangi bir yerde don var mı?" sorusu için ilin tüm ilçelerini sorgulayın. Eşikler yayınlanan (bir ondalığa yuvarlanmış) değerlere uygulanır: yanıtta görünen 0,0 don, 35,0 sıcak uyarısını tetikler; tahmin dosyasındaki değerlerle birebir tutarlıdır.
Doğrulama (API anahtarı)
Modelin kendi karnesi: canlı tahminlerin son 30 gününde, her tahmin günü (lead) için istasyon termometresine karşı ortalama mutlak hata ve sapma, yanında ham HRES hatası ve %90 aralığın gerçekte tuttuğu oran. Bir çalıştırma henüz doğrulanmadıysa 404 döner; kendi istasyonu olmayan 5 aktarım ilinin (Bitlis, Kahramanmaraş, Karabük, Sivas, Şırnak) doğrulaması yoktur, /v1/verification/all.json hepsini bir arada verir.
Hata kodları
| Kod | Ne zaman | Gövde |
|---|---|---|
400 | Geçersiz yol: .., //, ters eğik çizgi ya da kodlanmış nokta/eğik çizgi (%2e, %2f). Önce bu denetlenir. | {"error": "invalid path", "docs": "…"} |
301 | /il/ankara → /il/ankara/, /api → /api/ (HTML sayfaları; sorgu dizesi korunur) | – |
404 | Bilinmeyen yol ya da yer: ad yanlış yazılmış, ya da bu çalıştırmada bu yer için tahmin yok (/v1/status.json'daki missing). Anahtar denetiminden önce gelir: yanlış bir yola anahtar gönderseniz de 404 alırsınız. /il/… sayfalarında HTML döner. 30 saniye önbelleklenir. | {"error": "not found", "hint": "unknown slug, or no forecast in this run (see /v1/status.json missing); slugs: /v1/places.json", "docs": "…"} |
401 | Bilinen bir anahtarlı yola (/v1/alerts, /v1/verification) anahtarsız istek | {"error": "api key required: send x-api-key header or ?key=", "key_request_url": "…", "docs": "…"} |
403 | Gönderilen anahtar tanınmıyor (anahtarsız yollarda bile) | {"error": "invalid api key", "key_request_url": "…", "docs": "…"} |
403 | İstek sınırı aşıldı (aşağıya bakın); her yolda, anahtarlı ya da anahtarsız | JSON: "rate limit exceeded ..." ve key_request_url |
İstek sınırı ve önbellek
- IP başına 5 dakikada 300 istek; anahtar bu sınırı yükseltmez, anahtarlı ve anahtarsız istekler birlikte sayılır. Aşan IP, hızı düşene kadar
403ve"rate limit exceeded"ile başlayan bir JSON yanıt alır; yanıttakikey_request_urlalanı iletişim formunu gösterir: bu API üzerine bir şey geliştiriyorsanız ücretsiz anahtar isteyin ve beklenen istek hacminizi yazın. - Sıra: geçersiz yol →
400; bilinmeyen yer →404; sonra anahtar: yok →401(yalnızca anahtarlı yollarda), geçersiz →403(her yolda). Anahtarsız istekler serbest uç noktalarda serbesttir. - Yanıtlar 5 dakika önbellekte tutulur (
Cache-Control: max-age=300). Veri günde iki kez değişir; kendi tarafınızda da önbellekleyin. - Tüm il ve ilçeleri çekmek için ~1.050 istek gerekir: sınır nedeniyle istekleri 20 dakikaya yayın (anahtar bunu değiştirmez).
- Yeni veri gelip gelmediğini anlamak için yalnızca
/v1/status.json'dakilatest_run'a bakın.
Kod örnekleri
Python (yalnızca standart kütüphane)
import json, urllib.request, urllib.error
BASE = "https://havatahmin.abso.net"
import re, unicodedata
def slug(s): # "Şebin Karahisar" -> "sebin-karahisar" (API'nin kuralı)
s = unicodedata.normalize("NFKD", s.replace("ı", "i").replace("İ", "i"))
s = "".join(c for c in s if not unicodedata.combining(c)).lower()
return "-".join(re.findall(r"[a-z0-9]+", s))
def get(path, key=None):
req = urllib.request.Request(BASE + path, headers={"x-api-key": key} if key else {})
try:
with urllib.request.urlopen(req) as r:
return json.load(r)
except urllib.error.HTTPError as e:
if e.code == 404:
return None # son çalıştırmada tahmin yok
raise
def find(name): # "Bodrum" -> "mugla/bodrum" (slug ile eşleştirin, name ile değil)
want = slug(name)
for p in get("/v1/places.json")["provinces"]:
if p["slug"] == want:
return p["path"]
for d in p["districts"]:
if d["slug"] == want:
return d["path"]
path = find("Bodrum")
f = path and get(f"/v1/forecast/{path}.json")
for d in (f or {}).get("days", []):
print(d["valid"], d["tmin"]["value"], d["tmax"]["value"])
JavaScript (tarayıcı ya da Node 22; dosya adı .mjs, yerleşik fetch)
// forecast.mjs — node forecast.mjs
const BASE = "https://havatahmin.abso.net";
const r = await fetch(`${BASE}/v1/forecast/izmir.json`);
if (r.status === 404) console.log("tahmin yok");
else {
const f = await r.json();
for (const d of f.days) console.log(d.valid, d.tmin.value, d.tmax.value);
}
Bir ilin tüm ilçelerinde don riski (anahtarla)
import json, urllib.request
KEY, BASE = "ANAHTARINIZ", "https://havatahmin.abso.net"
get = lambda p: json.load(urllib.request.urlopen(urllib.request.Request(BASE + p, headers={"x-api-key": KEY})))
for d in get("/v1/districts/erzurum.json")["districts"]:
if d["has_forecast"]:
frost = [a for a in get(f"/v1/alerts/{d['path']}.json")["alerts"] if a["type"] == "frost"]
if frost:
print(d["name"], [(a["valid"], a["level"]) for a in frost])
Makineler ve AI ajanları
- /openapi.json: OpenAPI 3.1 tanımı (kod üreticiler ve araç çağıran ajanlar için)
- /llms.txt ve /llms-full.txt: ajanlar için Markdown özet ve tam başvuru
- /.well-known/api-catalog (RFC 9727), /.well-known/ard.json (ARD 0.91) ve /.well-known/ai-catalog.json: ajan katalogları
- /index.json: uç noktalar, kapsam, hatalar, sınırlar ve lisans makine tarafından okunabilir biçimde
- /v1/places.min.json: il ve ilçeler
[path, name, lat, lon]satırları hâlinde (~45 KB); koordinattan en yakın yeri bulmak için - /sitemap.xml: tüm il ve ilçe sayfaları
Accept: text/markdownile/istenirse302ile/llms-full.txt'ye yönlendirilir (q değerleri dikkate alınır)
Bilinmesi gerekenler
- İl tahmini, ilin ana istasyonundaki nokta tahminidir; il geneli için ilçelere bakın.
latest_runbir günden eskiyse ilk günler geçmişte kalmıştır;validtarihine göre süzün.- İlçe tahminleri termometresi olan en yakın uygun istasyondan aktarılır; doğrudan ölçülmez.
- Tahminler olduğu gibi sunulur; hayati kararlar için resmi kaynaklarla (MGM) birlikte kullanın.