Dokumentasi API Reseller
Endpoint ini tersedia untuk member Gold dan Diamond. Semua request harus disertai header autentikasi HMAC-SHA256. API Key tersedia di Member Area.
Base URL
https://isiin.id/api/v1
Autentikasi
Setiap request wajib menyertakan tiga header berikut:
X-Api-Key: {api_key}
X-Timestamp: {unix_timestamp_detik}
X-Signature: {hmac_sha256}
Formula Signature
payload = METHOD + "\n" + path + "\n" + timestamp + "\n" + SHA256(request_body) X-Signature = HMAC-SHA256(payload, api_secret)
Timestamp harus dalam 5 menit dari waktu server. Body kosong = SHA256 dari string kosong.
Contoh (PHP)
$timestamp = time();
$body = json_encode(['product_code' => 'TLP5000', 'target_number' => '08123456789']);
$bodyHash = hash('sha256', $body);
$payload = implode("\n", ['POST', '/api/v1/transaction', $timestamp, $bodyHash]);
$signature = hash_hmac('sha256', $payload, $apiSecret);
HTTP Status Codes
| 200 | OK — pembayaran sync berhasil / status transaksi |
| 202 | Accepted — pembelian masuk antrian (async) |
| 400 | Bad Request — inquiry gagal (nomor tidak ditemukan, tagihan tidak ada) |
| 401 | Unauthorized — header tidak valid / timestamp kedaluwarsa |
| 402 | Payment Required — saldo tidak mencukupi |
| 403 | Forbidden — level bukan Gold/Diamond |
| 404 | Not Found |
| 422 | Unprocessable — field wajib tidak ada / tipe produk tidak sesuai / inquiry_id tidak valid atau expired / inquiry_total tidak cocok dengan data inquiry |
| 429 | Too Many Requests — melampaui batas 100 request/menit |
| 500 | Internal Server Error — gagal terbitkan tiket pesawat (saldo dikembalikan otomatis) |
| 503 | Service Unavailable — maintain mode aktif |
Callback Notification
Saat transaksi berhasil (status=success), sistem akan mengirimkan HTTP POST ke Callback URL yang Anda daftarkan di Member Area → API Key.
Format Payload (JSON)
{
"event": "transaction.success",
"order_id": "TRX20260508143201A3F9C12B",
"status": "success",
"product_id": "uuid",
"target_number": "08123456789",
"amount": 6500,
"provider_ref": "SN_OR_REF_ID",
"processed_at": "2026-05-08 14:32:05"
}
- Timeout pengiriman: 5 detik. Server Anda harus merespons dengan HTTP 2xx.
- Kegagalan pengiriman dicatat di log sistem — transaksi tetap sukses.
- Tidak ada retry otomatis. Gunakan
GET /api/v1/transaction/{order_id}untuk memverifikasi status. - Callback URL dapat diatur di Member Area → API Key tanpa perlu regenerasi key.
Timestamp: Toleransi ±5 menit dari waktu server. Pastikan waktu sistem Anda sinkron (NTP). Kirim ulang request yang gagal karena 401 dengan timestamp baru.
Umum
/api/v1/balance
Cek Saldo
Kembalikan saldo deposit dan level member.
Response
{
"level": "gold",
"balance": 500000,
"currency": "IDR"
}
/api/v1/products
Daftar Produk
Kembalikan semua produk aktif beserta harga untuk level member Anda. Field `code` digunakan sebagai `product_code` di endpoint transaksi. Filter opsional: `?category={slug}`.
Response
{
"data": [
{
"code": "TLP5000",
"name": "Telkomsel 5.000",
"category": "Pulsa",
"category_slug": "pulsa",
"price": 6500,
"is_active": true
}
],
"total": 1,
"level": "gold"
}
Transaksi PPOB & Pulsa
/api/v1/inquiry
Inquiry Tagihan (Pembayaran)
Cek data pelanggan sebelum melakukan transaksi pembayaran (PLN, BPJS, air, dll). Hanya tersedia untuk produk dengan tipe `pembayaran`. Tidak memotong saldo. Response menyertakan `inquiry_id` yang berlaku 15 menit — wajib disertakan saat memanggil POST /api/v1/transaction untuk produk pembayaran.
Request Body (JSON)
{
"product_code": "PLN20",
"target_number": "530000123456"
}
Response
{
"inquiry_id": "550e8400-e29b-41d4-a716-446655440000",
"product_code": "PLN20",
"target_number": "530000123456",
"customer_name": "BUDI SANTOSO",
"bill_amount": 250000,
"admin_fee": 2500,
"total_amount": 252500,
"period": "202504",
"message": "Berhasil"
}
/api/v1/transaction
Buat Transaksi (Live)
Buat transaksi dan potong saldo langsung. Perilaku berbeda berdasarkan tipe produk: **pembelian** (pulsa, paket data) → tidak memerlukan inquiry, status awal `pending`, diproses async, response `202`; **pembayaran** (PLN, BPJS) → wajib sertakan `inquiry_id` dari hasil POST /api/v1/inquiry (berlaku 15 menit), diproses synchronous, response `200` dengan status final dan SN. Field `inquiry_total` bersifat opsional — jika dikirim harus cocok persis dengan `total_amount` dari inquiry (bill_amount + admin_fee).
Request Body (JSON)
// Pembelian (pulsa, paket data)
{
"product_code": "TLP5000",
"target_number": "08123456789"
}
// Pembayaran (PLN, BPJS, dll) — inquiry_id wajib
{
"product_code": "PLN20",
"target_number": "530000123456",
"inquiry_id": "550e8400-e29b-41d4-a716-446655440000",
"inquiry_total": 252500
}
Response
// Pembelian (async) — HTTP 202
{
"order_id": "TRX20260508143201A3F9C12B",
"status": "pending",
"product_code": "TLP5000",
"target_number": "08123456789",
"amount": 6500,
"message": "Transaction queued. Poll GET /api/v1/transaction/{order_id} for status."
}
// Pembayaran (sync) — HTTP 200
{
"order_id": "TRX20260508143201A3F9C12B",
"status": "success",
"product_code": "PLN20",
"target_number": "530000123456",
"amount": 252500,
"sn": "TOKEN:1234-5678-9012-3456",
"message": "Transaksi berhasil"
}
/api/v1/transaction/{order_id}
Status Transaksi
Ambil status transaksi live berdasarkan `order_id`. Gunakan untuk polling transaksi pembelian async.
Response
{
"order_id": "TRX20260508143201A3F9C12B",
"status": "success",
"product_code": "TLP5000",
"target_number": "08123456789",
"amount": 6500,
"sn": null,
"created_at": "2026-05-08 14:32:01"
}
/api/v1/demo/transaction?simulate=success
Demo — Buat Transaksi
Simulasi transaksi tanpa memotong saldo dan tanpa hit provider. Parameter `simulate`: `success`, `pending`, atau `failed`.
Request Body (JSON)
{
"product_code": "TLP5000",
"target_number": "08123456789"
}
Response
{
"order_id": "DEMO20260508143201A3F9",
"status": "success",
"product_code": "TLP5000",
"target_number": "08123456789",
"amount": 6500,
"demo": true,
"message": "Demo mode: status simulated as 'success'. No balance deducted."
}
/api/v1/demo/transaction/{order_id}
Demo — Status Transaksi
Ambil status transaksi demo berdasarkan `order_id` (prefix `DEMO`).
Response
{
"order_id": "DEMO20260508143201A3F9",
"status": "success",
"product_code": "TLP5000",
"demo": true,
"created_at": "2026-05-08 14:32:01"
}
Tiket Pesawat
/api/v1/flight/search
Cari Jadwal Penerbangan
Cari jadwal penerbangan berdasarkan rute, tanggal, dan jumlah penumpang. Response berisi array penerbangan berangkat (`depart`) dan pulang (`return`, hanya untuk `roundtrip`). Harga sudah termasuk markup sesuai level member. Gunakan `search_key` dari response saat melakukan booking.
Request Body (JSON)
{
"origin": "CGK",
"destination": "SUB",
"depart_date": "2026-06-10",
"trip_type": "oneway",
"pax_adult": 1,
"pax_child": 0,
"pax_infant": 0
}
Response
{
"depart": [
{
"airline_code": "GA",
"airline_name": "Garuda Indonesia",
"flight_number": "GA-401",
"depart_time": "06:00",
"arrive_time": "08:10",
"duration": "2j 10m",
"origin": "CGK",
"destination": "SUB",
"depart_date": "2026-06-10",
"cabin_class": "Ekonomi",
"available": 9,
"transit": 0,
"base_price": 850000,
"final_price": 885000,
"final_price_per_pax": 885000,
"search_key": "MOCK-SK-GA401-..."
}
],
"return": []
}
/api/v1/flight/book
Pesan & Terbitkan Tiket
Buat booking dan langsung terbitkan tiket dalam satu request (synchronous). Saldo dipotong otomatis. Jika penerbitan tiket gagal, saldo dikembalikan. Field `flight` berisi data penerbangan yang dipilih dari `/api/v1/flight/search`, termasuk `search_key`. Field `passengers` adalah array data penumpang sesuai jumlah `pax_adult` + `pax_child` + `pax_infant`. Gunakan `order_id` di response untuk cek status via GET `/api/v1/flight/{order_id}`.
Request Body (JSON)
{
"flight": {
"airline_code": "GA",
"airline_name": "Garuda Indonesia",
"flight_number": "GA-401",
"origin": "CGK",
"destination": "SUB",
"depart_date": "2026-06-10",
"depart_time": "06:00",
"arrive_time": "08:10",
"cabin_class": "Ekonomi",
"ticket_price": 850000,
"sales_price": 850000,
"search_key": "MOCK-SK-GA401-...",
"trip_type": "oneway",
"pax_adult": 1,
"pax_child": 0,
"pax_infant": 0
},
"passengers": [
{
"type": "adult",
"title": "Tn.",
"first_name": "Budi",
"last_name": "Santoso",
"nationality": "ID",
"id_number": "3201234567890001"
}
],
"contact_email": "budi@email.com",
"contact_phone": "08123456789"
}
Response
// Sukses — HTTP 200
{
"order_id": "FLT-XXXX260610-260602",
"status": "issued",
"booking_code": "DW-MOCK-XXXXXX",
"booking_code_airline": "MOCKABCD",
"origin": "CGK",
"destination": "SUB",
"depart_date": "2026-06-10",
"flight_number": "GA-401",
"amount": 885000,
"message": "Tiket berhasil diterbitkan"
}
// Saldo kurang — HTTP 402
{
"error": "Insufficient balance.",
"balance": 100000,
"required": 885000
}
/api/v1/flight/{order_id}
Status / Detail Tiket
Ambil detail booking tiket pesawat berdasarkan `order_id` (prefix `FLT-`). Hanya mengembalikan booking milik member yang terautentikasi.
Response
{
"order_id": "FLT-XXXX260610-260602",
"status": "issued",
"booking_code": "DW-MOCK-XXXXXX",
"booking_code_airline": "MOCKABCD",
"origin": "CGK",
"destination": "SUB",
"trip_type": "oneway",
"depart_date": "2026-06-10",
"return_date": null,
"airline": "GA",
"flight_number": "GA-401",
"cabin_class": "Ekonomi",
"pax_adult": 1,
"pax_child": 0,
"pax_infant": 0,
"amount": 885000,
"issued_at": "2026-06-02 10:00:00",
"created_at": "2026-06-02 10:00:00",
"passengers": [
{
"type": "adult",
"name": "TN. BUDI SANTOSO",
"id_number": "3201234567890001",
"seat": null,
"baggage_kg": 0
}
]
}
Hotel
/api/v1/hotel/search
Cari Hotel
Cari hotel berdasarkan kota tujuan, tanggal check-in/out, jumlah kamar, dan tamu. Harga sudah termasuk markup sesuai level member. Gunakan `search_key` dari response saat memilih kamar.
Request Body (JSON)
{
"city_code": "DPS",
"check_in": "2026-07-10",
"check_out": "2026-07-12",
"rooms": 1,
"adult_count": 2,
"child_count": 0
}
Response
{
"hotels": [
{
"hotel_code": "HTL-DPS-001",
"hotel_name": "Grand Hyatt Bali",
"hotel_stars": 5,
"city_code": "DPS",
"city_name": "Bali",
"address": "Jl. Utama No. 1, Bali",
"facilities": ["Pool", "Gym", "Spa", "Restaurant", "WiFi"],
"rating": 9.2,
"available": true,
"price_per_night": 1800000,
"display_price_per_night": 1854000,
"search_key": "MOCK-SK-HTL001-..."
}
]
}
/api/v1/hotel/rooms
Kamar Tersedia
Ambil daftar tipe kamar tersedia untuk hotel dan tanggal yang dipilih. Gunakan `search_key` dari response saat melakukan booking.
Request Body (JSON)
{
"hotel_code": "HTL-DPS-001",
"check_in": "2026-07-10",
"check_out": "2026-07-12",
"rooms": 1,
"adult_count": 2,
"child_count": 0
}
Response
{
"hotel_code": "HTL-DPS-001",
"check_in": "2026-07-10",
"check_out": "2026-07-12",
"nights": 2,
"rooms": 1,
"room_types": [
{
"room_type_code": "HTL-DPS-001-DLX",
"room_type_name": "Deluxe Room",
"bed_type": "King",
"max_occupancy": 2,
"breakfast": true,
"refundable": true,
"available": 4,
"facilities": ["AC", "TV", "WiFi", "Bathtub", "Sarapan"],
"price_per_night": 2400000,
"final_price_per_night": 2472000,
"final_total": 4994000,
"search_key": "MOCK-ROOM-DLX-..."
}
]
}
/api/v1/hotel/book
Pesan & Terbitkan Voucher Hotel
Buat booking hotel dan langsung terbitkan voucher (synchronous). Saldo dipotong otomatis. Jika penerbitan gagal, saldo dikembalikan. Field `room` berisi data kamar yang dipilih dari `/api/v1/hotel/rooms`, termasuk `search_key`. Field `guests` adalah array data tamu (minimal 1 tamu utama).
Request Body (JSON)
{
"room": {
"hotel_code": "HTL-DPS-001",
"hotel_name": "Grand Hyatt Bali",
"hotel_stars": 5,
"city_code": "DPS",
"city_name": "Bali",
"room_type_code": "HTL-DPS-001-DLX",
"room_type_name": "Deluxe Room",
"check_in": "2026-07-10",
"check_out": "2026-07-12",
"nights": 2,
"rooms": 1,
"adult_count": 2,
"child_count": 0,
"price_per_night": 2400000,
"search_key": "MOCK-ROOM-DLX-..."
},
"guests": [
{
"title": "Tn.",
"first_name": "Budi",
"last_name": "Santoso",
"nationality": "ID",
"id_number": "3201234567890001"
}
],
"contact_email": "budi@email.com",
"contact_phone": "08123456789"
}
Response
// Sukses — HTTP 200
{
"order_id": "HTL-DPS1N2-260710-A3F9",
"status": "issued",
"booking_code": "DW-HTL-XXXXXXXX",
"hotel_name": "Grand Hyatt Bali",
"check_in": "2026-07-10",
"check_out": "2026-07-12",
"amount": 4994000,
"message": "Voucher hotel berhasil diterbitkan"
}
// Saldo kurang — HTTP 402
{
"error": "Insufficient balance.",
"balance": 1000000,
"required": 4994000
}
/api/v1/hotel/{order_id}
Status / Detail Voucher Hotel
Ambil detail booking hotel berdasarkan `order_id` (prefix `HTL-`). Hanya mengembalikan booking milik member yang terautentikasi.
Response
{
"order_id": "HTL-DPS1N2-260710-A3F9",
"status": "issued",
"booking_code": "DW-HTL-XXXXXXXX",
"hotel_name": "Grand Hyatt Bali",
"hotel_stars": 5,
"city": "Bali",
"room_type": "Deluxe Room",
"check_in": "2026-07-10",
"check_out": "2026-07-12",
"nights": 2,
"rooms": 1,
"guests_adult": 2,
"guests_child": 0,
"amount": 4994000,
"issued_at": "2026-07-08 10:00:00",
"guests": [
{
"name": "TN. BUDI SANTOSO",
"nationality": "ID",
"id_number": "3201...",
"is_primary": true
}
]
}
Tiket Kereta Api
/api/v1/train/search
1. Cari Jadwal Kereta
Cari jadwal kereta berdasarkan stasiun asal, tujuan, tanggal keberangkatan, dan jumlah penumpang. Response berisi array kereta beserta kelas yang tersedia. Harga sudah termasuk markup sesuai level member. Gunakan `search_key` dari response saat melakukan booking.
Request Body (JSON)
{
"origin_code": "GMR",
"destination_code": "SGU",
"depart_date": "2026-07-15",
"pax_adult": 2,
"pax_child": 0,
"pax_infant": 0
}
Response
{
"trains": [
{
"train_number": "KA-001",
"train_name": "Argo Bromo Anggrek",
"origin_code": "GMR",
"origin_name": "Gambir",
"destination_code": "SGU",
"destination_name": "Surabaya Gubeng",
"depart_time": "08:00",
"arrive_time": "14:30",
"class_code": "EKS",
"class_name": "Eksekutif",
"available": 12,
"search_key": "MOCK-TRN001-EKS-...",
"base_price": 475000,
"markup_percent": 3.0,
"markup_rupiah": 14250,
"admin_fee": 15000,
"price_per_pax": 489250,
"total_price": 993500
}
],
"count": 5,
"origin": "GMR",
"destination": "SGU",
"date": "2026-07-15"
}
/api/v1/train/seatmap
2. Peta Kursi (Opsional)
Ambil peta kursi kereta berdasarkan nomor kereta, kode kelas, dan tanggal. Response berisi layout gerbong: jumlah baris, kolom (A/B/C/D atau A/B/C/D/E untuk EKO), dan array kursi yang sudah terpesan. Gunakan nomor kursi dari response ini di field `seat_number` pada request `/book`. **Pilih kursi bersifat opsional** — jika tidak disertakan, sistem akan assign otomatis.
Request Body (JSON)
// Query params: GET /api/v1/train/seatmap?train_number=KA-001&class_code=EKS&depart_date=2026-07-15
Response
{
"train_number": "KA-001",
"class_code": "EKS",
"depart_date": "2026-07-15",
"rows": 20,
"columns": ["A", "B", "C", "D"],
"occupied": ["1A", "2C", "5B", "7D", "10A"],
"available": 75
}
// EKO — layout 2-3 (5 kolom):
{
"rows": 25,
"columns": ["A", "B", "C", "D", "E"],
"occupied": [...],
"available": 110
}
/api/v1/train/book
3. Pesan & Terbitkan Tiket Kereta
Buat booking dan langsung terbitkan tiket kereta dalam satu request. Saldo dipotong otomatis. Jika penerbitan gagal, saldo dikembalikan. Field `train` berisi data kereta dari `/api/v1/train/search`, termasuk `search_key`. Field `passengers` adalah array data penumpang. Field `seat_number` opsional — isi dari response `/seatmap` untuk pilih kursi spesifik. Gunakan `order_id` di response untuk cek status.
Request Body (JSON)
{
"train": {
"train_number": "KA-001",
"train_name": "Argo Bromo Anggrek",
"origin_code": "GMR",
"origin_name": "Gambir",
"destination_code": "SGU",
"destination_name": "Surabaya Gubeng",
"depart_date": "2026-07-15",
"depart_time": "08:00",
"arrive_time": "14:30",
"class_code": "EKS",
"class_name": "Eksekutif",
"base_price": 475000,
"pax_adult": 2,
"pax_child": 0,
"pax_infant": 0,
"search_key": "MOCK-TRN001-EKS-..."
},
"passengers": [
{
"type": "adult",
"title": "Tn.",
"first_name": "Budi",
"last_name": "Santoso",
"gender": "M",
"birth_date": "1990-05-15",
"nationality": "ID",
"id_number": "320112345678",
"seat_number": "3A"
},
{
"type": "adult",
"title": "Ny.",
"first_name": "Sari",
"last_name": "Dewi",
"gender": "F",
"birth_date": "1992-08-20",
"nationality": "ID",
"id_number": "320198765432",
"seat_number": "3B"
}
],
"contact_email": "budi@email.com",
"contact_phone": "081234567890"
}
Response
{
"order_id": "TRN-GMRSGУ-260715-X7K2",
"booking_code": "DW-TRN-ABCD1234",
"status": "issued",
"train_name": "Argo Bromo Anggrek",
"depart_date": "2026-07-15",
"depart_time": "08:00",
"final_price": 993500
}
// Saldo kurang — HTTP 402
{
"error": "Saldo tidak mencukupi. Saldo Anda: Rp 500.000"
}
/api/v1/train/{order_id}
4. Status / E-Tiket Kereta
Ambil detail booking kereta berdasarkan `order_id` (prefix `TRN-`). Hanya mengembalikan booking milik member yang terautentikasi.
Response
{
"order_id": "TRN-GMRSGУ-260715-X7K2",
"booking_code": "DW-TRN-ABCD1234",
"booking_code_train": "KAI-XYZ123",
"train_number": "KA-001",
"train_name": "Argo Bromo Anggrek",
"class_code": "EKS",
"class_name": "Eksekutif",
"origin_code": "GMR",
"origin_name": "Gambir",
"destination_code": "SGU",
"destination_name": "Surabaya Gubeng",
"depart_date": "2026-07-15",
"depart_time": "08:00",
"arrive_time": "14:30",
"pax_adult": 2,
"pax_child": 0,
"pax_infant": 0,
"final_price": 993500,
"status": "issued",
"issued_at": "2026-07-13 10:00:00",
"passengers": [
{
"type": "adult",
"title": "Tn.",
"first_name": "Budi",
"last_name": "Santoso",
"nationality": "ID",
"seat_number": "3A"
}
]
}
Tiket Kapal Laut
/api/v1/ship/search
1. Cari Jadwal Kapal
Cari jadwal kapal Pelni berdasarkan pelabuhan asal, tujuan, tanggal keberangkatan, dan jumlah penumpang. Response berisi array jadwal kapal beserta kelas yang tersedia. Harga sudah termasuk markup sesuai level member. Simpan seluruh object ship dari response untuk digunakan di `/book`.
Request Body (JSON)
{
"origin_port": "TPRIOK",
"destination_port": "MKSSAR",
"depart_date": "2026-07-20",
"pax_adult": 2,
"pax_child": 0,
"pax_infant": 0
}
Response
{
"ships": [
{
"ship_number": "KM-001",
"ship_name": "KM Umsini",
"origin_port": "TPRIOK",
"origin_name": "Tanjung Priok (Jakarta)",
"destination_port": "MKSSAR",
"destination_name": "Makassar",
"class_code": "EKO",
"class_name": "Ekonomi",
"sub_class": "Ekonomi",
"depart_datetime": "2026-07-20 08:00:00",
"arrival_datetime": "2026-07-23 14:00:00",
"adult_fare": 350000,
"child_fare": 280000,
"infant_fare": 50000,
"hpp_total": 700000,
"markup_percent": 3,
"markup_rupiah": 21000,
"admin_fee": 50000,
"total_price": 771000
}
],
"count": 5,
"origin_port": "TPRIOK",
"origin_name": "Tanjung Priok (Jakarta)",
"destination_port": "MKSSAR",
"destination_name": "Makassar",
"depart_date": "2026-07-20"
}
/api/v1/ship/book
2. Pesan & Terbitkan Tiket Kapal
Buat booking dan langsung terbitkan tiket kapal dalam satu request. Sistem otomatis melakukan GetRoom (reservasi kamar), Booking, dan Issue ke Darmawisata. Saldo dipotong otomatis. Field `ship` berisi seluruh object jadwal dari `/search`. Field `passengers` adalah array data penumpang. Response mencakup `order_id` untuk cek status.
Request Body (JSON)
{
"ship": {
"ship_number": "KM-001",
"ship_name": "KM Umsini",
"origin_port": "TPRIOK",
"origin_call": 101,
"origin_name": "Tanjung Priok (Jakarta)",
"destination_port": "MKSSAR",
"destination_call": 201,
"destination_name": "Makassar",
"class_code": "EKO",
"class_name": "Ekonomi",
"sub_class": "Ekonomi",
"depart_datetime": "2026-07-20 08:00:00",
"arrival_datetime": "2026-07-23 14:00:00",
"adult_fare": 350000,
"child_fare": 280000,
"infant_fare": 50000,
"hpp_total": 700000,
"total_price": 771000,
"admin_fee": 50000
},
"passengers": [
{
"type": "adult",
"title": "Tn.",
"first_name": "Budi",
"last_name": "Santoso",
"birth_date": "1990-05-15",
"id_number": "3174xxxxxxxx0001",
"phone": "08123456789",
"nationality": "ID"
}
],
"contact_email": "budi@email.com",
"contact_phone": "08123456789"
}
Response
{
"order_id": "SHP-TPRIMKSS-260715-A3B2",
"booking_number": "DW-SHP-ABCD1234",
"status": "issued",
"ship_name": "KM Umsini",
"depart_datetime": "2026-07-20 08:00:00",
"final_price": 771000
}
/api/v1/ship/{order_id}
3. Status / E-Tiket Kapal
Ambil detail booking kapal berdasarkan `order_id` (prefix `SHP-`). Hanya mengembalikan booking milik member yang terautentikasi. Response mencakup detail penumpang beserta nomor tiket, nomor kamar (deck/cabin/bed), dan QR code tiket individual.
Response
{
"order_id": "SHP-TPRIMKSS-260715-A3B2",
"booking_number": "DW-SHP-ABCD1234",
"ship_number": "KM-001",
"ship_name": "KM Umsini",
"class_code": "EKO",
"class_name": "Ekonomi",
"origin_port": "TPRIOK",
"origin_name": "Tanjung Priok (Jakarta)",
"destination_port": "MKSSAR",
"destination_name": "Makassar",
"depart_datetime": "2026-07-20 08:00:00",
"arrival_datetime": "2026-07-23 14:00:00",
"pax_adult": 1,
"pax_child": 0,
"pax_infant": 0,
"final_price": 771000,
"status": "issued",
"issued_at": "2026-07-15 10:00:00",
"passengers": [
{
"type": "adult",
"first_name": "Budi",
"last_name": "Santoso",
"deck": "Dek 5",
"cabin": "Kabin 01",
"bed": "Kasur 1",
"ticket_number": "TKT-ABCDEF1234",
"ticket_qr_code": "QR-MOCK-ABCDEF123456789"
}
]
}
Tiket Kapal DLU
/api/v1/ship-dlu/search
1. Cari Jadwal Kapal DLU
Cari jadwal kapal DLU berdasarkan pelabuhan asal, tujuan, dan tanggal. Response berisi array jadwal beserta pilihan fare (kelas/tipe tiket: penumpang atau kendaraan). Harga sudah termasuk markup sesuai level member. Simpan seluruh object fare yang dipilih untuk digunakan di `/book`.
Request Body (JSON)
{
"origin_port": "TPRIOK",
"destination_port": "BALI",
"depart_date": "2026-07-20"
}
Response
{
"schedules": [
{
"ship_number": "DLU-001",
"ship_name": "KMP Leuser",
"ship_id": "DLU-S001",
"depart_datetime": "2026-07-20 07:00:00",
"arrival_datetime": "2026-07-22 15:00:00",
"origin_port": "TPRIOK",
"origin_name": "Tanjung Priok (Jakarta)",
"destination_port": "BALI",
"destination_name": "Benoa (Bali)",
"fares": [
{
"data": "EKO|PAX",
"ticketType": "Penumpang",
"class": "Ekonomi",
"hpp_price": 280000,
"markup_rupiah": 11200,
"admin_fee": 50000,
"total_price": 341200
}
]
}
],
"count": 1
}
/api/v1/ship-dlu/book
2. Pesan & Terbitkan Tiket Kapal DLU
Buat booking dan langsung terbitkan tiket kapal DLU dalam satu request (tidak ada step GetRoom/Booking terpisah). Saldo dipotong otomatis. Field `ship` berisi object jadwal dari `/search` ditambah info fare yang dipilih. Field `passengers` adalah array data penumpang. Field `vehicles` (opsional) untuk kendaraan yang diangkut.
Request Body (JSON)
{
"ship": {
"ship_number": "DLU-001",
"ship_name": "KMP Leuser",
"ship_id": "DLU-S001",
"origin_port": "TPRIOK",
"origin_name": "Tanjung Priok (Jakarta)",
"destination_port": "BALI",
"destination_name": "Benoa (Bali)",
"depart_datetime": "2026-07-20 07:00:00",
"arrival_datetime": "2026-07-22 15:00:00",
"ticket_type": "Penumpang",
"class_type": "Ekonomi",
"pax_adult": 1,
"pax_child": 0,
"pax_infant": 0
},
"passengers": [
{
"type": "adult",
"first_name": "Budi",
"last_name": "Santoso",
"gender": "M",
"birth_date": "1990-01-15",
"id_number": "3271xxxxxxxxxx",
"nationality": "ID",
"ticket_type": "Penumpang",
"class_type": "Ekonomi",
"fare": 280000
}
],
"vehicles": []
}
Response
{
"order_id": "DLU-TPRIBALI-260715-A3B2",
"booking_number": "DW-DLU-ABCD1234",
"status": "issued",
"ship_name": "KMP Leuser",
"depart_datetime": "2026-07-20 07:00:00",
"final_price": 341200
}
/api/v1/ship-dlu/{order_id}
3. Status / E-Tiket Kapal DLU
Ambil detail booking kapal DLU berdasarkan `order_id` (prefix `DLU-`). Hanya mengembalikan booking milik member yang terautentikasi. Response mencakup detail penumpang beserta nomor tiket dan QR code, serta daftar kendaraan jika ada.
Response
{
"order_id": "DLU-TPRIBALI-260715-A3B2",
"booking_number": "DW-DLU-ABCD1234",
"ship_number": "DLU-001",
"ship_name": "KMP Leuser",
"ticket_type": "Penumpang",
"class_type": "Ekonomi",
"origin_port": "TPRIOK",
"origin_name": "Tanjung Priok (Jakarta)",
"destination_port": "BALI",
"destination_name": "Benoa (Bali)",
"depart_datetime": "2026-07-20 07:00:00",
"arrival_datetime": "2026-07-22 15:00:00",
"pax_adult": 1,
"pax_vehicle": 0,
"final_price": 341200,
"status": "issued",
"issued_at": "2026-07-15 10:00:00",
"passengers": [
{
"type": "adult",
"first_name": "Budi",
"last_name": "Santoso",
"ticket_type": "Penumpang",
"class_type": "Ekonomi",
"ticket_number": "DLU-TKT-ABCDEF1234",
"ticket_qr_code": "DLU-QR-ABCDEF123456789"
}
],
"vehicles": []
}
Tiket Bus
/api/v1/bus/search
1. Cari Jadwal Bus
Cari jadwal bus berdasarkan terminal asal, tujuan, tanggal, dan jumlah penumpang. Harga yang dikembalikan sudah termasuk markup sesuai level member. Gunakan object schedule (termasuk `directCode`, `locationID`, `depart_id`, `arrival_id`, `selectedClass`) yang dipilih untuk request `/book`.
Request Body (JSON)
{
"origin_terminal": "Jakarta Pulo Gadung",
"destination_terminal": "Surabaya Bungurasih",
"depart_date": "2026-07-20",
"pax_adult": 1,
"pax_child": 0,
"pax_infant": 0,
"bus": ""
}
Response
{
"data": {
"schedules": [
{
"directCode": "RI-JKT-SBY-001",
"locationID": "LOC001",
"operatorName": "Rosalia Indah",
"busType": "Big Bus",
"isAllowChooseSeat": true,
"depart_time": "2026-07-20 07:00:00",
"arrival_time": "2026-07-20 16:00:00",
"depart_id": 1,
"arrival_id": 2,
"classes": [
{
"subClassFare": "EKS",
"className": "Eksekutif",
"adultHpp": 320000,
"adultFareTotal": 349600
}
]
}
],
"origin_terminal": "Jakarta Pulo Gadung",
"destination_terminal": "Surabaya Bungurasih"
}
}
/api/v1/bus/book
2. Pesan & Terbitkan Tiket Bus
Booking dan terbitkan tiket bus dalam satu request. Sistem memanggil `Bus/Booking` lalu `Bus/Issued` secara atomik. Saldo dipotong otomatis. Field `bus` berisi data jadwal dari `/search`. Field `seats` adalah array nomor kursi (kosong jika bus tidak support pilih kursi). Field `passengers` adalah array data penumpang.
Request Body (JSON)
{
"bus": {
"bus_name": "Rosalia Indah",
"origin_terminal": "Jakarta Pulo Gadung",
"destination_terminal": "Surabaya Bungurasih",
"direct_code": "RI-JKT-SBY-001",
"location_id": "LOC001",
"sub_class_fare": "EKS",
"depart_date": "2026-07-20",
"depart_id": 1,
"arrival_id": 2,
"pax_adult": 1,
"pax_child": 0,
"pax_infant": 0
},
"seats": ["A1"],
"passengers": [
{
"pax_type": "adult",
"title": "Tn.",
"first_name": "Budi",
"last_name": "Santoso",
"identity": "3271xxxxxxxxxx",
"identity_type": "KTP",
"phone": "08123456789",
"email": "budi@example.com",
"address": "Jl. Contoh No. 1",
"birth_date": "1990-01-15",
"fare": 320000
}
]
}
Response
{
"data": {
"order_id": "BUS-JAKASURA-260720-A3B2",
"booking_code": "BK-ABCD1234EF",
"reff_number": "REF-XYZ123456789",
"final_price": 349600,
"status": "issued"
}
}
/api/v1/bus/{order_id}
3. Status / E-Tiket Bus
Ambil detail booking bus berdasarkan `order_id` (prefix `BUS-`). Hanya mengembalikan booking milik member yang terautentikasi. Field `reff_number` adalah nomor tiket yang ditunjukkan ke petugas bus.
Response
{
"data": {
"order_id": "BUS-JAKASURA-260720-A3B2",
"booking_code": "BK-ABCD1234EF",
"reff_number": "REF-XYZ123456789",
"bus_name": "Rosalia Indah",
"origin_terminal": "Jakarta Pulo Gadung",
"destination_terminal": "Surabaya Bungurasih",
"depart_time": "2026-07-20 07:00:00",
"seat_numbers": "A1",
"final_price": 349600,
"status": "issued",
"issued_at": "2026-07-15 10:23:45",
"passengers": [
{
"pax_type": "adult",
"title": "Tn.",
"first_name": "Budi",
"last_name": "Santoso",
"fare": 320000
}
]
}
}