Geliştirici Dokümantasyonu

ALO 153 Web API

Tatvan Belediyesi kurumsal web sitesinin ALO 153 Destek Merkezi ile entegrasyonu için hazırlanmış teknik dokümandır. Vatandaşın talep oluşturması, kendi kaydını sorgulaması ve takip etmesi için gereken tüm uçları içerir.

Bu doküman, Tatvan Belediyesi kurumsal web sitesinin ALO 153 Destek Merkezi ile entegrasyonu için hazırlanmıştır. Vatandaş; yeni talep oluşturur, kendi talebini sorgular, aşamasını görür, iletişim bilgilerini düzeltir, yanıt yazar, çözüldü olarak işaretler veya kaydını kapatır.

Base URL https://153.vegabyte.com.tr/api/web/v1
Biçim JSON (istek ve yanıt)
Kimlik doğrulama X-API-Key başlığı
Karakter kodlaması UTF-8
Çevrimiçi sürüm https://153.vegabyte.com.tr/api-dokumantasyon

Bu dokümanın her zaman güncel hâli yukarıdaki adreste yayımlanır; giriş gerektirmez. Elinizdeki kopya eskimiş olabilir, kuşkuya düştüğünüzde çevrimiçi sürümü esas alın.


1. Kimlik Doğrulama

Her istek (yalnızca /health hariç) geçerli bir API anahtarı gerektirir. Anahtar, yönetim panelinden Yönetim → API Anahtarları ekranından üretilir.

X-API-Key: tvb_xxxxxxxxxxxx.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

Kritik güvenlik kuralları

  • Anahtar yalnızca sunucu tarafında saklanmalıdır. Tarayıcıya inen JavaScript'e, mobil pakete veya herkese açık depoya konulmamalıdır. Web sitesi, tarayıcıdan gelen isteği kendi sunucusunda karşılayıp API'ye sunucu-sunucu (server-to-server) iletmelidir.
  • Anahtar yalnızca üretildiği anda bir kez gösterilir; sistemde geri çevrilemez biçimde (özet olarak) saklanır. Kaybedilirse yenisi üretilir.
  • Anahtar sızarsa panelden anında devre dışı bırakılabilir.
  • Anahtar URL'de (query string) gönderilmemelidir; yalnızca başlıkta.

Hata yanıtları (kimlik doğrulama)

Durum Anlamı
401 Anahtar eksik veya geçersiz
403 Anahtar devre dışı bırakılmış

2. Hız Sınırları (Rate Limit)

Uç grubu Sınır
Yeni talep (POST /tickets) Ziyaretçi başına dakikada 3 istek
Sorgulama (lookup, tickets/{token}, neighborhoods) Ziyaretçi başına dakikada 30 istek
İşlem (update, reply, resolve, close) Ziyaretçi başına dakikada 10 istek
Başarısız eşleşme (yanlış talep no/telefon) Ziyaretçi başına 10 başarısız denemeden sonra 5 dk kilit

Sınır aşıldığında 429 Too Many Requests döner. Web sitesi bu durumu kullanıcıya "Çok fazla deneme yaptınız, lütfen biraz sonra tekrar deneyin" şeklinde göstermelidir.

2.1 X-Client-IP — ziyaretçiyi bildirin (önemli)

İstekler web sitesinin sunucusundan geldiği için, API tüm ziyaretçileri varsayılan olarak tek bir IP gibi görür. Bu durumda bir kişinin denemeleri sitenin tüm ziyaretçilerini kilitler.

Bunu önlemek için her istekte son kullanıcının IP adresini iletin:

X-Client-IP: 88.240.15.72

Sınırlar o ziyaretçiye özel uygulanır; bir ziyaretçinin kilitlenmesi diğerlerini etkilemez. Başlık gönderilmezse tüm trafik ortak kotayı paylaşır.

Bu başlık yalnızca anahtar sahibi güvenilen istemciden kabul edilir. Değeri son kullanıcının gerçek IP'si olmalıdır ($_SERVER['REMOTE_ADDR'] veya proxy arkasındaysanız doğruladığınız X-Forwarded-For değeri).


3. Sahiplik Doğrulaması

Vatandaşın yalnızca kendi talebine erişebilmesi için her istek sahiplik kanıtı taşır. İki yöntemden biri kullanılır:

  1. Takip token'ıtrack_token: talep oluşturulurken üretilen, tahmin edilemez benzersiz değer (vatandaşa SMS/e-posta ile giden takip bağlantısında yer alır).
  2. Talep numarası + telefonticket_number + phone: ikisi birlikte eşleşmelidir.

Kanıt eşleşmezse 404 döner; talebin var olup olmadığı dahi sızdırılmaz.

Not: Telefon numarası içeren tüm sorgular POST ile yapılır. Numara URL'de taşınsaydı sunucu/proxy erişim loglarına düşerdi (KVKK riski).

Yalnızca telefonla sorgulama yoktur. Telefon numarası gizli bir bilgi değildir; tek başına yeterli sayılsaydı numarayı bilen herkes o kişinin tüm taleplerini, adresini ve yazışmalarını görebilirdi. Bu nedenle sorgulama daima talep numarası + telefon ya da takip token'ı ile yapılır.


4. Uçlar (Endpoints)

4.1 Servis Durumu

GET /health

Anahtar gerektirmez. İzleme (uptime) kontrolü için kullanılır.

{
  "status": "ok",
  "service": "tatvan-web-api",
  "time": "2026-07-29T21:21:14+03:00"
}

4.2 Mahalle Listesi (form için)

GET /neighborhoods
X-API-Key: ...

Talep formundaki mahalle açılır listesini doldurmak içindir. Yalnızca aktif ve herkese açık mahalleler döner; çağrı merkezine özel kayıtlar (örn. "Adres Belirtilmedi") dışarı verilmez.

Yanıt: 200 OK

{
  "data": [
    { "id": 1, "name": "Atatürk Mahallesi" },
    { "id": 2, "name": "Sahil Mahallesi" }
  ]
}

Liste nadiren değişir; sitenizde günlük önbelleğe almanız önerilir.


4.3 Yeni Talep Oluşturma

POST /tickets
X-API-Key: ...
X-Client-IP: 88.240.15.72
Content-Type: application/json
{
  "citizen_name": "Ahmet Yılmaz",
  "citizen_phone": "0532 999 88 77",
  "citizen_email": "ahmet@example.com",
  "neighborhood_id": 2,
  "address": "Sahil Mah. 123. Sok. No:4",
  "subject": "Sokak lambası yanmıyor",
  "description": "Sokağımızdaki aydınlatma direği üç gündür yanmıyor.",
  "latitude": 38.5012,
  "longitude": 42.2795,
  "kvkk_consent": true
}
Alan Zorunlu Kural
citizen_name 3–120 karakter
citizen_phone 10–20 karakter; esnek biçim kabul edilir
citizen_email Geçerli e-posta, en fazla 150 karakter
neighborhood_id GET /neighborhoods listesinden bir kimlik
address En fazla 255 karakter
subject 5–160 karakter
description 10–4000 karakter
latitude / longitude Sayısal koordinat
kvkk_consent true olmalıdır
photos[] En fazla 5 dosya, her biri en fazla 8 MB

Kategori (konu başlığı) gönderilmez. Talebi hangi kategoriye ve müdürlüğe yönlendireceğine çağrı merkezi temsilcisi karar verir. Vatandaş yalnızca konuyu serbest metin olarak yazar.

Fotoğraf/belge eki ile gönderim

Ek göndereceksiniz multipart/form-data kullanın (JSON yerine). İzin verilen türler: jpg, jpeg, png, webp, heic, pdf, doc, docx.

curl -X POST https://153.vegabyte.com.tr/api/web/v1/tickets \
  -H "X-API-Key: $ALO153_API_KEY" \
  -H "X-Client-IP: 88.240.15.72" \
  -F "citizen_name=Ahmet Yılmaz" \
  -F "citizen_phone=05329998877" \
  -F "subject=Sokak lambası yanmıyor" \
  -F "description=Aydınlatma direği üç gündür yanmıyor." \
  -F "kvkk_consent=1" \
  -F "photos[]=@lamba.jpg" \
  -F "photos[]=@sokak.jpg"

Yanıt: 201 CreatedTalep Detay Nesnesi

Yanıttaki ticket_number ve track_token değerlerini kullanıcıya gösterin; track_token takip ekranına yönlendirme için kullanılır. Vatandaşa ayrıca sistem tarafından bilgilendirme SMS'i/e-postası gönderilir.

Hatalar:

Durum Anlamı
422 Doğrulama hatası (eksik alan, KVKK onayı yok, geçersiz dosya türü/boyutu)
429 Dakikada 3 talep sınırı aşıldı

4.4 Takip Token'ı ile Talep Detayı

GET /tickets/{track_token}
X-API-Key: ...

Vatandaşa gönderilen takip bağlantısındaki token ile talebin tüm detayını döner.

Yanıt: 200 OK — bkz. Talep Detay Nesnesi

Hatalar: 404 (talep bulunamadı)


4.5 Talep No + Telefon ile Sorgulama

POST /tickets/lookup
X-API-Key: ...
Content-Type: application/json

{
  "ticket_number": "153-2026-000004",
  "phone": "0532 999 88 77"
}

Telefon numarası esnek biçimde kabul edilir: 05329998877, 0532 999 88 77, +90 532 999 88 77, 905329998877 — hepsi aynı numaraya normalize edilir.

Yanıt: 200 OKTalep Detay Nesnesi

Hatalar:

Durum Anlamı
404 Talep numarası ve telefon eşleşmedi
422 Geçersiz telefon formatı
429 Çok fazla başarısız deneme

4.6 Bilgi Düzeltme (Düzenleme)

POST /tickets/update
X-API-Key: ...
Content-Type: application/json

{
  "track_token": "5b7d4c7e-...",
  "citizen_name": "Ahmet Yılmaz",
  "citizen_email": "yeni@example.com",
  "address": "Sahil Mah. 123. Sok. No:6",
  "neighborhood_id": 3
}

Vatandaşın, talebini oluştururken hatalı/eksik girdiği iletişim ve konum bilgilerini düzeltmesi içindir. Sahiplik kanıtı olarak track_token yerine ticket_number + phone de gönderilebilir.

Değiştirilebilen alanlar

Alan Kural
citizen_name 3–120 karakter
citizen_email Geçerli e-posta veya null
address En fazla 255 karakter veya null
neighborhood_id GET /neighborhoods listesinden bir kimlik veya null

Yalnızca gönderdiğiniz alanlar değerlendirilir (kısmi güncelleme); göndermediğiniz alanlar olduğu gibi kalır.

Değiştirilemeyen alanlar

  • Telefon numarası — sahiplik kanıtıdır; değiştirilmesi talebin başkasına devredilmesi anlamına gelirdi. İstekte gönderilse bile yok sayılır.
  • Konu ve açıklama — personelin üzerinde çalıştığı içeriktir. Ek bilgi için yanıt yazma ucunu kullanın.

Süre kısıtı

Düzeltme yalnızca talep oluşturulduktan sonraki ilk 24 saat içinde ve talep açıkken yapılabilir. Süre dolduktan sonra 409 döner; bu durumda vatandaş yanıt yazarak düzeltmeyi iletebilir.

Yanıt: 200 OK

{
  "message": "Bilgileriniz güncellendi.",
  "updated": [
    "Ad Soyad: \"Ahmet Yilmaz\" → \"Ahmet Yılmaz\"",
    "Adres: \"Sahil Mah. 123. Sok. No:4\" → \"Sahil Mah. 123. Sok. No:6\""
  ],
  "data": { }
}

updated dizisi uygulanan değişikliklerin okunabilir özetidir; kullanıcıya onay mesajı olarak gösterilebilir. Aynı değişiklik panelde personele iç not olarak da işlenir, böylece kayıt geçmişi izlenebilir kalır.

Hatalar:

Durum Anlamı
409 24 saatlik düzeltme süresi doldu veya talep kapatılmış
422 Doğrulama hatası ya da hiçbir alanda değişiklik yok
404 Sahiplik eşleşmedi

4.7 Talebe Yanıt Yazma

POST /tickets/reply
X-API-Key: ...
Content-Type: application/json

{
  "track_token": "5b7d4c7e-...",
  "message": "Sorun devam ediyor, tekrar bakılabilir mi?"
}

Sahiplik kanıtı olarak track_token yerine ticket_number + phone de gönderilebilir. message: 2–1000 karakter.

Yanıt: 201 Created

{
  "message": "Yanıtınız talebinize eklendi.",
  "data": {
    "id": 12,
    "body": "Sorun devam ediyor, tekrar bakılabilir mi?",
    "author_type": "citizen",
    "created_at": "2026-07-29T21:22:07+03:00"
  }
}

Hatalar: 409 (talep kapalı), 404, 422


4.8 Çözüldü Olarak İşaretleme

POST /tickets/resolve
X-API-Key: ...
Content-Type: application/json

{
  "track_token": "5b7d4c7e-...",
  "note": "Sorun giderildi, teşekkürler."
}

note isteğe bağlıdır (en fazla 1000 karakter).

Yanıt: 200 OK

{
  "message": "Talebiniz çözüldü olarak işaretlendi.",
  "data": {
    "ticket_number": "153-2026-000004",
    "status": { "value": "resolved", "label": "Çözüldü", "order": 3, "color": "teal" },
    "resolved_at": "2026-07-29T21:23:07+03:00"
  }
}

Hatalar: 409 (zaten çözülmüş), 404


4.9 Kaydı Kapatma

POST /tickets/close
X-API-Key: ...
Content-Type: application/json

{
  "track_token": "5b7d4c7e-...",
  "reason": "Talebimden vazgeçtim."
}

Vatandaşın talebinden vazgeçmesi / kaydı sonlandırması içindir. reason isteğe bağlıdır (en fazla 500 karakter).

Önemli: Kayıt silinmez. Yönetim panelinde ve raporlarda görünmeye devam eder; yalnızca "Çözüldü" durumuna alınır ve geçmişine "Vatandaş kaydı kapattı" notu işlenir. Kurumsal arşiv bütünlüğü korunur.

Yanıt: 200 OK

{
  "message": "Kaydınız kapatıldı. Kurum arşivinde saklanmaya devam eder.",
  "data": {
    "ticket_number": "153-2026-000004",
    "status": { "value": "resolved", "label": "Çözüldü", "order": 3, "color": "teal" },
    "closed_at": "2026-07-29T21:23:07+03:00"
  }
}

Hatalar: 409 (zaten kapalı), 404


5. Talep Detay Nesnesi

{
  "data": {
    "ticket_number": "153-2026-000004",
    "track_token": "5b7d4c7e-...",
    "subject": "API test talebi",
    "status": { "value": "resolved", "label": "Çözüldü", "order": 3, "color": "teal" },
    "is_open": false,
    "category": "Alt Yapı / Yol Şikayeti",
    "neighborhood": "Sahil Mahallesi",
    "department": "Fen İşleri Müdürlüğü",
    "is_emergency": false,
    "created_at": "2026-07-29T21:22:40+03:00",
    "resolved_at": "2026-07-29T21:23:07+03:00",
    "description": "Talep açıklaması...",
    "citizen": {
      "name": "Test Vatandaş",
      "phone": "05329998877",
      "email": null,
      "address": "Test Adres"
    },
    "location": { "latitude": null, "longitude": null },
    "attachments_count": 0,
    "stages": [
      { "key": "received",  "label": "Talep Alındı",   "order": 0, "state": "completed", "completed": true,  "active": false, "reached_at": "2026-07-29T21:22:40+03:00" },
      { "key": "forwarded", "label": "Birime İletildi", "order": 1, "state": "completed", "completed": true,  "active": false, "reached_at": null },
      { "key": "in_review", "label": "İnceleniyor",     "order": 2, "state": "completed", "completed": true,  "active": false, "reached_at": null },
      { "key": "resolved",  "label": "Çözüldü",         "order": 3, "state": "completed", "completed": true,  "active": false, "reached_at": "2026-07-29T21:23:07+03:00" }
    ],
    "replies": [
      {
        "id": 4,
        "body": "Talebiniz ilgili müdürlüğe iletilmiştir.",
        "author_type": "staff",
        "author_name": "Merve K.",
        "created_at": "2026-07-29T21:23:31+03:00"
      }
    ],
    "can": { "reply": false, "resolve": false, "close": false }
  }
}

Alan açıklamaları

Alan Açıklama
status.value received, forwarded, in_review, resolved
status.order 0–3 arası sıra numarası
status.color Öneri renk anahtarı: sky, blue, amber, teal
is_open Talep hâlâ açık mı
citizen Vatandaşın kendi bilgileri (tam)
replies[].author_type citizen (vatandaş) veya staff (belediye personeli)
replies[].author_name Personel için soyadı maskeli (örn. Merve K.); vatandaş yanıtlarında null
attachments_count Talebe eklenen dosya sayısı (yalnızca sayı)
can Bu talepte hangi işlemlerin yapılabileceği — butonları buna göre gösterin

Ek dosyalar indirilemez. attachments_count yalnızca kaç dosya eklendiğini bildirir; dosyaların kendisi web API'si üzerinden sunulmaz. Vatandaşın yüklediği belgeler yalnızca yetkili personelin panelinde görüntülenir. Sitenizde "3 dosya eklediniz" biçiminde bilgi gösterebilirsiniz.

Aşama (stage) durumları

state Anlamı Önerilen gösterim
completed Bu aşama tamamlandı Dolu / işaretli
active Talep şu an bu aşamada Vurgulu / animasyonlu
pending Henüz ulaşılmadı Soluk

reached_at alanı, aşamaya ulaşıldığı an (ISO 8601). null ise o aşama için ayrı bir kayıt tutulmamıştır (örn. doğrudan çözüme geçen talepler).

Gizlilik notları

  • Belediye personelinin soyadı maskelenir (Merve K.); tam ad dışarı verilmez.
  • Personelin iç notları (dahili yazışmalar) API'de hiçbir koşulda dönmez.
  • Vatandaşın kendi ad/telefon/adres bilgisi tam döner (kendi kaydını sorgulamaktadır).

6. Hata Biçimi

Doğrulama hataları Laravel standardındadır:

{
  "message": "Geçerli bir cep telefonu numarası giriniz (örn. 0532 111 22 33).",
  "errors": {
    "phone": ["Geçerli bir cep telefonu numarası giriniz (örn. 0532 111 22 33)."]
  }
}

Diğer hatalarda yalnızca message döner.

Kod Anlamı
200 Başarılı
201 Oluşturuldu (yeni talep, yanıt ekleme)
401 API anahtarı eksik/geçersiz
403 API anahtarı devre dışı
404 Talep bulunamadı veya sahiplik eşleşmedi
409 İşlem talebin mevcut durumuyla çelişiyor (örn. kapalı talebe yanıt)
422 Doğrulama hatası (eksik/geçersiz alan)
429 Hız sınırı aşıldı

7. Örnek Entegrasyon

PHP (sunucu tarafı)

$response = Http::withHeaders([
        'X-API-Key' => env('ALO153_API_KEY'),
        'Accept'    => 'application/json',
    ])
    ->post('https://153.vegabyte.com.tr/api/web/v1/tickets/lookup', [
        'ticket_number' => $request->input('ticket_number'),
        'phone'         => $request->input('phone'),
    ]);

if ($response->status() === 404) {
    return back()->withErrors('Talep numarası ve telefon eşleşmedi.');
}

$ticket = $response->json('data');

Node.js (sunucu tarafı)

const res = await fetch('https://153.vegabyte.com.tr/api/web/v1/tickets/lookup', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.ALO153_API_KEY,
    'Content-Type': 'application/json',
    Accept: 'application/json',
  },
  body: JSON.stringify({ ticket_number: ticketNumber, phone }),
});

if (res.status === 404) throw new Error('Talep bulunamadı.');
const { data } = await res.json();

cURL

curl -X POST https://153.vegabyte.com.tr/api/web/v1/tickets/lookup \
  -H "X-API-Key: $ALO153_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ticket_number":"153-2026-000004","phone":"05329998877"}'

8. Web Sitesi İçin Öneriler

  1. Anahtarı gizleyin. Tarayıcıdan gelen formu kendi sunucunuzda karşılayın, API'ye oradan gidin. Anahtar hiçbir zaman istemciye inmemelidir.
  2. X-Client-IP gönderin. Aksi halde tüm ziyaretçileriniz aynı hız sınırı kotasını paylaşır ve bir kişi hepsini kilitleyebilir (bkz. bölüm 2.1).
  3. Formda kendi bot korumanızı kullanın. Yeni talep ucu dakikada 3 istekle sınırlıdır; buna ek olarak sitenizde captcha/honeypot bulundurun.
  4. Mahalle listesini önbelleğe alın. GET /neighborhoods günde bir kez çekilmesi yeterlidir.
  5. Aşama çubuğunu stages dizisiyle çizin. state alanı doğrudan tamamlandı/aktif/bekliyor gösterimine karşılık gelir.
  6. Butonları can nesnesine göre gösterin. Kapalı taleplerde yanıt/çözüldü/kapat butonları gizlenmelidir; aksi halde 409 alırsınız.
  7. Düzenleme butonunu süreye göre gösterin. created_at üzerinden 24 saat geçmişse "Bilgilerimi düzelt" seçeneğini gizleyin.
  8. KVKK uyarısı gösterin. Hem talep formunda hem sorgulama ekranında kişisel veri işlendiğine dair bilgilendirme ve açık onay kutusu bulunmalıdır.
  9. Sorgulama formunda iki alanı da isteyin. Yalnızca telefonla sorgulama bilinçli olarak desteklenmez (bkz. bölüm 3). Formunuzda hem talep numarası hem telefon alanı zorunlu olmalıdır.
  10. Takip bağlantısını kullanıcıya hatırlatın. Talep oluşturulduğunda dönen track_token ile hazırlanan bağlantı, kullanıcının talep numarasını hatırlamadan doğrudan takip ekranına girmesini sağlar.

9. Çalışan Örnek Entegrasyon

Bu dokümandaki tüm uçları kullanan, çalışır durumda bir referans uygulama hazırlanmıştır. Kendi entegrasyonunuzu yazmadan önce incelemeniz önerilir.

Adres https://153.vegabyte.com.tr/ornek/
Erişim parolası Sistem yöneticisinden talep edilir

Örnek uygulama düz PHP ile yazılmıştır ve şunları gösterir:

  • Anahtarın sunucu tarafında tutulması ve isteklerin sunucu-sunucu iletilmesi (lib/Alo153Client.php)
  • X-Client-IP başlığının doğru gönderimi
  • Fotoğraf ekli talep oluşturma (multipart/form-data)
  • Talep numarası + telefon ile sorgulama ve takip token'ı ile detay
  • Aşama çubuğunun stages dizisiyle çizilmesi
  • Yanıt yazma, bilgi düzeltme, çözüldü işaretleme ve kayıt kapatma
  • Her ekranda yapılan API çağrısının istek/yanıt/süre dökümü (teknik günlük)

Örnek site canlı API'ye bağlıdır; burada oluşturduğunuz talepler gerçek kayıt olarak sisteme düşer ve vatandaşa SMS gider. Test ederken bunu göz önünde bulundurun.


10. Sürüm ve Destek

  • Sürüm: v1 (/api/web/v1)
  • Geriye dönük uyumsuz değişiklikler yeni sürüm yolu (/api/web/v2) ile yayınlanır.
  • Yeni anahtar talebi, anahtar iptali ve teknik destek: yönetim paneli Yönetim → API Anahtarları ekranı / sistem yöneticisi.

Değişiklik geçmişi

Tarih Değişiklik
30.07.2026 Telefonla listeleme ucu (POST /tickets/by-phone) kaldırıldı. Sorgulama artık yalnızca talep numarası + telefon veya takip token'ı ile yapılır (bkz. bölüm 3).
30.07.2026 Tüm uçlara güvenlik sertleştirmesi uygulandı; hız sınırları ziyaretçi bazında işler hâle getirildi (X-Client-IP).
29.07.2026 Talep oluşturma (POST /tickets), bilgi düzeltme (POST /tickets/update) ve mahalle listesi (GET /neighborhoods) uçları eklendi.