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ıç

  1. Yerinizin path değerini /v1/places.json'dan bulun (ör. Bodrum için mugla/bodrum).
  2. Tahmini alın: GET https://havatahmin.abso.net/v1/forecast/mugla/bodrum.json
  3. days dizisindeki 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 adreshttps://havatahmin.abso.net (yalnızca HTTPS)
BiçimUTF-8 JSON, sıkıştırılmış (gzip/brotli) sunulur
GüncellemeGü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 ufku7 gün; lead 1, issued tarihinden sonraki gündür
BirimlerSıcaklıklar °C, mesafeler km, rakımlar m
Saat dilimiissued 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).
LisansTahmin verileri CC BY 4.0 ile sunulur: kaynak olarak havatahmin.abso.net'i gösterin; yer adları GeoNames (CC BY 4.0).
CORSAçı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
Kapsam81 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

YolDöndürürErişim
/v1/status.jsonSon ç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.jsonTüm iller ve ilçeleri: name, slug, path, enlem, boylam, rakımanahtarsız
/v1/search/{abc}.jsonAd arama: iller, ilçeler, ~54.000 köy ve mahalle; nasıl kullanılıranahtarsız
/v1/districts/{il}.jsonBir ilin ilçeleri; her biri path ve has_forecast ileanahtarsız
/v1/forecast/{il}.jsonİlin 7 günlük tahmini ve ildeki her istasyonun tahminianahtarsı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 listesianahtarsı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 birlikteAPI 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

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:

  1. 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.
  2. GET /v1/search/yas.json ile o harflerle başlayan tüm yerleri alın; adı eşleşen kaydı seçin. Aynı ad birden çok yerde olabilir: district ve province ile ayırın.
  3. Kaydın path'i ilçedir: GET /v1/forecast/{path}.json. Her günün tmax, tmin, tmean değerlerinin value, p05 ve p95'ine kaydın offset değ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}, …]}

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
  ]
}
AlanAnlamı
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_againstTahminin dayandığı WMO istasyonu ve uzaklığı
days[].valueNokta tahmini (°C)
days[].p05, p95Kalibre edilmiş %90 aralığın alt ve üst sınırı; her zaman p05 ≤ value ≤ p95
days[].raw_hresModelin başladığı düzeltilmemiş ECMWF HRES değeri; karşılaştırma için
stationsYalnı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:

typelevelKoşulEk alan
frostlikelyen düşük ≤ 0 °Ctmin
frostpossibleen düşüğün p05'i ≤ 0 °Ctmin_p05
heatlikelyen yüksek ≥ 35 °Ctmax
heatpossibleen yükseğin p95'i ≥ 35 °Ctmax_p95
sudden_change(yok)günlük ortalama bir önceki güne göre ≥ 6 °C değişirdelta_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ı

KodNe zamanGövde
400Geç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)–
404Bilinmeyen 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": "…"}
401Bilinen 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": "…"}
403Gö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ızJSON: "rate limit exceeded ..." ve key_request_url

İstek sınırı ve önbellek

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ı

Bilinmesi gerekenler