Başlarken

Bu API, Flutter ve diğer mobil uygulamalar için kullanıcı yönetimi, kimlik doğrulama ve kitap takip sistemi hizmetleri sunar. RESTful mimari kullanılarak tasarlanmıştır ve JSON formatında veri alışverişi yapar.

Auth API

  • Token tabanlı kimlik doğrulama (30 gün)
  • Çoklu cihaz desteği
  • Oturum yönetimi
  • Profil ve şifre güncelleme

Books API

  • Kitap CRUD işlemleri
  • Kategori ve raf yönetimi
  • Arama ve filtreleme
  • İstatistik ve raporlama

Response Formatı

Tüm API yanıtları aşağıdaki formatta döner:

JSON Response Format
{
  "success": true | false,
  "message": "İşlem mesajı",
  "data": { ... },           // Başarılı işlemlerde veri
  "error": "ERROR_CODE",    // Hata durumunda hata kodu
  "errors": { ... }          // Validation hataları
}
Kimlik Doğrulama

Korumalı endpoint'lere erişmek için Authorization header'ında Bearer token göndermeniz gerekir.

HTTP Header
Authorization: Bearer your-token-here
POST /login Kullanıcı Girişi

Kullanıcı girişi yapar ve erişim token'ı döndürür.

JSON
{
  "email": "admin@example.com",
  "password": "admin123",
  "device_name": "iPhone 15 Pro",
  "device_id": "unique-device-uuid"
}
ParametreTipDurumAçıklama
email string zorunlu Kullanıcı e-posta adresi
password string zorunlu Kullanıcı şifresi (min 6 karakter)
device_name string opsiyonel Cihaz adı
device_id string opsiyonel Benzersiz cihaz ID
POST /register Yeni Kullanıcı Kaydı

Yeni kullanıcı hesabı oluşturur.

JSON
{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "secret123",
  "password_confirm": "secret123",
  "phone": "+905551234567"
}
GET /me Mevcut Kullanıcı Bilgisi

Giriş yapmış kullanıcının profil bilgilerini döndürür. Token gerektirir.

Dart (Flutter)
Future<Map<String, dynamic>> getMe() async {
  final token = await getToken();
  
  final response = await http.get(
    Uri.parse('$baseUrl/me'),
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $token',
    },
  );

  return jsonDecode(response.body);
}
POST /logout Çıkış Yap

Mevcut cihazdan çıkış yapar ve token'ı geçersiz kılar. Token gerektirir.

Dart (Flutter)
Future<void> logout() async {
  final token = await getToken();
  
  await http.post(
    Uri.parse('$baseUrl/logout'),
    headers: {'Authorization': 'Bearer $token'},
  );
  
  // Yerel token'ı sil
  await clearToken();
}
PUT /profile Profil Güncelle

Kullanıcı profil bilgilerini günceller. Token gerektirir.

JSON Request
{
  "name": "John Smith",
  "phone": "+905559876543",
  "bio": "Flutter Developer"
}
PUT /password Şifre Değiştir

Kullanıcı şifresini değiştirir. Token gerektirir.

JSON Request
{
  "current_password": "oldpassword",
  "new_password": "newpassword123",
  "new_password_confirm": "newpassword123",
  "logout_others": true
}
GET /sessions Aktif Oturumlar

Kullanıcının tüm aktif oturumlarını (cihazlarını) listeler. Token gerektirir.

DELETE /sessions/{id} Oturum Sonlandır

Belirli bir oturumu (cihazı) sonlandırır. Token gerektirir.

Books API

Kitap kayıtları için RESTful API endpoint'leri

Base URL: https://kitap.makbil.com.tr/api/books
GET /api/books Kitapları Listele

Tüm kitapları sayfalama ve filtreleme ile listeler. Kimlik doğrulama gerektirmez.

ParametreTipDurumAçıklama
page integer opsiyonel Sayfa numarası (varsayılan: 1)
per_page integer opsiyonel Sayfa başına kayıt (1-100, varsayılan: 15)
search string opsiyonel Kitap adı, yazar, ISBN veya yayınevi araması
status string opsiyonel Durum: available, borrowed, reserved, damaged
category_id integer opsiyonel Kategori ID ile filtrele
shelf_id integer opsiyonel Raf ID ile filtrele
GET /api/books/{id} Kitap Detayı

Belirtilen ID'ye sahip kitabın detaylarını getirir. Kimlik doğrulama gerektirmez.

ParametreTipDurumAçıklama
id integer zorunlu Kitap ID (URL path parametresi)
POST /api/books Yeni Kitap Ekle

Yeni kitap kaydı oluşturur. Token gerektirir.

JSON
{
  "title": "Sefiller",
  "author": "Victor Hugo",
  "isbn": "978-605-789-012-3",
  "publisher": "Can Yayınları",
  "publish_year": 2021,
  "page_count": 1456,
  "language": "Türkçe",
  "category_id": 2,
  "shelf_id": 1,
  "quantity": 3,
  "price": 125.00,
  "description": "Dünya edebiyatının...",
  "status": "available"
}
ParametreTipDurumAçıklama
title string zorunlu Kitap adı
author string zorunlu Yazar adı (min 2 karakter)
isbn string opsiyonel ISBN numarası (max 20 karakter)
publisher string opsiyonel Yayınevi
category_id integer opsiyonel Kategori ID
shelf_id integer opsiyonel Raf ID
quantity integer opsiyonel Adet sayısı (varsayılan: 1)
status string opsiyonel Durum: available, borrowed, reserved, damaged
PUT /api/books/{id} Kitap Güncelle

Belirtilen kitabı günceller. Sadece gönderilen alanlar güncellenir. Token gerektirir.

JSON Request
{
  "title": "Güncellenmiş Kitap Adı",
  "status": "borrowed",
  "available_quantity": 1
}
ParametreTipDurumAçıklama
id integer zorunlu Kitap ID (URL path)
title string opsiyonel Kitap adı
author string opsiyonel Yazar adı
status string opsiyonel available, borrowed, reserved, damaged
quantity integer opsiyonel Toplam adet
available_quantity integer opsiyonel Mevcut adet

Sadece güncellemek istediğiniz alanları gönderin. Gönderilmeyen alanlar değişmez.

DELETE /api/books/{id} Kitap Sil

Belirtilen kitabı siler (soft delete - veritabanından tamamen silinmez). Token gerektirir.

ParametreTipDurumAçıklama
id integer zorunlu Silinecek kitabın ID'si (URL path)
GET /api/books/categories Kategorileri Listele

Tüm aktif kategorileri kitap sayıları ile listeler. Kimlik doğrulama gerektirmez.

200 Başarılı

JSON
{
  "success": true,
  "message": "Success",
  "data": {
    "categories": [
      {
        "id": 1,
        "name": "Roman",
        "slug": "roman",
        "description": "Yerli ve yabancı romanlar",
        "color": "#6366f1",
        "icon": "book",
        "book_count": 45,
        "sort_order": 1
      },
      {
        "id": 2,
        "name": "Bilim Kurgu",
        "slug": "bilim-kurgu",
        "description": "Bilim kurgu kitapları",
        "color": "#22c55e",
        "icon": "rocket",
        "book_count": 23,
        "sort_order": 2
      }
    ]
  }
}
GET /api/books/shelves Rafları Listele

Tüm rafları kitap sayıları ile listeler. Kimlik doğrulama gerektirmez.

200 Başarılı

JSON
{
  "success": true,
  "message": "Success",
  "data": {
    "shelves": [
      {
        "id": 1,
        "name": "Edebiyat Rafı",
        "code": "A-01",
        "location": "1. Kat, Sol Koridor",
        "capacity": 100,
        "book_count": 45,
        "status": "active"
      },
      {
        "id": 2,
        "name": "Bilim Rafı",
        "code": "B-01",
        "location": "2. Kat",
        "capacity": 80,
        "book_count": 32,
        "status": "active"
      }
    ]
  }
}
GET /api/books/stats Kitap İstatistikleri

Kitap koleksiyonu hakkında özet istatistikleri getirir. Dashboard ekranları için idealdir.

200 Başarılı

JSON
{
  "success": true,
  "message": "Success",
  "data": {
    "stats": {
      "total_books": 127,
      "available": 98,
      "borrowed": 22,
      "reserved": 5,
      "damaged": 2,
      "total_copies": 245,
      "available_copies": 189
    }
  }
}
AlanTipAçıklama
total_books integer Toplam benzersiz kitap sayısı
available integer Mevcut durumda olan kitap sayısı
borrowed integer Ödünç verilmiş kitap sayısı
reserved integer Rezerve edilmiş kitap sayısı
damaged integer Hasarlı kitap sayısı
total_copies integer Toplam kopya sayısı (adetler)
available_copies integer Mevcut kopya sayısı
Persons API

Kişi/Üye yönetimi için API endpoints. Kitap ödünç alan kişilerin kayıt, güncelleme ve sorgulama işlemleri.

Base URL: https://kitap.makbil.com.tr/api/persons
GET /api/persons

Tüm kişileri sayfalı olarak listeler. Filtreleme ve arama destekler.

Query Parameters

ParametreTipAçıklama
pageintSayfa numarası (varsayılan: 1)
limitintSayfa başına kayıt (varsayılan: 15)
searchstringArama terimi (ad, üye no, telefon)
statusstringDurum filtresi: active, inactive, suspended, blacklist
membership_typestringÜyelik tipi: standard, student, teacher, vip
GET /api/persons/{id}

Belirtilen ID'ye sahip kişinin detaylarını ve aktif ödünçlerini getirir.

200 Başarılı

JSON Response
{
  "success": true,
  "data": {
    "id": 1,
    "member_no": "UYE-2024-001",
    "name": "Ahmet Yılmaz",
    "email": "ahmet@email.com",
    "phone": "05321234567",
    "identity_no": "12345678901",
    "birth_date": "1990-05-15",
    "gender": "male",
    "occupation": "Öğretmen",
    "city": "İstanbul",
    "district": "Kadıköy",
    "active_borrowings": [
      {
        "id": 5,
        "book_title": "Sefiller",
        "book_author": "Victor Hugo",
        "borrow_date": "2024-01-10",
        "due_date": "2024-01-25",
        "is_overdue": false
      }
    ]
  }
}
POST /api/persons Auth Required

Yeni kişi/üye kaydı oluşturur.

Body Parameters

ParametreTipZorunluAçıklama
namestringEvetAd soyad
member_nostringHayırÜye no (otomatik oluşturulur)
emailstringHayırE-posta
phonestringHayırTelefon
identity_nostringHayırTC Kimlik No (11 hane)
membership_typestringHayırstandard, student, teacher, vip
max_booksintHayırMax ödünç sayısı (varsayılan: 3)
max_daysintHayırMax ödünç süresi (varsayılan: 15)
PUT /api/persons/{id} Auth Required

Mevcut kişi bilgilerini günceller. Sadece gönderilen alanlar güncellenir.

Dart
// Kişi güncelle
Future<Map<String, dynamic>> updatePerson(
  int id,
  Map<String, dynamic> data,
) async {
  final response = await http.put(
    Uri.parse('$baseUrl/api/persons/$id'),
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $token',
    },
    body: jsonEncode(data),
  );
  return jsonDecode(response.body);
}
DELETE /api/persons/{id} Auth Required

Kişiyi siler. Elinde ödünç kitap varsa silinemez.

Kişinin aktif ödüncü varsa silme işlemi reddedilir.
GET /api/persons/stats

Kişi istatistiklerini getirir.

JSON Response
{
  "success": true,
  "data": {
    "total": 150,
    "active": 120,
    "inactive": 25,
    "suspended": 3,
    "blacklist": 2,
    "by_type": {
      "standard": 80,
      "student": 50,
      "teacher": 15,
      "vip": 5
    }
  }
}
Borrowings API

Kitap ödünç verme, iade alma ve takip işlemleri için API endpoints.

Base URL: https://kitap.makbil.com.tr/api/borrowings
GET /api/borrowings

Tüm ödünç kayıtlarını listeler.

Query Parameters

ParametreTipAçıklama
pageintSayfa numarası
limitintSayfa başına kayıt
statusstringborrowed, returned
person_idintKişiye göre filtre
book_idintKitaba göre filtre
searchstringArama terimi
GET /api/borrowings/{id}

Tek ödünç kaydının detaylarını getirir.

GET /api/borrowings/active

Sadece aktif (iade edilmemiş) ödünçleri listeler.

GET /api/borrowings/overdue

Geciken (süresi geçmiş) ödünçleri listeler.

JSON Response
{
  "success": true,
  "data": {
    "borrowings": [
      {
        "id": 3,
        "book": { "title": "1984", ... },
        "person": { "name": "Mehmet Kaya", ... },
        "due_date": "2024-01-15",
        "overdue_days": 10,
        "is_overdue": true
      }
    ],
    "count": 5
  }
}
POST /api/borrowings Auth Required

Yeni ödünç kaydı oluşturur (kitap ödünç verir).

Body Parameters

ParametreTipZorunluAçıklama
book_idintEvetKitap ID
person_idintEvetKişi ID
borrow_datedateHayırÖdünç tarihi (varsayılan: bugün)
due_datedateHayırİade tarihi (varsayılan: kişinin max_days değeri)
notesstringHayırNotlar
Kitap müsait değilse veya kişi ödünç alamazsa hata döner.
POST /api/borrowings/{id}/return Auth Required

Kitabı iade alır. Gecikme varsa otomatik hesaplanır.

JSON Response
{
  "success": true,
  "message": "Kitap başarıyla iade alındı.",
  "data": {
    "borrowing": { ... },
    "late_days": 3
  }
}
POST /api/borrowings/{id}/extend Auth Required

Ödünç süresini uzatır. Maksimum 2 kez uzatılabilir.

Body Parameters

ParametreTipZorunluAçıklama
daysintHayırUzatma süresi gün (varsayılan: 7, max: 30)
GET /api/borrowings/stats

Ödünç istatistiklerini getirir.

JSON Response
{
  "success": true,
  "data": {
    "total": 350,
    "active": 45,
    "returned": 300,
    "overdue": 5,
    "today": {
      "borrowed": 3,
      "returned": 2
    },
    "this_month": {
      "borrowed": 45
    }
  }
}

Flutter Kurulum

Flutter projenizde API'yi kullanmak için aşağıdaki adımları izleyin.

1. Bağımlılıkları Ekle

pubspec.yaml
dependencies:
  http: ^1.1.0
  shared_preferences: ^2.2.2

2. Android için Internet İzni

android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>

3. Base URL Ayarı

Geliştirme ve canlı ortamlar için ayrı URL'ler kullanın:

lib/config/api_config.dart
class ApiConfig {
  // Geliştirme ortamı (Android Emulator için)
  static const String devBaseUrl = 'http://10.0.2.2/kullanici';
  
  // Gerçek cihaz için yerel IP
  static const String localBaseUrl = 'http://192.168.1.100/kullanici';
  
  // Canlı ortam
  static const String prodBaseUrl = 'https://your-domain.com';
  
  // Aktif URL
  static const String baseUrl = devBaseUrl;
  
  static String get authUrl => '$baseUrl/auth';
  static String get booksUrl => '$baseUrl/api/books';
}
ApiService Class

Projenizde kullanabileceğiniz hazır API servis sınıfı.

lib/services/api_service.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

class ApiService {
  // Base URL - Bunu kendi sunucu adresinizle değiştirin
  static const String baseUrl = 'https://kitap.makbil.com.tr/auth';
  
  String? _token;

  // Token'ı SharedPreferences'dan al
  Future<String?> get token async {
    if (_token != null) return _token;
    final prefs = await SharedPreferences.getInstance();
    _token = prefs.getString('auth_token');
    return _token;
  }

  // Token kaydet
  Future<void> setToken(String token) async {
    _token = token;
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('auth_token', token);
  }

  // Token sil
  Future<void> clearToken() async {
    _token = null;
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove('auth_token');
  }

  // Headers oluştur
  Future<Map<String, String>> _headers({bool auth = true}) async {
    final headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    };
    if (auth) {
      final t = await token;
      if (t != null) headers['Authorization'] = 'Bearer $t';
    }
    return headers;
  }

  // LOGIN
  Future<Map<String, dynamic>> login(String email, String password) async {
    final res = await http.post(
      Uri.parse('$baseUrl/login'),
      headers: await _headers(auth: false),
      body: jsonEncode({'email': email, 'password': password}),
    );
    final data = jsonDecode(res.body);
    if (data['success'] == true) {
      await setToken(data['data']['token']);
    }
    return data;
  }

  // GET ME
  Future<Map<String, dynamic>> getMe() async {
    final res = await http.get(
      Uri.parse('$baseUrl/me'),
      headers: await _headers(),
    );
    return jsonDecode(res.body);
  }

  // LOGOUT
  Future<void> logout() async {
    try {
      await http.post(
        Uri.parse('$baseUrl/logout'),
        headers: await _headers(),
      );
    } finally {
      await clearToken();
    }
  }

  // ======== BOOKS API ========
  static const String booksUrl = 'https://kitap.makbil.com.tr/api/books';

  // Kitapları listele
  Future<Map<String, dynamic>> getBooks({
    int page = 1,
    int perPage = 15,
    String? search,
    String? status,
    int? categoryId,
  }) async {
    final params = {
      'page': page.toString(),
      'per_page': perPage.toString(),
      if (search != null) 'search': search,
      if (status != null) 'status': status,
      if (categoryId != null) 'category_id': categoryId.toString(),
    };
    final uri = Uri.parse(booksUrl).replace(queryParameters: params);
    final res = await http.get(uri);
    return jsonDecode(res.body);
  }

  // Kitap detayı
  Future<Map<String, dynamic>> getBook(int id) async {
    final res = await http.get(Uri.parse('$booksUrl/$id'));
    return jsonDecode(res.body);
  }

  // Kitap ara
  Future<Map<String, dynamic>> searchBooks(String query) async {
    final uri = Uri.parse('$booksUrl/search')
        .replace(queryParameters: {'q': query});
    final res = await http.get(uri);
    return jsonDecode(res.body);
  }

  // Kategorileri getir
  Future<List<dynamic>> getCategories() async {
    final res = await http.get(Uri.parse('$booksUrl/categories'));
    final data = jsonDecode(res.body);
    return data['data']?['categories'] ?? [];
  }

  // Kitap ekle (Auth gerekli)
  Future<Map<String, dynamic>> createBook(Map<String, dynamic> data) async {
    final res = await http.post(
      Uri.parse(booksUrl),
      headers: await _headers(),
      body: jsonEncode(data),
    );
    return jsonDecode(res.body);
  }

  // Kitap güncelle (Auth gerekli)
  Future<Map<String, dynamic>> updateBook(int id, Map<String, dynamic> data) async {
    final res = await http.put(
      Uri.parse('$booksUrl/$id'),
      headers: await _headers(),
      body: jsonEncode(data),
    );
    return jsonDecode(res.body);
  }

  // Kitap sil (Auth gerekli)
  Future<Map<String, dynamic>> deleteBook(int id) async {
    final res = await http.delete(
      Uri.parse('$booksUrl/$id'),
      headers: await _headers(),
    );
    return jsonDecode(res.body);
  }
}