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:
{
"success": true | false,
"message": "İşlem mesajı",
"data": { ... }, // Başarılı işlemlerde veri
"error": "ERROR_CODE", // Hata durumunda hata kodu
"errors": { ... } // Validation hataları
}
Korumalı endpoint'lere erişmek için Authorization header'ında Bearer token göndermeniz gerekir.
Authorization: Bearer your-token-here
Kullanıcı girişi yapar ve erişim token'ı döndürür.
{
"email": "admin@example.com",
"password": "admin123",
"device_name": "iPhone 15 Pro",
"device_id": "unique-device-uuid"
}
| Parametre | Tip | Durum | Açıklama |
|---|---|---|---|
| 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 |
Yeni kullanıcı hesabı oluşturur.
{
"name": "John Doe",
"email": "john@example.com",
"password": "secret123",
"password_confirm": "secret123",
"phone": "+905551234567"
}
Giriş yapmış kullanıcının profil bilgilerini döndürür. Token gerektirir.
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); }
Mevcut cihazdan çıkış yapar ve token'ı geçersiz kılar. Token gerektirir.
Future<void> logout() async { final token = await getToken(); await http.post( Uri.parse('$baseUrl/logout'), headers: {'Authorization': 'Bearer $token'}, ); // Yerel token'ı sil await clearToken(); }
Kullanıcı profil bilgilerini günceller. Token gerektirir.
{
"name": "John Smith",
"phone": "+905559876543",
"bio": "Flutter Developer"
}
Kullanıcı şifresini değiştirir. Token gerektirir.
{
"current_password": "oldpassword",
"new_password": "newpassword123",
"new_password_confirm": "newpassword123",
"logout_others": true
}
Kullanıcının tüm aktif oturumlarını (cihazlarını) listeler. Token gerektirir.
Belirli bir oturumu (cihazı) sonlandırır. Token gerektirir.
Books API
Kitap kayıtları için RESTful API endpoint'leri
Tüm kitapları sayfalama ve filtreleme ile listeler. Kimlik doğrulama gerektirmez.
| Parametre | Tip | Durum | Açı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 |
Belirtilen ID'ye sahip kitabın detaylarını getirir. Kimlik doğrulama gerektirmez.
| Parametre | Tip | Durum | Açıklama |
|---|---|---|---|
| id | integer | zorunlu | Kitap ID (URL path parametresi) |
Kitap adı, yazar, ISBN veya yayınevi ile arama yapar. Kimlik doğrulama gerektirmez.
| Parametre | Tip | Durum | Açıklama |
|---|---|---|---|
| q veya query | string | zorunlu | Arama sorgusu (min 2 karakter) |
| page | integer | opsiyonel | Sayfa numarası (varsayılan: 1) |
| per_page | integer | opsiyonel | Sayfa başına kayıt (varsayılan: 20) |
| category_id | integer | opsiyonel | Kategori ID ile filtrele |
| status | string | opsiyonel | Durum filtresi: available, borrowed, reserved, damaged |
Yeni kitap kaydı oluşturur. Token gerektirir.
{
"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"
}
| Parametre | Tip | Durum | Açı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 |
Belirtilen kitabı günceller. Sadece gönderilen alanlar güncellenir. Token gerektirir.
{
"title": "Güncellenmiş Kitap Adı",
"status": "borrowed",
"available_quantity": 1
}
| Parametre | Tip | Durum | Açı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.
Belirtilen kitabı siler (soft delete - veritabanından tamamen silinmez). Token gerektirir.
| Parametre | Tip | Durum | Açıklama |
|---|---|---|---|
| id | integer | zorunlu | Silinecek kitabın ID'si (URL path) |
Tüm aktif kategorileri kitap sayıları ile listeler. Kimlik doğrulama gerektirmez.
200 Başarılı
{
"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
}
]
}
}
Tüm rafları kitap sayıları ile listeler. Kimlik doğrulama gerektirmez.
200 Başarılı
{
"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"
}
]
}
}
Kitap koleksiyonu hakkında özet istatistikleri getirir. Dashboard ekranları için idealdir.
200 Başarılı
{
"success": true,
"message": "Success",
"data": {
"stats": {
"total_books": 127,
"available": 98,
"borrowed": 22,
"reserved": 5,
"damaged": 2,
"total_copies": 245,
"available_copies": 189
}
}
}
| Alan | Tip | Açı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ı |
Kişi/Üye yönetimi için API endpoints. Kitap ödünç alan kişilerin kayıt, güncelleme ve sorgulama işlemleri.
https://kitap.makbil.com.tr/api/persons
Tüm kişileri sayfalı olarak listeler. Filtreleme ve arama destekler.
Query Parameters
| Parametre | Tip | Açıklama |
|---|---|---|
| page | int | Sayfa numarası (varsayılan: 1) |
| limit | int | Sayfa başına kayıt (varsayılan: 15) |
| search | string | Arama terimi (ad, üye no, telefon) |
| status | string | Durum filtresi: active, inactive, suspended, blacklist |
| membership_type | string | Üyelik tipi: standard, student, teacher, vip |
Belirtilen ID'ye sahip kişinin detaylarını ve aktif ödünçlerini getirir.
200 Başarılı
{
"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
}
]
}
}
Kişilerde hızlı arama yapar. Dropdown/autocomplete için optimize edilmiştir.
Query Parameters
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| q | string | Evet | Arama terimi (min 2 karakter) |
Yeni kişi/üye kaydı oluşturur.
Body Parameters
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| name | string | Evet | Ad soyad |
| member_no | string | Hayır | Üye no (otomatik oluşturulur) |
| string | Hayır | E-posta | |
| phone | string | Hayır | Telefon |
| identity_no | string | Hayır | TC Kimlik No (11 hane) |
| membership_type | string | Hayır | standard, student, teacher, vip |
| max_books | int | Hayır | Max ödünç sayısı (varsayılan: 3) |
| max_days | int | Hayır | Max ödünç süresi (varsayılan: 15) |
Mevcut kişi bilgilerini günceller. Sadece gönderilen alanlar güncellenir.
// 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); }
Kişiyi siler. Elinde ödünç kitap varsa silinemez.
Kişi istatistiklerini getirir.
{
"success": true,
"data": {
"total": 150,
"active": 120,
"inactive": 25,
"suspended": 3,
"blacklist": 2,
"by_type": {
"standard": 80,
"student": 50,
"teacher": 15,
"vip": 5
}
}
}
Kitap ödünç verme, iade alma ve takip işlemleri için API endpoints.
https://kitap.makbil.com.tr/api/borrowings
Tüm ödünç kayıtlarını listeler.
Query Parameters
| Parametre | Tip | Açıklama |
|---|---|---|
| page | int | Sayfa numarası |
| limit | int | Sayfa başına kayıt |
| status | string | borrowed, returned |
| person_id | int | Kişiye göre filtre |
| book_id | int | Kitaba göre filtre |
| search | string | Arama terimi |
Tek ödünç kaydının detaylarını getirir.
Sadece aktif (iade edilmemiş) ödünçleri listeler.
Geciken (süresi geçmiş) ödünçleri listeler.
{
"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
}
}
Yeni ödünç kaydı oluşturur (kitap ödünç verir).
Body Parameters
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| book_id | int | Evet | Kitap ID |
| person_id | int | Evet | Kişi ID |
| borrow_date | date | Hayır | Ödünç tarihi (varsayılan: bugün) |
| due_date | date | Hayır | İade tarihi (varsayılan: kişinin max_days değeri) |
| notes | string | Hayır | Notlar |
Kitabı iade alır. Gecikme varsa otomatik hesaplanır.
{
"success": true,
"message": "Kitap başarıyla iade alındı.",
"data": {
"borrowing": { ... },
"late_days": 3
}
}
Ödünç süresini uzatır. Maksimum 2 kez uzatılabilir.
Body Parameters
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| days | int | Hayır | Uzatma süresi gün (varsayılan: 7, max: 30) |
Ödünç istatistiklerini getirir.
{
"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
dependencies: http: ^1.1.0 shared_preferences: ^2.2.2
2. Android için Internet İzni
<uses-permission android:name="android.permission.INTERNET"/>
3. Base URL Ayarı
Geliştirme ve canlı ortamlar için ayrı URL'ler kullanın:
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'; }
Projenizde kullanabileceğiniz hazır API servis sınıfı.
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); } }