Blog · Adres verisi ve rehberler

Adres API Örneği: Node.js ve Python ile İlk İstek

Adres API örneği: kayıt ve API anahtarından curl, Node.js fetch ve Python requests ile ilk başarılı yanıta kadar adım adım hızlı başlangıç rehberi.

4 dk okuma

Bu yazıda bir adres API örneği üzerinden hesap açmaktan ilk başarılı yanıta kadar olan yolu adım adım izleyeceğiz. Önce bir API anahtarı alacak, ardından curl ile terminalden istek atacak, sonra aynı isteği Node.js ve Python ile kodlayacağız. Son bölümde yanıtların ortak yapısını, yani data ve meta alanlarını inceleyeceğiz. Bu yapıyı baştan doğru okursanız sonraki entegrasyon adımları da kolaylaşır.

Başlamadan önce: neye ihtiyacınız var?

Örnekleri çalıştırmak için şunlar yeterli:

  • Bir API Türkiye hesabı ve bu hesaptan oluşturulmuş bir API anahtarı
  • Terminalde curl
  • Node.js tarafı için yerleşik fetch desteği olan güncel bir Node.js sürümü
  • Python tarafı için Python 3 ve requests paketi (pip install requests)

Resmî bir SDK paketi npm veya PyPI'da yayımlı değildir. Bu yüzden örneklerin tamamı düz HTTP ve JSON ile yazıldı. Ek bir kütüphane öğrenmeniz gerekmez.

1. Adım: Kayıt ve API anahtarı

Ücretsiz kayıt sayfasından hesabınızı oluşturun. Core paketi ücretsiz başlangıç paketidir. Tam adres kataloğuna ve akıllı aramaya erişim sağlar. Paketiniz onaylandıktan sonra müşteri panelinden bir API anahtarı oluşturabilirsiniz. Anahtar apt_live_... biçimindedir.

Anahtarı koda gömmek yerine bir ortam değişkeninde tutun:

# macOS / Linux
export APITURKIYE_KEY="apt_live_..."
# Windows PowerShell
$env:APITURKIYE_KEY="apt_live_..."

Dikkat etmeniz gereken üç kural var:

  1. Anahtarı tarayıcı koduna koymayın. İstekleri her zaman sunucu tarafından yapın.
  2. Anahtarı Git deposuna commit etmeyin. .env dosyalarını .gitignore içine ekleyin.
  3. Anahtarı loglara yazmayın. İstek loglarında başlıkları maskeleyin.

Anahtar yönetimini daha ayrıntılı öğrenmek isterseniz API anahtarı nedir ve nasıl güvenli kullanılır yazımıza göz atabilirsiniz.

2. Adım: curl ile ilk istek

Kimlik doğrulama tek bir başlıkla yapılır: X-API-Key. Başka bir yetkilendirme başlığı kullanılmaz. Temel adres https://api.apiturkiye.com, adres uçları ise /v1 önekiyle başlar.

En basit istek il listesini getirmektir:

curl -i "https://api.apiturkiye.com/v1/provinces" \
  -H "X-API-Key: $APITURKIYE_KEY"

-i bayrağı yanıt başlıklarını da gösterir. HTTP/... 200 satırını ve content-type: application/json; charset=utf-8 başlığını görüyorsanız ilk isteğiniz başarılı olmuştur. Gövde şuna benzer:

{ "data": [ { "stableId": "apt_v1_prv_...", "code": 1, "name": "Adana" } ] }

İl kodu (code), araç plaka koduyla aynıdır. Bu nedenle İstanbul'un ilçelerini almak için 34 kodunu kullanabilirsiniz:

curl "https://api.apiturkiye.com/v1/provinces/34/districts" \
  -H "X-API-Key: $APITURKIYE_KEY"

Başlığı unutursanız ya da anahtar hatalıysa 401 yanıtı alırsınız:

{ "error": { "code": "invalid_api_key", "message": "Geçerli bir X-API-Key başlığı zorunludur." } }

Node.js fetch ile adres API örneği

Aynı iki isteği şimdi Node.js ile yazalım. Aşağıdaki dosyayı ilk-istek.mjs adıyla kaydedin. .mjs uzantısı, üst düzey await kullanabilmeniz için gereklidir.

// ilk-istek.mjs
const API_BASE = "https://api.apiturkiye.com";
const apiKey = process.env.APITURKIYE_KEY;

if (!apiKey) {
  throw new Error("APITURKIYE_KEY ortam değişkeni tanımlı değil.");
}

async function getJson(path, params = {}) {
  const url = new URL(path, API_BASE);
  for (const [key, value] of Object.entries(params)) {
    url.searchParams.set(key, String(value));
  }

  const res = await fetch(url, { headers: { "X-API-Key": apiKey } });
  const body = await res.json().catch(() => ({}));

  if (!res.ok) {
    const code = body?.error?.code ?? "unknown_error";
    throw new Error(`HTTP ${res.status} (${code})`);
  }
  return body;
}

const { data: provinces } = await getJson("/v1/provinces");
console.log(`Toplam il: ${provinces.length}`);

const { data: districts } = await getJson("/v1/provinces/34/districts");
for (const d of districts.slice(0, 5)) {
  console.log(d.code, d.name, d.stableId);
}

Çalıştırmak için:

node ilk-istek.mjs

Katalogda 81 il bulunduğundan ilk satırda bu sayıyı görmelisiniz. Hata durumunda karar verirken message metnine değil, HTTP durum koduna ve error.code değerine bakın. Mesaj metni zamanla değişebilir, kod ise programatik kontrol için tasarlanmıştır.

Python requests ile aynı istek

Python tarafında bir Session kullanmak, başlığı her istekte tekrar yazmanızı önler ve bağlantıları yeniden kullanır:

# ilk_istek.py
import os
import requests

API_BASE = "https://api.apiturkiye.com"
API_KEY = os.environ["APITURKIYE_KEY"]

session = requests.Session()
session.headers.update({"X-API-Key": API_KEY})


def get_json(path, params=None):
    res = session.get(f"{API_BASE}{path}", params=params, timeout=10)
    if not res.ok:
        try:
            code = res.json().get("error", {}).get("code", "unknown_error")
        except ValueError:
            code = "unknown_error"
        raise RuntimeError(f"HTTP {res.status_code} ({code})")
    return res.json()


provinces = get_json("/v1/provinces")["data"]
print(f"Toplam il: {len(provinces)}")

districts = get_json("/v1/provinces/34/districts")["data"]
for d in districts[:5]:
    print(d["code"], d["name"], d["stableId"])
python ilk_istek.py

timeout parametresini boş bırakmayın. Aksi hâlde ağ sorunlarında isteğiniz süresiz bekleyebilir.

Yanıt zarfı: data ve meta

Başarılı /v1 yanıtlarının hepsi aynı zarfı kullanır:

  • data: Asıl içerik. Liste uçlarında bir dizidir, adres doğrulama gibi uçlarda bir nesnedir.
  • meta: Uca göre gelen ek bilgi. Her yanıtta bulunmaz.

/v1 yanıtlarında success alanı yoktur. Başarıyı HTTP durum koduyla anlayın. success alanını kontrol eden bir kod yazarsanız her yanıtı yanlışlıkla başarısız sayabilirsiniz.

meta ne zaman gelir?

İl, ilçe ve mahalle listeleri ilgili kapsamın tamamını tek yanıtta döner. Bu üç uçta sayfalama ve meta.nextCursor yoktur. Cadde/sokak ve dış kapı listeleri ise cursor ile sayfalanır:

curl "https://api.apiturkiye.com/v1/neighborhoods/20239/streets?limit=50" \
  -H "X-API-Key: $APITURKIYE_KEY"
{
  "data": [ { "stableId": "apt_v1_str_...", "code": "173405", "name": "Moda Caddesi" } ],
  "meta": { "nextCursor": "eyJuYW1lLi4u" }
}

Sonraki sayfa için meta.nextCursor değerini cursor parametresiyle gönderin. Değer null ise son sayfadasınız. limit 1 ile 100 arasında olabilir. Örnekteki kodlar yalnız yapıyı göstermek içindir. Kendi uygulamanızda liste yanıtlarından aldığınız gerçek kodları kullanın.

Python ile tüm sokakları dolaşan kısa bir döngü şöyle yazılabilir. Önceki bölümdeki get_json fonksiyonunu kullanır:

def all_streets(neighborhood_code):
    cursor = None
    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor
        body = get_json(f"/v1/neighborhoods/{neighborhood_code}/streets", params)
        yield from body["data"]
        cursor = body["meta"]["nextCursor"]
        if not cursor:
            break

Akıllı adres aramasında (/v1/autocomplete) meta, normalize edilmiş sorguyu ve uygulanan limit değerini taşır. Bu uç cursor kullanmaz.

Hangi alanı saklamalısınız?

AlanNe işe yarar?
stableIdKalıcı ve sürümden bağımsız kimliktir. Veritabanınızda referans olarak bunu saklayın.
codeKaynak kodudur, eşleştirme için korunur. İl kodu sayısal, diğer kodlar metindir.
nameGörüntüleme içindir. Aynı ad farklı yerlerde bulunabileceği için kimlik olarak kullanmayın.

Örneğin bir kullanıcının seçtiği ilçeyi kaydederken yalnız name değerini tutarsanız aynı adı taşıyan başka bir kayıtla karışma riski doğar. stableId ise bu belirsizliği ortadan kaldırır.

Hata zarfı

Hatalı yanıtlarda data yerine error nesnesi gelir. İlk denemelerde en sık karşılaşacağınız durumlar şunlardır:

Durumerror.codeNe yapmalı?
401invalid_api_keyBaşlık adını (X-API-Key) ve anahtar değerini kontrol edin.
403insufficient_scopeUç, paketinizde olmayan bir yetki istiyor. requiredScope alanına bakın.
403subscription_inactivePaketiniz henüz aktif değil.
400invalid_code, invalid_cursorYol veya sorgu parametresini düzeltin.
429rate_limit_exceededRetry-After başlığındaki süre kadar bekleyin.
429quota_exceededresetAt zamanını bekleyin. Aynı çağrıyı sürekli tekrarlamayın.

401 ve 403 yanıtlarında otomatik yeniden deneme yapmayın. Anahtar, yetki ya da paket düzeltilmeden sonuç değişmez. Yeniden deneme mantığını yalnız 429 gibi geçici durumlar için kurun.

Sonraki adımlar

İlk isteğiniz çalıştıysa artık il → ilçe → mahalle → cadde/sokak → dış kapı zincirini aynı kalıpla dolaşabilirsiniz. Bir sonraki mantıklı adım, bu uçları kullanıcıya sunan bir form kurmaktır. Bunun için il, ilçe ve mahalle seçimli adres formu yazımız iyi bir devam olur. Hazır bileşen örneklerini de adres seçici bileşenler sayfasında bulabilirsiniz.

Tüm uçların parametrelerini ve yanıt alanlarını API dokümantasyonunda inceleyebilirsiniz. Henüz anahtarınız yoksa ücretsiz kayıt olup API anahtarınızı alarak bu yazıdaki örnekleri hemen çalıştırabilirsiniz.