Blog · Adres verisi ve rehberler

API Nedir? Adres Verisiyle REST API'ye Giriş

API nedir, nasıl çalışır? İstemci, uç nokta, HTTP metodu, JSON yanıt, API anahtarı ve durum kodlarını adres verisi örneğiyle, çalışan kodlarla öğrenin.

5 dk okuma

Bir formda il seçtiğinizde ilçe listesi kendiliğinden dolar. Bunun arka planında iki program birbiriyle konuşur. Bu yazıda "API nedir?" sorusunu tek bir somut örnekle yanıtlıyoruz: Türkiye adres verisini sunan bir REST API'ye ilk isteği göndermek. Yazının sonunda isteğin ve yanıtın parçalarını okuyabilecek, anahtarınızı güvenle kullanabilecek ve hata kodlarına göre doğru kararı veren küçük bir kod yazmış olacaksınız.

API nedir ne işe yarar?

API (Application Programming Interface, uygulama programlama arayüzü), bir yazılımın başka bir yazılımdan veri ya da hizmet istemesi için tanımlanmış kurallardır. Bu kurallar üç şeyi belirler: hangi adrese istek gönderileceğini, isteğin hangi biçimde olacağını ve karşılığında ne döneceğini. API'yi iki taraf arasındaki bir sözleşme gibi düşünebilirsiniz. Sözleşme korunduğu sürece iki taraf da kendi iç yapısını diğerini bozmadan değiştirebilir.

Pratikteki faydası şudur: Bir veriyi kendiniz derleyip güncel tutmak yerine, onu düzenli olarak sunan bir servisten istersiniz. Türkiye'de 81 il ve 973 ilçe var. Bunların altında mahalleler, cadde/sokaklar ve dış kapılar bulunur. Bu hiyerarşiyi kendi veritabanınızda tutmak, güncellemeleri izlemek ve doğruluğunu korumak ayrı bir iş yüküdür. Bir adres API'si bu işi tek bir arayüzün arkasına toplar.

İstemci, sunucu ve uç nokta

Her API konuşmasında üç temel kavram vardır:

  • İstemci: İsteği başlatan taraftır. Sizin backend uygulamanız, bir betik ya da terminaldeki curl komutu olabilir.
  • Sunucu: İsteği karşılayan ve yanıt üreten taraftır. Örneğimizde sunucu https://api.apiturkiye.com adresindedir.
  • Uç nokta (endpoint): Sunucuda belirli bir kaynağı temsil eden yoldur. Örneğin /v1/provinces illeri temsil eder.

REST yaklaşımında kaynaklar URL ile adlandırılır ve ilişkiler yolun içinde görünür. Adres hiyerarşisi bunu iyi gösterir:

Uç noktaDöndürdüğü kaynak
GET /v1/provincesİller
GET /v1/provinces/{code}/districtsBir ilin ilçeleri
GET /v1/districts/{code}/neighborhoodsBir ilçenin mahalleleri
GET /v1/neighborhoods/{code}/streetsBir mahallenin cadde/sokakları
GET /v1/streets/{code}/buildingsBir sokağın dış kapıları

{code} bir yol parametresidir. Bir önceki yanıttan aldığınız kodu buraya yazarsınız. /v1 öneki ise API sürümünü gösterir. Böylece ileride yapılacak köklü değişiklikler mevcut entegrasyonları bozmaz. Bu katmanların her birinin ne anlama geldiğini Türkiye adres verilerinin yapısı yazımızda ayrıntılı anlattık.

Bir REST API isteğinin parçaları

Bir HTTP isteği dört parçadan oluşur:

  1. Metot: İsteğin amacını belirtir. GET veri okumak içindir; adres listelerinin tamamı GET ile alınır. POST ise sunucuya veri gönderip bir işlem yaptırmak içindir. Örneğin POST /v1/addresses/validate, adres bileşenlerini alıp katalogda kontrol eder (Pro ve üzeri paketlerde).
  2. URL: Temel adres, yol ve gerekiyorsa sorgu parametrelerinden oluşur. Örneğin akıllı arama ucunda ?q=Bağdat&provinceCode=34 gibi parametreler aramayı tarif eder.
  3. Başlıklar (headers): İstekle ilgili ek bilgilerdir. Kimlik doğrulama burada yapılır: X-API-Key. Gövde gönderen isteklerde Content-Type: application/json başlığı da eklenir.
  4. Gövde (body): Yalnız POST gibi veri gönderen isteklerde bulunur.

Ham hâliyle bir istek şöyle görünür:

GET /v1/provinces/34/districts HTTP/1.1
Host: api.apiturkiye.com
X-API-Key: apt_live_...

Sunucunun yanıtı da üç parçadan oluşur. Önce bir durum kodu gelir (ör. 200). Ardından yanıt başlıkları gelir; burada Content-Type: application/json; charset=utf-8 yer alır. Son olarak JSON biçimindeki yanıt gövdesi gelir.

JSON yanıtı okumak

JSON, anahtar–değer çiftlerinden ve dizilerden oluşan, hem insanın hem makinenin kolayca okuyabildiği bir metin biçimidir. İl listesinin yanıtı şuna benzer:

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

Bu yanıtı okurken dikkat edilecek noktalar şunlardır:

  • data: Asıl içerik her zaman bu alandadır. Bazı uçlar ek olarak meta alanı döner. Örneğin sayfalı listelerde sonraki sayfa için meta.nextCursor bulunur.
  • stableId: Kaydın sürümden bağımsız, kalıcı kimliğidir. Kendi veritabanınızda referans olarak bunu saklayın.
  • code: Bir sonraki isteği kurarken kullandığınız koddur. İl kodu, plaka koduyla aynıdır (34 İstanbul gibi).
  • name: Kullanıcıya göstereceğiniz addır.

/v1 yanıtlarında success gibi bir alan yoktur. İsteğin başarılı olup olmadığını HTTP durum kodundan anlarsınız. Bu yazıdaki örnek kodlar ve değerler yanıtın biçimini göstermek içindir. Uygulamanızda her zaman gerçek yanıtlardan aldığınız kodları kullanın.

API anahtarı ile kimlik doğrulama

Sunucu, isteği kimin gönderdiğini ve ona hangi yetkilerin tanındığını bilmek ister. API Türkiye'de bunun yolu API anahtarıdır. Anahtarı ücretsiz kayıt sonrasında müşteri panelinden oluşturur ve her istekte X-API-Key başlığıyla gönderirsiniz.

Anahtar bir şifre gibi korunmalıdır:

  • Kodun içine yazmayın; ortam değişkeninden okuyun.
  • Git deposuna ve loglara yazmayın.
  • Tarayıcı koduna koymayın. Frontend geliştiriyorsanız akış şöyle olmalıdır: tarayıcı kendi backend'inize istek atar, backend anahtarı ekleyerek API Türkiye'ye istek atar ve sonucu tarayıcıya iletir. Böylece anahtar kullanıcının cihazına hiç ulaşmaz.

Anahtar eksik ya da geçersizse sunucu 401 döner. Anahtar geçerli olduğu hâlde paketiniz o özelliği kapsamıyorsa 403 döner.

İlk isteğiniz: curl ve Python

Önce anahtarı ortam değişkenine koyun, ardından il listesini isteyin. -i seçeneği, gövdeyle birlikte durum satırını ve yanıt başlıklarını da gösterir:

export APITURKIYE_KEY="apt_live_..."

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

Çıktının ilk satırında 200 durum kodunu görmelisiniz. Başlıklar arasında content-type değerinin JSON olduğunu, gövdede de data dizisini göreceksiniz.

Aynı isteğin Python karşılığı:

import os
import requests

res = requests.get(
    "https://api.apiturkiye.com/v1/provinces",
    headers={"X-API-Key": os.environ["APITURKIYE_KEY"]},
    timeout=10,
)

print(res.status_code, res.headers.get("Content-Type"))

if res.ok:
    for province in res.json()["data"]:
        print(province["code"], province["name"])
else:
    print("Hata kodu:", res.json().get("error", {}).get("code"))

Listeden bir il kodu seçip /v1/provinces/34/districts ucunu çağırırsanız, hiyerarşide bir adım aşağı inmiş olursunuz. İl–ilçe verisini JSON olarak almanın ayrıntıları için il ilçe listesi yazımıza bakabilirsiniz.

Durum kodlarını okumak

Durum kodu, yanıtın ilk ve en önemli bilgisidir. 2xx başarı, 4xx istemci tarafındaki bir sorun, 5xx sunucu tarafındaki bir sorun anlamına gelir. Hata yanıtlarında gövde şu biçimdedir:

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

Kararlarınızı message metnine göre değil, HTTP durumuna ve error.code değerine göre verin. Mesaj metni değişebilir; kod ise sözleşmenin parçasıdır.

DurumÖrnek error.codeNe yapmalı?
200—Gövdedeki data alanını işleyin.
400invalid_request, invalid_queryParametreleri ve gövdeyi düzeltin; aynı isteği tekrarlamayın.
401invalid_api_keyAnahtarı kontrol edin; otomatik tekrar yapmayın.
403insufficient_scope, subscription_inactivePaketinizi ve yetkinizi kontrol edin.
404dataset_not_foundİstediğiniz kaynak yok; kimliği kontrol edin.
429rate_limit_exceededRetry-After başlığındaki süre kadar bekleyip yeniden deneyin.
429quota_exceededGövdedeki resetAt zamanını bekleyin; sürekli yeniden denemeyin.
503catalog_unavailableGeçici bir durumdur; bekleyip tekrar deneyin, servis durumu sayfasına bakın.

Bir ayrıntıya dikkat edin: Adres doğrulama ucunda eşleşmeyen bir adres hata sayılmaz. Yanıt yine 200 döner ve gövdede data.valid: false yer alır. "İstek başarılı" ile "adres geçerli" farklı sorulardır.

Bu kuralları Node.js tarafında küçük bir yardımcı fonksiyonda toplayabilirsiniz. Dosyayı ilk-istek.mjs olarak kaydedip Node.js 18 veya üzeri bir sürümle node ilk-istek.mjs komutuyla çalıştırabilirsiniz:

const API_BASE = "https://api.apiturkiye.com";

async function apiGet(path) {
  const res = await fetch(`${API_BASE}${path}`, {
    headers: { "X-API-Key": process.env.APITURKIYE_KEY },
  });

  const body = await res.json().catch(() => null);
  if (res.ok) return body;

  const code = body?.error?.code ?? "unknown_error";

  switch (res.status) {
    case 400:
      throw new Error(`İstek hatalı (${code}): parametreleri kontrol edin.`);
    case 401:
    case 403:
      throw new Error(`Yetki sorunu (${code}): anahtarı ve paketi kontrol edin.`);
    case 429: {
      const retryAfter = res.headers.get("Retry-After");
      throw new Error(`Sınır aşıldı (${code}). Retry-After: ${retryAfter ?? "-"}`);
    }
    default:
      throw new Error(`HTTP ${res.status} (${code})`);
  }
}

const { data } = await apiGet("/v1/provinces/34/districts");
console.log(data.map((d) => `${d.code} ${d.name}`).join("\n"));

İlk API entegrasyonu için kontrol listesi

Deneme isteklerinden gerçek bir API entegrasyonuna geçerken şu maddeleri gözden geçirin:

  • API anahtarı ortam değişkeninde duruyor; depoda, logda ve tarayıcı kodunda yer almıyor.
  • Tüm istekler sunucu tarafından gönderiliyor.
  • Başarı kontrolü durum koduyla yapılıyor; hata kararları error.code değerine dayanıyor.
  • 401 ve 403 yanıtlarında otomatik tekrar yapılmıyor, 429 yanıtlarında bekleme kuralı uygulanıyor.
  • Kendi veritabanınızda adres kayıtlarına referans olarak stableId saklanıyor.
  • Sorgularda kodlar elle yazılmıyor, önceki yanıtlardan alınıyor.
  • HTTP istemcisinde bir zaman aşımı (timeout) tanımlı.

Sonraki adım

Artık bir API isteğinin hangi parçalardan oluştuğunu, JSON yanıtın nasıl okunacağını ve durum kodlarına göre nasıl karar verileceğini biliyorsunuz. Kendi anahtarınızla denemek için ücretsiz kayıt olabilir, tüm uçları ve parametreleri API dokümantasyonunda inceleyebilirsiniz. Öğrendiklerinizi bir arayüze dökmek isterseniz il, ilçe ve mahalle seçimli adres formu yazımız iyi bir devam noktası olur.