{"success":true,"message":"Başarılı","data":{"info":{"title":"Halı Takip Sistemi API","version":"v1.0","description":"Halı yıkama firmaları için çok kiracılı (multi-tenant) sipariş, müşteri, halı ve ödeme yönetim API'si. JWT (Bearer) tabanlı kimlik doğrulama, firma bazlı veri izolasyonu, rol tabanlı yetkilendirme.","base_url":"http://localhost/halitakip/api/v1","auth_type":"Bearer JWT","rate_limits":{"per_minute":100,"per_hour":1000},"contact":{"email":"destek@halitakip.com","phone":"0850 000 00 00"}},"authentication":{"flow":[{"step":1,"desc":"POST /auth/login ile e-posta + şifre gönder, access + refresh token al"},{"step":2,"desc":"Tüm korumalı endpoint'lere \"Authorization: Bearer <access_token>\" header'ı ile istek gönder"},{"step":3,"desc":"Access token süresi dolduğunda POST /auth/refresh ile yenisini al"}],"login_example":{"request":{"method":"POST","path":"/auth/login","headers":{"Content-Type":"application/json"},"body":{"email":"admin@halitakip.com","password":"admin123"}},"response":{"success":true,"message":"Giriş başarılı","data":{"access_token":"eyJ0eXAiOiJKV1Q...","refresh_token":"eyJ0eXAiOiJKV1Q...","token_type":"Bearer","expires_in":3600,"user":{"id":1,"name":"Sistem Yöneticisi","email":"admin@halitakip.com","role":"super_admin","firm_id":null,"firm":null}}}},"curl_example":"curl -X POST 'http://localhost/halitakip/api/v1/auth/login' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"email\":\"admin@halitakip.com\",\"password\":\"admin123\"}'"},"response_format":{"success":{"success":true,"message":"Başarılı","data":"..."},"paginated":{"success":true,"data":"[...]","meta":{"current_page":1,"per_page":20,"total":145,"last_page":8,"has_more":true}},"error":{"success":false,"message":"Bir hata oluştu"},"validation_error":{"success":false,"message":"Doğrulama hatası","errors":{"email":"E-posta zorunludur","password":"Şifre en az 6 karakter olmalıdır"}}},"roles":[{"code":"super_admin","label":"Sistem Yöneticisi","desc":"Tüm sistem yetkileri (firmalar, planlar, sistem ayarları). firm_id IS NULL."},{"code":"moderator","label":"Moderatör","desc":"Salt-okunur sistem kullanıcısı. Tüm sayfaları görür, yazma yapamaz. firm_id IS NULL."},{"code":"firm_admin","label":"Firma Yöneticisi","desc":"Kendi firmasının tüm verileri ve kullanıcıları üzerinde yetkili."},{"code":"employee","label":"Çalışan","desc":"Müşteri/halı/sipariş/ödeme operasyonları."},{"code":"driver","label":"Kurye/Şoför","desc":"Operasyonel işlemler (sipariş durumu, teslim)."}],"permissions":{"description":"Rol bazlı varsayılan yetkiler + kullanıcı bazlı override sistemi. Her kullanıcının role’ünden gelen varsayılan yetkileri vardır; firma yöneticisi (firm_admin) veya süper admin custom_permissions JSON array’i ile bu yetkileri override edebilir.","override":"users.custom_permissions sütunu JSON array. NULL ise rol varsayılanı, dolu ise sadece liste içindeki yetkiler etkin.","all_keys":{"customers":{"customers.view":"Müşterileri görüntüle","customers.create":"Yeni müşteri ekle","customers.update":"Müşteri düzenle","customers.delete":"Müşteri sil"},"orders":{"orders.view":"Siparişleri görüntüle","orders.create":"Yeni sipariş oluştur","orders.update":"Sipariş düzenle","orders.status":"Sipariş durumu güncelle","orders.delete":"Sipariş sil/iptal"},"payments":{"payments.view":"Ödemeleri görüntüle","payments.create":"Ödeme kaydet","payments.delete":"Ödeme sil"},"operations":{"carpets.types.manage":"Halı türü/fiyat yönetimi","vehicles.manage":"Araç/plaka yönetimi","service_areas.manage":"Hizmet bölgeleri yönetimi"},"management":{"reports.view":"Raporları görüntüle","users.manage":"Kullanıcı yönetimi","settings.manage":"Firma ayarları yönetimi","firm.edit":"Firma bilgilerini düzenle"}},"role_defaults":{"super_admin":"* (tüm yetkiler)","moderator":"Sadece view yetkileri (customers.view, orders.view, payments.view, reports.view) — write işlemleri middleware seviyesinde engellenir","firm_admin":"Tüm firma yetkileri","employee":"customers.view/create/update, orders.view/create/update/status, payments.view/create, reports.view","driver":"customers.view, orders.view, orders.status (sadece görüntüleme + durum güncelleme)"},"usage_example":{"description":"Bir çalışana sadece müşteri görüntüleme yetkisi verme:","request":{"method":"POST","path":"/users","body":{"name":"Sınırlı Çalışan","email":"sinirli@firma.com","password":"******","role":"employee","firm_id":1,"custom_permissions":["customers.view","orders.view"]}}}},"errors":[{"code":200,"desc":"Başarılı"},{"code":201,"desc":"Oluşturuldu"},{"code":400,"desc":"Hatalı istek"},{"code":401,"desc":"Yetkisiz (token yok / geçersiz / süresi dolmuş)"},{"code":403,"desc":"Yasaklı (yetersiz rol)"},{"code":404,"desc":"Bulunamadı"},{"code":422,"desc":"Doğrulama hatası (errors objesi içerir)"},{"code":500,"desc":"Sunucu hatası"}],"endpoints":[{"group":"Kimlik Doğrulama","icon":"shield-lock","color":"primary","endpoints":[{"method":"POST","path":"/auth/login","desc":"E-posta + şifre ile giriş, JWT token al","roles":["public"],"auth":"none","body":{"email":"string (required)","password":"string (required, min 6)"},"returns":"access_token, refresh_token, user object"},{"method":"POST","path":"/auth/refresh","desc":"Refresh token ile yeni access token al","roles":["public"],"auth":"none","body":{"refresh_token":"string (required)"}},{"method":"GET","path":"/auth/me","desc":"Giriş yapan kullanıcı bilgisi","roles":["authenticated"],"auth":"bearer"},{"method":"PUT","path":"/auth/profile","desc":"Kendi profilini güncelle","roles":["authenticated"],"auth":"bearer","body":{"name":"string","phone":"string","password":"string (opsiyonel, min 6)"}}]},{"group":"Firmalar","icon":"building","color":"info","endpoints":[{"method":"GET","path":"/firms","desc":"Firmaları listele (sayfalı)","roles":["super_admin","moderator"],"auth":"bearer","query":{"page":"int","per_page":"int","search":"string"}},{"method":"POST","path":"/firms","desc":"Yeni firma + yöneticisi oluştur","roles":["super_admin"],"auth":"bearer","body":{"name":"string (required)","plan_id":"int","license_starts_at":"date","license_expires_at":"date","phone":"string","email":"string","tax_no":"string","tax_office":"string","city":"string","address":"string","admin_name":"string (required)","admin_email":"string (required)","admin_password":"string (required, min 6)","admin_phone":"string"}},{"method":"GET","path":"/firms/{id}","desc":"Firma detayı (effective_limits, license_status, active_overrides dahil)","roles":["super_admin","moderator","firm_admin"],"auth":"bearer"},{"method":"PUT","path":"/firms/{id}","desc":"Firma güncelle (super_admin tüm alanları, firm_admin sadece bilgileri)","roles":["super_admin","firm_admin"],"auth":"bearer"},{"method":"DELETE","path":"/firms/{id}","desc":"Firmayı devre dışı bırak","roles":["super_admin"],"auth":"bearer"},{"method":"GET","path":"/firms/{id}/usage","desc":"Firma kullanım/limit raporu (% dahil)","roles":["super_admin","moderator","firm_admin"],"auth":"bearer"},{"method":"POST","path":"/firms/{id}/extend-license","desc":"Lisans süresini uzat","roles":["super_admin"],"auth":"bearer","body":{"days":"int (required, > 0)"}}]},{"group":"Planlar","icon":"layers","color":"warning","endpoints":[{"method":"GET","path":"/plans","desc":"Tüm planları listele (firm_count dahil)","roles":["authenticated"],"auth":"bearer"},{"method":"POST","path":"/plans","desc":"Yeni plan oluştur","roles":["super_admin"],"auth":"bearer","body":{"code":"string (required, unique)","name":"string (required)","price_monthly":"float","duration_days":"int","max_users":"int (required)","max_customers":"int (required)","max_orders_per_month":"int (required)","can_use_sms":"bool","can_use_webhook":"bool","can_use_reports":"bool","can_use_custom_carpet_types":"bool","can_export_data":"bool"}},{"method":"GET","path":"/plans/{id}","desc":"Plan detayı","roles":["authenticated"],"auth":"bearer"},{"method":"PUT","path":"/plans/{id}","desc":"Planı güncelle","roles":["super_admin"],"auth":"bearer"},{"method":"DELETE","path":"/plans/{id}","desc":"Planı sil (kullanımdaysa engellenir)","roles":["super_admin"],"auth":"bearer"}]},{"group":"Müşteriler","icon":"people","color":"success","endpoints":[{"method":"GET","path":"/customers","desc":"Müşteri listesi (firma scoped, sayfalı)","roles":["firm_admin","employee","driver"],"auth":"bearer","query":["page","per_page","search","city"]},{"method":"GET","path":"/customers/search?q=","desc":"Autocomplete arama (max 10 sonuç)","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"POST","path":"/customers","desc":"Yeni müşteri oluştur (limit kontrolü vardır)","roles":["firm_admin","employee","driver"],"auth":"bearer","body":{"first_name":"string (required)","last_name":"string (required)","phone":"string (required)","phone2":"string","email":"string","address":"string","city":"string","district":"string","latitude":"float (-90..90)","longitude":"float (-180..180)","location_note":"string","notes":"string"}},{"method":"GET","path":"/customers/{id}","desc":"Müşteri detayı","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"PUT","path":"/customers/{id}","desc":"Müşteri güncelle","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"DELETE","path":"/customers/{id}","desc":"Müşteriyi devre dışı bırak","roles":["super_admin","firm_admin"],"auth":"bearer"},{"method":"GET","path":"/customers/{id}/orders","desc":"Müşterinin siparişleri","roles":["firm_admin","employee","driver"],"auth":"bearer"}]},{"group":"Halılar","icon":"tags","color":"info","endpoints":[{"method":"GET","path":"/carpets/types","desc":"Halı türleri ve fiyatları (firma bazlı + yerleşik)","roles":["authenticated"],"auth":"bearer"},{"method":"POST","path":"/carpets/types","desc":"Özel halı türü ekle","roles":["firm_admin"],"auth":"bearer","body":{"label":"string (required)","price":"float (required)","group_name":"string","description":"string"}},{"method":"PUT","path":"/carpets/types/{key}","desc":"Özel halı türünü güncelle","roles":["firm_admin"],"auth":"bearer"},{"method":"DELETE","path":"/carpets/types/{key}","desc":"Özel halı türünü sil (kullanımdaysa engellenir)","roles":["firm_admin"],"auth":"bearer"},{"method":"GET","path":"/carpets","desc":"Halı kayıtları listesi","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"GET","path":"/carpets/{id}","desc":"Halı detayı","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"GET","path":"/carpets/{id}/barcode","desc":"Barkod SVG (Content-Type: image/svg+xml)","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"GET","path":"/customers/{id}/carpets","desc":"Müşterinin halıları","roles":["firm_admin","employee","driver"],"auth":"bearer"}]},{"group":"Siparişler","icon":"clipboard-check","color":"primary","endpoints":[{"method":"GET","path":"/orders","desc":"Sipariş listesi (filtre + arama, sayfalı)","roles":["firm_admin","employee","driver"],"auth":"bearer","query":["page","per_page","search","status","service_type","payment_status","priority","date_from","date_to","customer_id"]},{"method":"POST","path":"/orders","desc":"Yeni sipariş — çoklu halı kalemi (items) destekli. Tek bir sipariş kaydı oluşur, her kalem için quantity kadar halı kaydı (barkod) açılır.","roles":["firm_admin","employee","driver"],"auth":"bearer","body":{"customer_id":"int (required)","items":"array (required, en az 1 eleman) — her eleman: {carpet_type, width, length, quantity, unit_price?}","items[].carpet_type":"string (required) - halı türü kodu","items[].width":"float (required, m)","items[].length":"float (required, m)","items[].quantity":"int (default: 1) - aynı türden kaç halı","items[].unit_price":"float (opsiyonel; boşsa firma plan fiyatı)","service_type":"string (required) - tüm sipariş için tek servis","pickup_date":"datetime (required)","estimated_delivery":"datetime","priority":"string (normal|urgent|express)","pickup_address":"string","delivery_address":"string","courier_name":"string","courier_phone":"string","notes":"string"},"returns":"Tek order objesi + items[] array (her item için id, carpet_type, carpet_type_label, width, length, quantity, unit_price, line_total, carpet_ids[], barcodes[])"},{"method":"GET","path":"/orders/dashboard","desc":"Dashboard istatistikleri (today/week/month)","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"GET","path":"/orders/{id}","desc":"Sipariş detayı (status_history + payments dahil)","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"PUT","path":"/orders/{id}","desc":"Sipariş güncelle (priority, dates, courier, unit_price)","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"PATCH","path":"/orders/{id}/status","desc":"Sipariş durumunu güncelle (webhook tetikler)","roles":["firm_admin","employee","driver"],"auth":"bearer","body":{"status":"string (required)","note":"string"}},{"method":"GET","path":"/orders/{id}/history","desc":"Sipariş durum geçmişi","roles":["firm_admin","employee","driver"],"auth":"bearer"}]},{"group":"Ödemeler","icon":"cash-coin","color":"success","endpoints":[{"method":"GET","path":"/payments","desc":"Ödeme listesi","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"POST","path":"/payments","desc":"Ödeme kaydet (kısmi ödeme destekli, fazla ödeme engellenir)","roles":["firm_admin","employee","driver"],"auth":"bearer","body":{"order_id":"int (required)","amount":"float (required)","payment_method":"string (cash|credit_card|debit_card|bank_transfer|other)","reference_no":"string","note":"string","payment_date":"datetime"}},{"method":"GET","path":"/payments/{id}","desc":"Ödeme detayı","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"DELETE","path":"/payments/{id}","desc":"Ödeme sil (sipariş tutarı yeniden hesaplanır)","roles":["super_admin","firm_admin"],"auth":"bearer"},{"method":"GET","path":"/orders/{id}/payments","desc":"Siparişin ödemeleri","roles":["firm_admin","employee","driver"],"auth":"bearer"}]},{"group":"Araçlar (Plakalar)","icon":"truck","color":"info","endpoints":[{"method":"GET","path":"/vehicles","desc":"Firma araçları (plakalar) listesi","roles":["firm_admin"],"auth":"bearer","query":["page","per_page","search","driver_id"],"returns":"driver_name + driver_phone JOIN dahil"},{"method":"POST","path":"/vehicles","desc":"Yeni araç ekle (plaka firma içinde benzersiz, otomatik upper-case)","roles":["firm_admin"],"auth":"bearer","body":{"plate":"string (required, max 20) - örn: 34 ABC 123","brand":"string","model":"string","color":"string","year":"int (1990-2030)","capacity_kg":"int - yük kapasitesi kg","driver_id":"int (opsiyonel) - sadece role=driver olan firma kullanıcıları","notes":"string"}},{"method":"GET","path":"/vehicles/drivers","desc":"Firma şoförleri listesi (vehicle eşleştirme için)","roles":["authenticated"],"auth":"bearer"},{"method":"GET","path":"/vehicles/{id}","desc":"Araç detayı","roles":["firm_admin"],"auth":"bearer"},{"method":"PUT","path":"/vehicles/{id}","desc":"Araç güncelle","roles":["firm_admin"],"auth":"bearer"},{"method":"DELETE","path":"/vehicles/{id}","desc":"Aracı devre dışı bırak (soft delete, is_active=0)","roles":["firm_admin"],"auth":"bearer"}]},{"group":"Hizmet Bölgeleri","icon":"geo-alt","color":"success","endpoints":[{"method":"GET","path":"/service-areas","desc":"Hizmet bölgeleri listesi (firma scoped)","roles":["authenticated"],"auth":"bearer","query":{"grouped":"bool (1 ise şehre göre gruplandırılmış object döner)"},"returns":"Düz liste veya {city: [{district, delivery_fee, extra_delivery_days}]}"},{"method":"POST","path":"/service-areas","desc":"Tek hizmet bölgesi ekle","roles":["firm_admin"],"auth":"bearer","body":{"city":"string (required, max 50)","district":"string (required, max 50)","delivery_fee":"float - bölgeye özel teslim ücreti TL","extra_delivery_days":"int - standart süreye eklenecek gün","notes":"string"}},{"method":"POST","path":"/service-areas/bulk","desc":"Toplu bölge ekleme (mevcut olanlar atlanır)","roles":["firm_admin"],"auth":"bearer","body":{"areas":"array - her eleman: {city, district, delivery_fee?, extra_delivery_days?}"},"returns":"{added: count}"},{"method":"GET","path":"/service-areas/{id}","desc":"Bölge detayı","roles":["firm_admin"],"auth":"bearer"},{"method":"PUT","path":"/service-areas/{id}","desc":"Bölge güncelle","roles":["firm_admin"],"auth":"bearer"},{"method":"DELETE","path":"/service-areas/{id}","desc":"Bölge sil (hard delete)","roles":["firm_admin"],"auth":"bearer"}]},{"group":"Kullanıcılar","icon":"person-gear","color":"secondary","endpoints":[{"method":"GET","path":"/users?firm_id=X","desc":"Firma kullanıcıları","roles":["super_admin","moderator","firm_admin"],"auth":"bearer","query":["firm_id","page","per_page","search","role"]},{"method":"GET","path":"/users?system_only=1","desc":"Sistem kullanıcıları (super_admin + moderator)","roles":["super_admin","moderator"],"auth":"bearer"},{"method":"POST","path":"/users","desc":"Yeni kullanıcı oluştur","roles":["super_admin","firm_admin"],"auth":"bearer","body":{"name":"string (required)","email":"string (required, unique)","password":"string (required, min 6)","phone":"string","role":"string (super_admin/moderator/firm_admin/employee/driver)","firm_id":"int (sistem rolleri için NULL)","custom_permissions":"array (opsiyonel) - rol varsayılan yetkilerini override eder. Örn: [\"customers.view\",\"orders.view\"]"}},{"method":"GET","path":"/users/{id}","desc":"Kullanıcı detayı (custom_permissions JSON dahil)","roles":["super_admin","moderator","firm_admin"],"auth":"bearer"},{"method":"PUT","path":"/users/{id}","desc":"Kullanıcı güncelle (şifre + custom_permissions dahil)","roles":["super_admin","firm_admin"],"auth":"bearer","body":{"name":"string","email":"string","phone":"string","password":"string (opsiyonel, boşsa değişmez)","role":"string","is_active":"bool","custom_permissions":"array | null - null = rol varsayılanına döndür"}},{"method":"DELETE","path":"/users/{id}","desc":"Kullanıcıyı devre dışı bırak","roles":["super_admin","firm_admin"],"auth":"bearer"}]},{"group":"Ayarlar","icon":"gear","color":"dark","endpoints":[{"method":"GET","path":"/settings","desc":"Firma ayarları (gruplu) — company, pricing, notification, system, operation, carpet_prices","roles":["firm_admin"],"auth":"bearer","returns":"Gruplar: company (firma bilgileri), pricing (KDV/para birimi), notification (SMS şablonları, webhook), system (barkod prefix, varsayılan teslim süresi), operation (yıkama/kurutma süreleri, çalışma saatleri, otomatik durum akışı), carpet_prices (halı türü m² fiyatları)"},{"method":"PUT","path":"/settings","desc":"Firma ayarlarını topluca güncelle. Anahtarlar (örnek): default_delivery_days, wash_default_days, drying_default_days, quality_check_required, auto_calculate_delivery_date, working_hours_start, working_hours_end, working_days, order_min_area_m2, sms_template_pickup, sms_template_ready, sms_template_delivered, vat_rate, currency, webhook_url, webhook_secret, barcode_prefix, carpet_price_<type_key>","roles":["firm_admin"],"auth":"bearer","body":{"settings":"object {key: value}"}},{"method":"GET","path":"/settings/{group}","desc":"Belirli grupta ayarları al (operation, notification, vb.)","roles":["firm_admin","employee","driver"],"auth":"bearer"},{"method":"GET","path":"/admin/settings","desc":"Sistem ayarları (firm_id IS NULL)","roles":["super_admin","moderator"],"auth":"bearer"},{"method":"PUT","path":"/admin/settings","desc":"Sistem ayarlarını güncelle","roles":["super_admin"],"auth":"bearer"}]},{"group":"Raporlar","icon":"graph-up","color":"success","endpoints":[{"method":"GET","path":"/reports/revenue","desc":"Gelir raporu (firma scoped)","roles":["firm_admin"],"auth":"bearer","query":["date_from","date_to"],"returns":"summary, daily, by_service, by_customer, payment_methods"}]},{"group":"Sistem Yönetim","icon":"shield-fill","color":"danger","endpoints":[{"method":"GET","path":"/admin/dashboard","desc":"Sistem dashboard (tüm firmalar geneli)","roles":["super_admin","moderator"],"auth":"bearer"},{"method":"GET","path":"/admin/health","desc":"Sistem sağlık (PHP, MySQL, disk)","roles":["super_admin","moderator"],"auth":"bearer"},{"method":"GET","path":"/admin/api-endpoints","desc":"API endpoint listesi (admin paneli için)","roles":["super_admin","moderator"],"auth":"bearer"}]},{"group":"Public Endpoints","icon":"globe","color":"secondary","endpoints":[{"method":"GET","path":"/track?q=","desc":"Sipariş takip (barkod, telefon veya sipariş no ile)","roles":["public"],"auth":"none","query":{"q":"string (required, min 3 char)"}},{"method":"GET","path":"/docs","desc":"Bu API dokümantasyonu (JSON)","roles":["public"],"auth":"none"},{"method":"GET","path":"/docs.md","desc":"API dokümantasyonu (Markdown)","roles":["public"],"auth":"none"}]}],"webhook":{"description":"Sipariş durumu değiştiğinde firma ayarlarındaki webhook_url'ye POST isteği gönderilir.","configuration":"Firma Ayarları → Bildirim → webhook_url ve webhook_secret","request":{"method":"POST","headers":{"Content-Type":"application/json","X-Webhook-Signature":"HMAC-SHA256(payload, secret)","X-Webhook-Event":"order.status_changed"},"body":{"event":"order.status_changed","order_id":123,"order_no":"SP25042500001","new_status":"pending_delivery","status_label":"Teslim Edilecek","customer":{"name":"Ahmet Yılmaz","phone":"05001234567"},"note":"Yıkama tamamlandı","timestamp":"2026-04-29T18:56:30+00:00"}},"verification_php":"$payload = file_get_contents('php://input');\n$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';\n$expected = hash_hmac('sha256', $payload, $webhookSecret);\nif (hash_equals($expected, $signature)) {\n    $data = json_decode($payload, true);\n    // Güvenilir payload\n}","statuses":{"pending_pickup":"Teslim Alınacak","pending_delivery":"Teslim Edilecek","delivered":"Teslim Edildi","cancelled":"İptal Edildi"}}}}