HT Transportation API Dokümantasyonu
Şehirlerarası otobüs yönetim sistemi için RESTful API referans rehberi. Tüm endpoint'ler, istek/yanıt örnekleri ve iş kuralları bu sayfada yer almaktadır.
Giriş
Base URL
http://localhost:8080/api/v1/
Genel Kurallar
- Tüm istekler
Content-Type: application/jsonheader'ı ile gönderilmelidir. - Kimlik doğrulama gerektiren endpoint'lerde
Authorization: Bearer <token>header'ı zorunludur. - Tarih formatı:
YYYY-MM-DD, tarih-saat formatı:YYYY-MM-DDTHH:MM:SSZ(RFC 3339). - Para birimleri kuruş (1 TL = 100 kuruş) cinsinden integer olarak taşınır.
- UUID formatında kimliklendirme kullanılır.
Başarılı Yanıt Formatı
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Örnek Kayıt"
}
}
Hata Yanıt Formatı
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Kayıt bulunamadı"
}
}
Validasyon Hatası Formatı
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Girdi doğrulama hatası",
"details": [
{
"field": "email",
"message": "Geçerli bir e-posta adresi giriniz"
},
{
"field": "password",
"message": "Şifre en az 8 karakter olmalıdır"
}
]
}
}
Kimlik Doğrulama
JWT tabanlı kimlik doğrulama sistemi. Access token süresi 15 dakika, refresh token süresi 7 gündür.
POST /api/v1/auth/login
Kullanıcı girişi yapar ve token çifti döndürür.
Yetki: Herkese açık
İstek:
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "admin@ht.com",
"password": "Admin123!"
}'
Yanıt (200):
{
"success": true,
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "dGhpcyBpcyBhIHJlZnJl...",
"expires_in": 900,
"token_type": "Bearer",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "admin@ht.com",
"first_name": "Admin",
"last_name": "User",
"role": "system_admin",
"agency_id": null
}
}
}
POST /api/v1/auth/refresh
Refresh token kullanarak yeni access token alır.
Yetki: Herkese açık
İstek:
curl -X POST http://localhost:8080/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "dGhpcyBpcyBhIHJlZnJl..."
}'
Yanıt (200):
{
"success": true,
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "yenilenmis_refresh_token...",
"expires_in": 900,
"token_type": "Bearer"
}
}
GET /api/v1/auth/me
Mevcut oturumdaki kullanıcı bilgilerini döndürür.
Yetki: Tüm oturum açmış kullanıcılar
İstek:
curl http://localhost:8080/api/v1/auth/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Yanıt (200):
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "admin@ht.com",
"first_name": "Admin",
"last_name": "User",
"role": "system_admin",
"agency_id": null,
"created_at": "2026-01-15T10:30:00Z"
}
}
POST /api/v1/users
Yeni kullanıcı oluşturur.
Yetki: user.create
İstek:
curl -X POST http://localhost:8080/api/v1/users \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"email": "personel@ht.com",
"password": "Sifre123!",
"first_name": "Ahmet",
"last_name": "Yılmaz",
"role": "central_staff"
}'
GET /api/v1/users
Kullanıcı listesini döndürür.
Yetki: user.read
İstek:
curl http://localhost:8080/api/v1/users \
-H "Authorization: Bearer <token>"
Güzergah
Şehirlerarası güzergah ve durak yönetimi. Her güzergah birden fazla durak içerebilir ve durakların biniş/iniş özellikleri ayrı ayrı tanımlanır.
POST /api/v1/routes
Yeni güzergah ve durakları oluşturur.
Yetki: route.create
İstek:
curl -X POST http://localhost:8080/api/v1/routes \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "İstanbul - Ankara",
"origin_city": "İstanbul",
"destination_city": "Ankara",
"distance_km": 450,
"duration_minutes": 360,
"base_price_kurus": 35000,
"stops": [
{
"stop_name": "İstanbul Otogar",
"city": "İstanbul",
"district": "Bayrampaşa",
"is_boarding": true,
"is_dropoff": false,
"stop_order": 1
},
{
"stop_name": "Bolu Dinlenme",
"city": "Bolu",
"district": "Merkez",
"is_boarding": true,
"is_dropoff": true,
"stop_order": 2
},
{
"stop_name": "Ankara AŞTİ",
"city": "Ankara",
"district": "Yenimahalle",
"is_boarding": false,
"is_dropoff": true,
"stop_order": 3
}
]
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "İstanbul - Ankara",
"origin_city": "İstanbul",
"destination_city": "Ankara",
"distance_km": 450,
"duration_minutes": 360,
"base_price_kurus": 35000,
"is_active": true,
"stops": [
{
"id": "s1000000-0000-0000-0000-000000000001",
"stop_name": "İstanbul Otogar",
"city": "İstanbul",
"district": "Bayrampaşa",
"is_boarding": true,
"is_dropoff": false,
"stop_order": 1
},
{
"id": "s1000000-0000-0000-0000-000000000002",
"stop_name": "Bolu Dinlenme",
"city": "Bolu",
"district": "Merkez",
"is_boarding": true,
"is_dropoff": true,
"stop_order": 2
},
{
"id": "s1000000-0000-0000-0000-000000000003",
"stop_name": "Ankara AŞTİ",
"city": "Ankara",
"district": "Yenimahalle",
"is_boarding": false,
"is_dropoff": true,
"stop_order": 3
}
],
"created_at": "2026-01-20T09:00:00Z"
}
}
GET /api/v1/routes
Tüm güzergahları listeler.
Yetki: route.read
İstek:
curl http://localhost:8080/api/v1/routes \
-H "Authorization: Bearer <token>"
GET /api/v1/routes/:id
Belirli bir güzergahın detayını duraklar ile birlikte döndürür.
Yetki: route.read
İstek:
curl http://localhost:8080/api/v1/routes/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer <token>"
Koltuk Düzeni
Araç koltuk düzeni şablonları. 2+1, 2+2 gibi farklı konfigürasyon tipleri desteklenir. Her koltuk satır, sütun ve tip bilgisi ile tanımlanır.
POST /api/v1/seat-layouts
Yeni koltuk düzeni oluşturur.
Yetki: seat_layout.create
İstek:
curl -X POST http://localhost:8080/api/v1/seat-layouts \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "2+1 Standart",
"layout_type": "2+1",
"total_seats": 40,
"column_count": 3,
"seats": [
{"seat_number": 1, "row": 1, "column": 0, "seat_type": "standard"},
{"seat_number": 2, "row": 1, "column": 1, "seat_type": "standard"},
{"seat_number": 3, "row": 1, "column": 2, "seat_type": "standard"}
]
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "2+1 Standart",
"layout_type": "2+1",
"total_seats": 40,
"column_count": 3,
"is_active": true,
"created_at": "2026-01-20T10:00:00Z"
}
}
GET /api/v1/seat-layouts
Tüm koltuk düzenlerini listeler.
Yetki: seat_layout.read
İstek:
curl http://localhost:8080/api/v1/seat-layouts \
-H "Authorization: Bearer <token>"
GET /api/v1/seat-layouts/:id
Belirli bir koltuk düzeninin detayını döndürür.
Yetki: seat_layout.read
İstek:
curl http://localhost:8080/api/v1/seat-layouts/b2c3d4e5-f6a7-8901-bcde-f12345678901 \
-H "Authorization: Bearer <token>"
Araç
Araç filosu yönetimi. Her araç bir koltuk düzenine bağlanır ve aktif/pasif durumu yönetilebilir.
POST /api/v1/vehicles
Yeni araç oluşturur.
Yetki: vehicle.create
İstek:
curl -X POST http://localhost:8080/api/v1/vehicles \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"plate_number": "34 HT 001",
"brand": "Mercedes",
"model": "Travego",
"year": 2023,
"seat_layout_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"plate_number": "34 HT 001",
"brand": "Mercedes",
"model": "Travego",
"year": 2023,
"seat_layout_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"is_active": true,
"created_at": "2026-01-20T11:00:00Z"
}
}
GET /api/v1/vehicles
Tüm araçları listeler.
Yetki: vehicle.read
İstek:
curl http://localhost:8080/api/v1/vehicles \
-H "Authorization: Bearer <token>"
GET /api/v1/vehicles/:id
Belirli bir aracın detayını döndürür.
Yetki: vehicle.read
İstek:
curl http://localhost:8080/api/v1/vehicles/c3d4e5f6-a7b8-9012-cdef-123456789012 \
-H "Authorization: Bearer <token>"
Sefer
Sefer planlama, arama ve durum yönetimi. Sefer oluşturulduğunda segment bazlı koltuk envanteri otomatik üretilir.
GET /api/v1/trip-search
Halka açık sefer arama. Kimlik doğrulama gerektirmez.
Yetki: Herkese açık (no auth)
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
from_city | string | Evet | Kalkış şehri |
to_city | string | Evet | Varış şehri |
departure_date | string | Evet | Tarih (YYYY-MM-DD) |
İstek:
curl "http://localhost:8080/api/v1/trip-search?from_city=Istanbul&to_city=Ankara&departure_date=2026-03-15"
Yanıt (200):
{
"success": true,
"data": [
{
"id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"route_name": "İstanbul - Ankara",
"departure_time": "2026-03-15T08:00:00Z",
"arrival_time": "2026-03-15T14:00:00Z",
"vehicle_plate": "34 HT 001",
"base_price_kurus": 35000,
"available_seats": 32,
"total_seats": 40,
"status": "scheduled",
"boarding_stops": [
{
"stop_id": "s1000000-0000-0000-0000-000000000001",
"stop_name": "İstanbul Otogar",
"city": "İstanbul"
}
],
"dropoff_stops": [
{
"stop_id": "s1000000-0000-0000-0000-000000000003",
"stop_name": "Ankara AŞTİ",
"city": "Ankara"
}
]
}
]
}
POST /api/v1/trips
Yeni sefer oluşturur. Segment ve koltuk envanteri otomatik üretilir.
Yetki: trip.create
İstek:
curl -X POST http://localhost:8080/api/v1/trips \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"route_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"vehicle_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"departure_time": "2026-03-15T08:00:00Z",
"arrival_time": "2026-03-15T14:00:00Z",
"base_price_kurus": 35000
}'
GET /api/v1/trips/:id
Sefer detayını döndürür.
Yetki: trip.read
İstek:
curl http://localhost:8080/api/v1/trips/d4e5f6a7-b8c9-0123-def0-234567890123 \
-H "Authorization: Bearer <token>"
GET /api/v1/trips/:id/seats
Seferin koltuk durumlarını döndürür (müsait, satılmış, rezerve).
Yetki: trip.read
İstek:
curl http://localhost:8080/api/v1/trips/d4e5f6a7-b8c9-0123-def0-234567890123/seats \
-H "Authorization: Bearer <token>"
GET /api/v1/trip-seats
Sefer koltuk durumlarını query parametresi ile sorgular.
Yetki: trip.read
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
trip_id | UUID | Evet | Sefer ID |
İstek:
curl "http://localhost:8080/api/v1/trip-seats?trip_id=d4e5f6a7-b8c9-0123-def0-234567890123" \
-H "Authorization: Bearer <token>"
PUT /api/v1/trips/:id/status
Sefer durumunu günceller.
Yetki: trip.create
İstek:
curl -X PUT http://localhost:8080/api/v1/trips/d4e5f6a7-b8c9-0123-def0-234567890123/status \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"status": "boarding"
}'
Yanıt (200):
{
"success": true,
"data": {
"id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"status": "boarding",
"updated_at": "2026-03-15T07:45:00Z"
}
}
Yolcu
TC Kimlik No bazlı yolcu kayıt sistemi. Yolcu bilgileri bilet ve rezervasyon işlemlerinde kullanılır.
POST /api/v1/passengers
Yeni yolcu kaydeder.
Yetki: passenger.create
İstek:
curl -X POST http://localhost:8080/api/v1/passengers \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"tc_no": "12345678901",
"ad": "Mehmet",
"soyad": "Demir",
"cinsiyet": "male",
"telefon": "05321234567",
"email": "mehmet@example.com",
"dogum_tarihi": "1990-05-15"
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
"tc_no": "12345678901",
"ad": "Mehmet",
"soyad": "Demir",
"cinsiyet": "male",
"telefon": "05321234567",
"email": "mehmet@example.com",
"dogum_tarihi": "1990-05-15",
"created_at": "2026-01-25T14:00:00Z"
}
}
GET /api/v1/passengers/:id
Yolcu detayını döndürür.
Yetki: passenger.read
İstek:
curl http://localhost:8080/api/v1/passengers/e5f6a7b8-c9d0-1234-ef01-345678901234 \
-H "Authorization: Bearer <token>"
GET /api/v1/passenger-search
TC Kimlik No ile yolcu arar.
Yetki: passenger.search
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
tc_no | string | Evet | TC Kimlik Numarası |
İstek:
curl "http://localhost:8080/api/v1/passenger-search?tc_no=12345678901" \
-H "Authorization: Bearer <token>"
Acente
Acente ağı yönetimi. Her acentenin kendine ait şubeleri, kullanıcıları ve kontör hesabı vardır. Acente kullanıcıları yalnızca kendi acentesinin verilerini görebilir.
POST /api/v1/agencies
Yeni acente oluşturur.
Yetki: agency.create
İstek:
curl -X POST http://localhost:8080/api/v1/agencies \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Anadolu Tur",
"code": "ANT",
"tax_no": "1234567890",
"tax_office": "Kadıköy VD",
"address": "Kadıköy, İstanbul",
"phone": "02161234567",
"email": "info@anadolutur.com",
"commission_rate_pct": 8.0
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "f6a7b8c9-d0e1-2345-f012-456789012345",
"name": "Anadolu Tur",
"code": "ANT",
"tax_no": "1234567890",
"tax_office": "Kadıköy VD",
"is_active": true,
"created_at": "2026-01-25T15:00:00Z"
}
}
GET /api/v1/agencies
Tüm acenteleri listeler.
Yetki: agency.read
İstek:
curl http://localhost:8080/api/v1/agencies \
-H "Authorization: Bearer <token>"
GET /api/v1/agencies/:id
Acente detayını döndürür.
Yetki: agency.read
İstek:
curl http://localhost:8080/api/v1/agencies/f6a7b8c9-d0e1-2345-f012-456789012345 \
-H "Authorization: Bearer <token>"
POST /api/v1/agency-branches/:id
Acenteye yeni şube ekler.
Yetki: branch.create
İstek:
curl -X POST http://localhost:8080/api/v1/agency-branches/f6a7b8c9-d0e1-2345-f012-456789012345 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Kadıköy Şubesi",
"address": "Kadıköy Meydan No:5",
"phone": "02161234568"
}'
Kontör
Acente ön ödemeli bakiye sistemi. Bilet satışı sırasında kontör bakiyesinden otomatik düşüm yapılır, iptal durumunda iade edilir. Tüm işlemler tam denetim izi ile kayıt altına alınır.
GET /api/v1/kontor/:agency_id
Acentenin kontör bakiyesini döndürür.
Yetki: kontor.read + acente kapsamında erişim
İstek:
curl http://localhost:8080/api/v1/kontor/f6a7b8c9-d0e1-2345-f012-456789012345 \
-H "Authorization: Bearer <token>"
Yanıt (200):
{
"success": true,
"data": {
"agency_id": "f6a7b8c9-d0e1-2345-f012-456789012345",
"agency_name": "Anadolu Tur",
"balance_kurus": 5000000,
"credit_limit_kurus": 1000000,
"available_kurus": 6000000,
"updated_at": "2026-02-01T10:30:00Z"
}
}
POST /api/v1/kontor/:agency_id/load
Acenteye kontör yükler.
Yetki: kontor.load
İstek (50.000 TL yükleme):
curl -X POST http://localhost:8080/api/v1/kontor/f6a7b8c9-d0e1-2345-f012-456789012345/load \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"amount_kurus": 5000000,
"description": "Şubat 2026 kontör yükleme"
}'
Yanıt (200):
{
"success": true,
"data": {
"transaction_id": "t1000000-0000-0000-0000-000000000001",
"agency_id": "f6a7b8c9-d0e1-2345-f012-456789012345",
"type": "load",
"amount_kurus": 5000000,
"balance_after_kurus": 10000000,
"description": "Şubat 2026 kontör yükleme",
"created_at": "2026-02-01T11:00:00Z"
}
}
GET /api/v1/kontor/:agency_id/transactions
Acentenin kontör işlem geçmişini listeler.
Yetki: kontor.transactions + acente kapsamında erişim
İstek:
curl http://localhost:8080/api/v1/kontor/f6a7b8c9-d0e1-2345-f012-456789012345/transactions \
-H "Authorization: Bearer <token>"
Yanıt (200):
{
"success": true,
"data": [
{
"id": "t1000000-0000-0000-0000-000000000001",
"type": "load",
"amount_kurus": 5000000,
"balance_after_kurus": 10000000,
"description": "Şubat 2026 kontör yükleme",
"reference_type": null,
"reference_id": null,
"created_at": "2026-02-01T11:00:00Z"
},
{
"id": "t1000000-0000-0000-0000-000000000002",
"type": "debit",
"amount_kurus": -35000,
"balance_after_kurus": 9965000,
"description": "Bilet satışı - PNR: HT7A3BX2",
"reference_type": "ticket",
"reference_id": "tk-xxx-xxx",
"created_at": "2026-02-01T12:15:00Z"
}
]
}
Rezervasyon
Geçici koltuk tutma sistemi. Rezervasyon yapıldığında koltuklar belirli bir süre tutulur ve süre dolunca otomatik olarak serbest bırakılır. Kanal bazlı hold süreleri aşağıdaki gibidir:
| Kanal | Kod | Hold Süresi |
|---|---|---|
| Mobil Uygulama | mobile | 10 dakika |
| Web Acente | web_agency | 15 dakika |
| Çağrı Merkezi | call_center | 60 dakika |
POST /api/v1/reservations
Yeni rezervasyon oluşturur.
Yetki: reservation.create
İstek:
curl -X POST http://localhost:8080/api/v1/reservations \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"trip_id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"boarding_stop_id": "s1000000-0000-0000-0000-000000000001",
"dropoff_stop_id": "s1000000-0000-0000-0000-000000000003",
"channel": "web_agency",
"passengers": [
{
"passenger_id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
"seat_number": 5
},
{
"passenger_id": "e5f6a7b8-c9d0-1234-ef01-345678901235",
"seat_number": 6
}
]
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "r1000000-0000-0000-0000-000000000001",
"pnr": "HT8K2M5N",
"trip_id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"status": "hold",
"channel": "web_agency",
"hold_until": "2026-03-15T07:15:00Z",
"passengers": [
{
"passenger_id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
"seat_number": 5,
"ad": "Mehmet",
"soyad": "Demir"
},
{
"passenger_id": "e5f6a7b8-c9d0-1234-ef01-345678901235",
"seat_number": 6,
"ad": "Ayşe",
"soyad": "Demir"
}
],
"created_at": "2026-03-15T07:00:00Z"
}
}
GET /api/v1/reservations
Rezervasyonları listeler.
Yetki: reservation.read
İstek:
curl http://localhost:8080/api/v1/reservations \
-H "Authorization: Bearer <token>"
GET /api/v1/reservations/:id
Belirli bir rezervasyonun detayını döndürür.
Yetki: reservation.read
İstek:
curl http://localhost:8080/api/v1/reservations/r1000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>"
POST /api/v1/reservation-cancel/:id
Rezervasyonu iptal eder ve koltukları serbest bırakır.
Yetki: reservation.cancel
İstek:
curl -X POST http://localhost:8080/api/v1/reservation-cancel/r1000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>"
Yanıt (200):
{
"success": true,
"data": {
"id": "r1000000-0000-0000-0000-000000000001",
"status": "cancelled",
"cancelled_at": "2026-03-15T07:10:00Z"
}
}
Biletleme
Bilet kesme, iptal ve yönetim işlemleri. Bilet doğrudan satılabildiği gibi mevcut bir rezervasyondan da dönüştürülerek kesilebilir. Her bilet benzersiz bir PNR kodu alır.
POST /api/v1/tickets
Doğrudan bilet keser (direkt satış).
Yetki: ticket.issue
İstek:
curl -X POST http://localhost:8080/api/v1/tickets \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"trip_id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"agency_id": "f6a7b8c9-d0e1-2345-f012-456789012345",
"channel": "web_agency",
"boarding_stop_id": "s1000000-0000-0000-0000-000000000001",
"dropoff_stop_id": "s1000000-0000-0000-0000-000000000003",
"base_amount_kurus": 35000,
"total_amount_kurus": 35000,
"passengers": [
{
"passenger_id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
"seat_number": 10
}
]
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "tk-1000000-0000-0000-0000-000000000001",
"pnr": "HT7A3BX2",
"trip_id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"agency_id": "f6a7b8c9-d0e1-2345-f012-456789012345",
"status": "issued",
"channel": "web_agency",
"base_amount_kurus": 35000,
"total_amount_kurus": 35000,
"passengers": [
{
"passenger_id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
"seat_number": 10,
"ad": "Mehmet",
"soyad": "Demir",
"is_boarded": false
}
],
"created_at": "2026-02-01T12:15:00Z"
}
}
GET /api/v1/tickets
Bilet listesini döndürür.
Yetki: ticket.read
İstek:
curl http://localhost:8080/api/v1/tickets \
-H "Authorization: Bearer <token>"
GET /api/v1/tickets/:id
Bilet detayını döndürür.
Yetki: ticket.read
İstek:
curl http://localhost:8080/api/v1/tickets/tk-1000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>"
GET /api/v1/ticket-by-pnr/:pnr
PNR kodu ile bilet sorgular.
Yetki: ticket.read
İstek:
curl http://localhost:8080/api/v1/ticket-by-pnr/HT7A3BX2 \
-H "Authorization: Bearer <token>"
POST /api/v1/ticket-from-reservation
Mevcut rezervasyonu bilete dönüştürür.
Yetki: ticket.issue
İstek:
curl -X POST http://localhost:8080/api/v1/ticket-from-reservation \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"reservation_id": "r1000000-0000-0000-0000-000000000001",
"base_amount_kurus": 35000,
"total_amount_kurus": 35000
}'
POST /api/v1/ticket-cancel/:id
Bileti iptal eder. Kalkış saatine kalan süreye göre kademeli iade uygulanır.
Yetki: ticket.cancel
İstek:
curl -X POST http://localhost:8080/api/v1/ticket-cancel/tk-1000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"reason": "Yolcu talebi ile iptal"
}'
Yanıt (200):
{
"success": true,
"data": {
"id": "tk-1000000-0000-0000-0000-000000000001",
"pnr": "HT7A3BX2",
"status": "cancelled",
"original_amount_kurus": 35000,
"refund_rate_pct": 80,
"refund_amount_kurus": 28000,
"cancel_reason": "Yolcu talebi ile iptal",
"cancelled_at": "2026-03-14T20:00:00Z"
}
}
PUT /api/v1/tickets/:id/board/:passenger_id
Yolcunun binişini onaylar.
Yetki: ticket.issue
İstek:
curl -X PUT http://localhost:8080/api/v1/tickets/tk-1000000-0000-0000-0000-000000000001/board/e5f6a7b8-c9d0-1234-ef01-345678901234 \
-H "Authorization: Bearer <token>"
Yanıt (200):
{
"success": true,
"data": {
"passenger_id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
"is_boarded": true,
"boarded_at": "2026-03-15T07:55:00Z"
}
}
Partner
Araç ortağı (partner) yönetimi. Partnerler araçlara pay oranı ile atanır. Komisyon ve kesinti tanımları yapılabilir. Hakediş hesaplama bu tanımlara göre çalışır.
POST /api/v1/partners
Yeni partner oluşturur.
Yetki: partner.create
İstek:
curl -X POST http://localhost:8080/api/v1/partners \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"code": "P001",
"name": "Ali Kaya",
"partner_type": "individual",
"commission_rate_pct": 8.0,
"tax_no": "12345678901",
"iban": "TR330006100519786457841326"
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "p1000000-0000-0000-0000-000000000001",
"code": "P001",
"name": "Ali Kaya",
"partner_type": "individual",
"commission_rate_pct": 8.0,
"tax_no": "12345678901",
"iban": "TR330006100519786457841326",
"is_active": true,
"created_at": "2026-01-28T09:00:00Z"
}
}
GET /api/v1/partners
Tüm partnerleri listeler.
Yetki: partner.read
İstek:
curl http://localhost:8080/api/v1/partners \
-H "Authorization: Bearer <token>"
GET /api/v1/partners/:id
Partner detayını döndürür.
Yetki: partner.read
İstek:
curl http://localhost:8080/api/v1/partners/p1000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>"
PUT /api/v1/partners/:id
Partner bilgilerini günceller.
Yetki: partner.update
İstek:
curl -X PUT http://localhost:8080/api/v1/partners/p1000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Ali Kaya Taşımacılık",
"partner_type": "corporate",
"commission_rate_pct": 7.5
}'
POST /api/v1/partners/:id/deductions
Partnere kesinti tanımı ekler.
Yetki: partner.update
İstek:
curl -X POST http://localhost:8080/api/v1/partners/p1000000-0000-0000-0000-000000000001/deductions \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"deduction_type": "fixed_kurus",
"name": "Yakıt Kesintisi",
"value": 250000
}'
Yanıt (201):
{
"success": true,
"data": {
"id": "dd-100000-0000-0000-0000-000000000001",
"partner_id": "p1000000-0000-0000-0000-000000000001",
"deduction_type": "fixed_kurus",
"name": "Yakıt Kesintisi",
"value": 250000,
"is_active": true
}
}
PUT /api/v1/partners/:id/deductions/:did
Kesinti tanımını günceller.
Yetki: partner.update
İstek:
curl -X PUT http://localhost:8080/api/v1/partners/p1000000-0000-0000-0000-000000000001/deductions/dd-100000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Yakıt Kesintisi (Güncel)",
"value": 300000
}'
DELETE /api/v1/partners/:id/deductions/:did
Kesinti tanımını siler.
Yetki: partner.update
İstek:
curl -X DELETE http://localhost:8080/api/v1/partners/p1000000-0000-0000-0000-000000000001/deductions/dd-100000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>"
POST /api/v1/vehicles/:id/partners
Araca partner atar (pay oranı ile).
Yetki: partner.update
İstek:
curl -X POST http://localhost:8080/api/v1/vehicles/c3d4e5f6-a7b8-9012-cdef-123456789012/partners \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"partner_id": "p1000000-0000-0000-0000-000000000001",
"share_pct": 60.0
}'
GET /api/v1/vehicles/:id/partners
Araca atanmış partnerleri listeler.
Yetki: partner.read
İstek:
curl http://localhost:8080/api/v1/vehicles/c3d4e5f6-a7b8-9012-cdef-123456789012/partners \
-H "Authorization: Bearer <token>"
DELETE /api/v1/vehicles/:id/partners/:pid
Araçtan partner atamasını kaldırır.
Yetki: partner.update
İstek:
curl -X DELETE http://localhost:8080/api/v1/vehicles/c3d4e5f6-a7b8-9012-cdef-123456789012/partners/p1000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>"
Hakediş
Sefer bazlı otomatik gelir paylaşımı hesaplama, onay akışı, faturalama ve cari hesap takip sistemi.
POST /api/v1/hakedish/calculate/:trip_id
Belirli bir sefer için hakediş hesaplar. Sefer durumu "completed" olmalıdır.
Yetki: hakedish.calculate
İstek:
curl -X POST http://localhost:8080/api/v1/hakedish/calculate/d4e5f6a7-b8c9-0123-def0-234567890123 \
-H "Authorization: Bearer <token>"
Yanıt (200):
{
"success": true,
"data": [
{
"id": "hk-100000-0000-0000-0000-000000000001",
"trip_id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"partner_id": "p1000000-0000-0000-0000-000000000001",
"partner_name": "Ali Kaya",
"trip_revenue_kurus": 10000000,
"share_pct": 60.0,
"gross_share_kurus": 6000000,
"commission_rate_pct": 8.0,
"commission_kurus": 480000,
"deductions_kurus": 382800,
"deduction_details": [
{"name": "Yakıt Kesintisi", "type": "fixed_kurus", "amount_kurus": 250000},
{"name": "HGS", "type": "fixed_kurus", "amount_kurus": 50000},
{"name": "Sigorta", "type": "percentage", "amount_kurus": 82800}
],
"net_amount_kurus": 5137200,
"status": "calculated",
"calculated_at": "2026-03-16T10:00:00Z"
}
]
}
GET /api/v1/hakedish/trip/:trip_id
Belirli bir seferin hakediş kayıtlarını döndürür.
Yetki: hakedish.calculate
İstek:
curl http://localhost:8080/api/v1/hakedish/trip/d4e5f6a7-b8c9-0123-def0-234567890123 \
-H "Authorization: Bearer <token>"
GET /api/v1/hakedish/partner/:partner_id
Belirli bir partnerin tüm hakediş kayıtlarını döndürür.
Yetki: partner.read
İstek:
curl http://localhost:8080/api/v1/hakedish/partner/p1000000-0000-0000-0000-000000000001 \
-H "Authorization: Bearer <token>"
PUT /api/v1/hakedish/:id/approve
Hakediş kaydını onaylar.
Yetki: hakedish.approve
İstek:
curl -X PUT http://localhost:8080/api/v1/hakedish/hk-100000-0000-0000-0000-000000000001/approve \
-H "Authorization: Bearer <token>"
Yanıt (200):
{
"success": true,
"data": {
"id": "hk-100000-0000-0000-0000-000000000001",
"status": "approved",
"approved_at": "2026-03-16T11:00:00Z",
"approved_by": "550e8400-e29b-41d4-a716-446655440000"
}
}
POST /api/v1/hakedish/invoice
Onaylanmış hakediş kayıtları için fatura oluşturur.
Yetki: hakedish.invoice
İstek:
curl -X POST http://localhost:8080/api/v1/hakedish/invoice \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"partner_id": "p1000000-0000-0000-0000-000000000001",
"entry_ids": [
"hk-100000-0000-0000-0000-000000000001",
"hk-100000-0000-0000-0000-000000000002"
],
"period_start": "2026-03-01",
"period_end": "2026-03-31"
}'
Yanıt (201):
{
"success": true,
"data": {
"invoice_id": "inv-10000-0000-0000-0000-000000000001",
"partner_id": "p1000000-0000-0000-0000-000000000001",
"period_start": "2026-03-01",
"period_end": "2026-03-31",
"total_amount_kurus": 10274400,
"entry_count": 2,
"status": "invoiced",
"created_at": "2026-04-01T09:00:00Z"
}
}
GET /api/v1/partners/:id/current-account
Partnerin cari hesap özetini döndürür.
Yetki: partner.read
İstek:
curl http://localhost:8080/api/v1/partners/p1000000-0000-0000-0000-000000000001/current-account \
-H "Authorization: Bearer <token>"
Yanıt (200):
{
"success": true,
"data": {
"partner_id": "p1000000-0000-0000-0000-000000000001",
"partner_name": "Ali Kaya",
"total_earned_kurus": 51372000,
"total_paid_kurus": 40000000,
"balance_kurus": 11372000
}
}
GET /api/v1/partners/:id/current-account/transactions
Partnerin cari hesap hareketlerini listeler.
Yetki: partner.read
İstek:
curl http://localhost:8080/api/v1/partners/p1000000-0000-0000-0000-000000000001/current-account/transactions \
-H "Authorization: Bearer <token>"
Raporlama
12 farklı aggregate rapor endpoint'i. Tüm raporlar start_date ve end_date query parametreleri ile tarih aralığı filtrelemeyi destekler.
| Metod | Endpoint | Yetki | Açıklama |
|---|---|---|---|
| GET | /api/v1/reports/dashboard | report.dashboard |
Genel özet dashboard |
| GET | /api/v1/reports/revenue/daily | report.revenue |
Günlük gelir raporu |
| GET | /api/v1/reports/revenue/by-agency | report.revenue |
Acente bazlı gelir |
| GET | /api/v1/reports/revenue/by-route | report.revenue |
Güzergah bazlı gelir |
| GET | /api/v1/reports/revenue/by-channel | report.revenue |
Kanal bazlı gelir |
| GET | /api/v1/reports/tickets/status | report.dashboard |
Bilet durum dağılımı |
| GET | /api/v1/reports/trips/occupancy | report.trips |
Sefer doluluk oranı |
| GET | /api/v1/reports/trips/status | report.trips |
Sefer durum dağılımı |
| GET | /api/v1/reports/hakedish/by-partner | report.hakedish |
Partner bazlı hakediş |
| GET | /api/v1/reports/hakedish/status | report.hakedish |
Hakediş durum dağılımı |
| GET | /api/v1/reports/ledger/summary | report.revenue |
Muhasebe defteri özeti |
| GET | /api/v1/reports/kontor/summary | report.revenue |
Kontör özet raporu |
Örnek: Dashboard Raporu
İstek:
curl "http://localhost:8080/api/v1/reports/dashboard?start_date=2026-03-01&end_date=2026-03-31" \
-H "Authorization: Bearer <token>"
Yanıt (200):
{
"success": true,
"data": {
"period": {
"start_date": "2026-03-01",
"end_date": "2026-03-31"
},
"tickets": {
"total_issued": 1250,
"total_cancelled": 87,
"total_revenue_kurus": 43750000,
"avg_ticket_price_kurus": 35000
},
"trips": {
"total_scheduled": 180,
"total_completed": 165,
"total_cancelled": 5,
"avg_occupancy_pct": 72.5
},
"reservations": {
"total_created": 890,
"total_converted": 720,
"total_expired": 120,
"conversion_rate_pct": 80.9
},
"kontor": {
"total_loaded_kurus": 50000000,
"total_spent_kurus": 43750000,
"total_refunded_kurus": 2436000
},
"hakedish": {
"total_calculated_kurus": 26250000,
"total_approved_kurus": 22000000,
"pending_approval_count": 15
}
}
}
Roller & İzinler
Sistem 6 kullanıcı rolü ve modül bazlı yetkilendirme ile çalışır. Aşağıdaki tabloda her rolün hangi modül işlemlerine erişimi olduğu gösterilmektedir.
| Rol | Kullanıcı | Güzergah | Araç | Sefer | Yolcu | Acente | Kontör | Rezervasyon | Bilet | Partner | Hakediş | Raporlama |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| system_admin | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| central_staff | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| call_center | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ |
| agency_admin | ✗ | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ |
| agency_user | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ |
| driver | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
Not: agency_admin ve agency_user rolleri yalnızca kendi acentelerine ait verileri görebilir ve işlem yapabilir (acente veri izolasyonu). driver rolü yalnızca kendi seferlerini salt okunur olarak görüntüleyebilir.
İş Kuralları
Bilet İptal ve İade Tablosu
Kalkış saatine kalan süreye göre kademeli iade oranları uygulanır:
| Kalkışa Kalan Süre | İade Oranı | Örnek (1.000 TL Bilet) |
|---|---|---|
| 24 saat ve üzeri | %100 | 1.000 TL iade |
| 12 - 24 saat arası | %80 | 800 TL iade |
| 3 - 12 saat arası | %50 | 500 TL iade |
| 3 saatten az | İptal engellenir | İptal yapılamaz |
Cinsiyet Bitişiklik Kuralı
Türk otobüs taşımacılığı düzenlemelerine uygun olarak farklı cinsiyetteki yolcular yan yana oturtulmaz. Kural detayları:
- 2+1 düzende sütun 0 (tek koltuk tarafı) muaftır. Tek koltukta yan yana oturma durumu bulunmadığı için cinsiyet kontrolü uygulanmaz.
- Aynı işlem (booking) içindeki yolcular muaftır. Birlikte seyahat eden yolcular (aile, arkadaşlar) yan yana oturabilir.
- Kontrol, koltuk satırındaki (row) aynı satırdaki diğer koltuk durumuna bakarak yapar.
- Kurala uymayan koltuk seçimi reddedilir ve uygun alternatif koltuklar önerilir.
Rezervasyon Hold Süreleri
Kanal bazlı geçici koltuk tutma süreleri:
| Kanal | Hold Süresi | Kullanım Senaryosu |
|---|---|---|
mobile | 10 dakika | Mobil uygulama üzerinden hızlı satış |
web_agency | 15 dakika | Acente web paneli üzerinden satış |
call_center | 60 dakika | Çağrı merkezi yolcu ile görüşme süresi |
Hold süresi dolduğunda rezervasyon otomatik olarak expired durumuna geçer ve koltuklar serbest bırakılır.
Sefer Durum Geçişleri
Seferler aşağıdaki durum akışını takip eder:
scheduled ──────► boarding ──────► in_transit ──────► completed
│ │
│ │
▼ ▼
cancelled cancelled
| Mevcut Durum | Geçiş Yapılabilir |
|---|---|
scheduled | boarding, cancelled |
boarding | in_transit, cancelled |
in_transit | completed |
completed | Geçiş yapılamaz (final durum) |
cancelled | Geçiş yapılamaz (final durum) |
Hakediş Hesaplama Formülü
Sefer tamamlandığında partnerlerin net hakedişleri aşağıdaki formül ile hesaplanır:
Sefer Geliri (toplam bilet satışı)
|
├── Ortak Brüt Payı = Sefer Geliri x Pay Oranı (%)
|
├── Komisyon = Brüt Pay x Komisyon Oranı (%)
|
├── Kesintiler (toplam)
| ├── Sabit kesintiler (fixed_kurus): doğrudan düşülür
| └── Yüzdelik kesintiler (percentage): Brüt Pay üzerinden hesaplanır
|
└── Net Hakediş = Brüt Pay - Komisyon - Toplam Kesintiler
Örnek hesaplama:
| Kalem | Değer |
|---|---|
| Sefer Geliri | 100.000 TL |
| Ortak Pay Oranı | %60 |
| Brüt Pay | 60.000 TL |
| Komisyon (%8) | -4.800 TL |
| Yakıt Kesintisi (sabit) | -2.500 TL |
| HGS Kesintisi (sabit) | -500 TL |
| Sigorta (%1.38 x Brüt) | -828 TL |
| Net Hakediş | 51.372 TL |