Hold Booking - Giữ Chỗ
API Endpoint: POST /api/v1/services/booking/v1/dat-chuyen
📋 Overview
Tạo booking trong trạng thái HOLD (giữ chỗ). Booking sẽ có thời hạn thanh toán (~4 giờ).
Status: trang_thai: 0 (HOLD)
Flow:
1. Search flights → Get flight UUID
2. Hold booking → Get PNR, ve_id
3. Payment (optional) → Issue ticket (trang_thai: 1)
🔌 API Specification
Endpoint
POST {{base_url}}/api/v1/services/booking/v1/dat-chuyen
Headers
{
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer {access_token}"
}
Request Body
Basic Example (No Services):
{
"api": "VJ",
"nhieu_chang": 0,
"chuyen_bay": [
{
"index": 1,
"uuid": "852ffde2-aeb0-11f0-8b81-86d224031662",
"phi_dai_ly": 0,
"index_hang_cho": 0,
"loai_phi_dai_ly": "Cơ bản"
}
],
"hanh_khach": [
{
"index": 1,
"ho": "NGUYEN VAN",
"ten": "TEST",
"email": "test@example.com",
"so_dien_thoai": "0987654321",
"ngay_sinh": "01-01-1990",
"the_thanh_vien": "",
"loai_hanh_khach": 1,
"danh_xung": 1,
"cha_me_id": null,
"ho_chieu": null
}
],
"thong_tin_booker": {
"ho": "TRAN THI",
"ten": "BOOKER",
"email": "booker@example.com",
"so_dien_thoai": "0912345678"
},
"dich_vu": [],
"cho_ngoi": [],
"ma_khuyen_mai": "",
"trang_thai": 0,
"xac_nhan_ve_dup": "",
"xac_nhan_thay_doi_gia": "",
"tong_gia_ve": 0,
"xac_nhan_cho_du_bi": ""
}
Complete Example (With Services & Insurance):
{
"api": "VJ",
"nhieu_chang": 0,
"bao_hiem": {
"uuid": "4dc7da23-8723-57e7-848f-5706bcf32257"
},
"chuyen_bay": [
{
"index": 1,
"uuid": "1f4a8f90-ba1a-11f0-a743-e69416960d28",
"phi_dai_ly": 0,
"index_hang_cho": 0,
"loai_phi_dai_ly": "Cơ bản"
}
],
"hanh_khach": [
{
"index": 1,
"ho": "NGUYEN VAN",
"ten": "TEST",
"email": "app@example.com",
"so_dien_thoai": "0702349398",
"ngay_sinh": "01-02-1993",
"the_thanh_vien": "",
"loai_hanh_khach": 1,
"danh_xung": 1,
"cha_me_id": null,
"ho_chieu": null
}
],
"thong_tin_booker": {
"ho": "AGENCY",
"ten": "BOOKER",
"email": "app@example.com",
"so_dien_thoai": "0702349398"
},
"dich_vu": [
{
"index_chang_bay": 1,
"index_chuyen_bay": 1,
"index_hanh_khach": 1,
"uuid": "044a181a-093d-8541-a41e-879caac6d017"
},
{
"index_chang_bay": 1,
"index_chuyen_bay": 1,
"index_hanh_khach": 1,
"uuid": "da38876a-cbcc-cfb3-76c0-f3fb5f6632db"
}
],
"cho_ngoi": [],
"ma_khuyen_mai": "",
"trang_thai": 0,
"xac_nhan_ve_dup": "",
"xac_nhan_thay_doi_gia": "",
"tong_gia_ve": 0,
"xac_nhan_cho_du_bi": ""
}
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
api | string | ✅ Yes | Airline API: "VJ" for VietJet |
nhieu_chang | number | ✅ Yes | Multi-city flag (0 = one-way/round-trip, 1 = multi-city) |
chuyen_bay | array | ✅ Yes | Flight segments to book |
chuyen_bay[].index | number | ✅ Yes | Segment index (1-based) |
chuyen_bay[].uuid | string | ✅ Yes | Flight UUID from search result |
chuyen_bay[].phi_dai_ly | number | ✅ Yes | Agency fee (0 for no fee) |
chuyen_bay[].index_hang_cho | number | ✅ Yes | Fare index from search (0-based) |
chuyen_bay[].loai_phi_dai_ly | string | ✅ Yes | Fee type: "Cơ bản" or "Nhập" |
hanh_khach | array | ✅ Yes | Passenger list |
hanh_khach[].index | number | ✅ Yes | Passenger index (1-based) |
hanh_khach[].ho | string | ✅ Yes | Last name (UPPERCASE) |
hanh_khach[].ten | string | ✅ Yes | First name (UPPERCASE) |
hanh_khach[].email | string | ✅ Yes | Passenger email |
hanh_khach[].so_dien_thoai | string | ✅ Yes | Phone number |
hanh_khach[].ngay_sinh | string | ✅ Yes | Date of birth (DD-MM-YYYY) |
hanh_khach[].the_thanh_vien | string | ❌ | Membership card number (optional) |
hanh_khach[].loai_hanh_khach | number | ✅ Yes | Passenger type: 1 = Adult, 2 = Child, 3 = Infant |
hanh_khach[].danh_xung | number | ✅ Yes | Title: 1 = Mr, 2 = Mrs, 3 = Ms |
hanh_khach[].cha_me_id | number/null | ✅ Yes | Parent passenger index for infant (null if not infant) |
hanh_khach[].ho_chieu | object/null | ⚠️ | Passport info (required for international flights) |
thong_tin_booker | object | ✅ Yes | Booker information |
thong_tin_booker.ho | string | ✅ Yes | Booker last name |
thong_tin_booker.ten | string | ✅ Yes | Booker first name |
thong_tin_booker.email | string | ✅ Yes | Booker email (for booking confirmation) |
thong_tin_booker.so_dien_thoai | string | ✅ Yes | Booker phone |
bao_hiem | object | ❌ | Insurance (optional) |
bao_hiem.uuid | string | ❌ | Insurance UUID (if selected) |
dich_vu | array | ✅ Yes | Services (baggage, food) - Empty [] if none selected |
dich_vu[].index_chang_bay | number | ⚠️ | Journey index (1-based) - Required if services added |
dich_vu[].index_chuyen_bay | number | ⚠️ | Flight index (1-based) - Required if services added |
dich_vu[].index_hanh_khach | number | ⚠️ | Passenger index (1-based) - Required if services added |
dich_vu[].uuid | string | ⚠️ | Service UUID from Step 2.4 - Required if services added |
cho_ngoi | array | ✅ Yes | Seat selection - Empty [] if none selected |
ma_khuyen_mai | string | ❌ | Promotion code |
trang_thai | number | ✅ Yes | Booking status: 0 = HOLD, 1 = ISSUED |
xac_nhan_ve_dup | string | ✅ Yes | Duplicate ticket confirmation (empty for new) |
xac_nhan_thay_doi_gia | string | ✅ Yes | Price change confirmation (empty) |
tong_gia_ve | number | ✅ Yes | Total price (0 for HOLD) |
xac_nhan_cho_du_bi | string | ✅ Yes | Standby seat confirmation (empty) |
✅ Success Response
Status: 200 OK
{
"message": "Giữ chỗ thành công. ",
"data": {
"ve": {
"id": 82,
"pnr": "AAMJ52",
"uuid": "853d1766-aeb0-11f0-8b81-86d224031662",
"trang_thai": 0,
"ngay_het_han": "22-10-2025 06:03:00",
"hang_bay": "VJ",
"so_hieu": "VJ 9001",
"hanh_trinh": "SGN - HAN",
"ngay_bay": "25-10-2025 08:00:00",
"gia_net": 4189100,
"thue": 630500,
"ho_ten_booker": "TRAN THI BOOKER",
"email_1": "test@example.com",
"so_dien_thoai_1": "0987654321",
"email_2": "booker@example.com",
"so_dien_thoai_2": "0912345678",
"nguoi_dai_dien": "NGUYEN VAN TEST",
"tong_hanh_khach": 1,
"tong_nguoi_lon": 1,
"tong_tre_em": 0,
"tong_em_be": 0,
"ngay_book": "22-10-2025 02:02:42",
"updated_at": "22-10-2025 02:02:42"
},
"hanh_khach": [
{
"id": 107,
"ve_id": 82,
"ho": "NGUYEN VAN",
"ten": "TEST",
"email": "test@example.com",
"so_dien_thoai": "0987654321",
"ngay_sinh": "01-01-1990",
"loai_hanh_khach": 1,
"danh_xung": 1
}
],
"chang_bay": [
{
"key_chang_bay": 0,
"hang_bay": "VJ",
"so_hieu": "VJ 9001",
"hanh_trinh": "SGN - HAN",
"diem_di": "SGN",
"diem_den": "HAN",
"ngay_di": "25-10-2025 08:00:00",
"ngay_den": "25-10-2025 09:00:00",
"hang_ve": "T1_DLX",
"loai_hang_ve": "Deluxe",
"cabin": "DELUXE",
"gia_net": 4189100
}
]
},
"status": "success",
"code": 200
}
Key Response Fields:
| Field | Type | Description |
|---|---|---|
data.ve.id | number | Booking ID (ve_id) - Critical for MMB operations |
data.ve.pnr | string | PNR - Booking reference code |
data.ve.uuid | string | Booking UUID |
data.ve.trang_thai | number | Status: 0 = HOLD, 1 = ISSUED |
data.ve.ngay_het_han | string | Payment deadline (usually +4 hours) |
data.ve.gia_net | number | Total net price |
data.hanh_khach[].id | number | Passenger ID (hanh_khach_id) - For services/seats |
data.chang_bay[].key_chang_bay | number | Flight segment key - For services/seats |
💡 Example: cURL
curl -X POST "{{base_url}}/api/v1/services/booking/v1/dat-chuyen" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {access_token}" \
-d '{
"api": "VJ",
"nhieu_chang": 0,
"chuyen_bay": [{
"index": 1,
"uuid": "852ffde2-aeb0-11f0-8b81-86d224031662",
"phi_dai_ly": 0,
"index_hang_cho": 0,
"loai_phi_dai_ly": "Cơ bản"
}],
"hanh_khach": [{
"index": 1,
"ho": "NGUYEN VAN",
"ten": "TEST",
"email": "test@example.com",
"so_dien_thoai": "0987654321",
"ngay_sinh": "01-01-1990",
"the_thanh_vien": "",
"loai_hanh_khach": 1,
"danh_xung": 1,
"cha_me_id": null,
"ho_chieu": null
}],
"thong_tin_booker": {
"ho": "TRAN THI",
"ten": "BOOKER",
"email": "booker@example.com",
"so_dien_thoai": "0912345678"
},
"dich_vu": [],
"cho_ngoi": [],
"ma_khuyen_mai": "",
"trang_thai": 0,
"xac_nhan_ve_dup": "",
"xac_nhan_thay_doi_gia": "",
"tong_gia_ve": 0,
"xac_nhan_cho_du_bi": ""
}'
Response:
{
"message": "Giữ chỗ thành công. ",
"data": {
"ve": {
"id": 82,
"pnr": "AAMJ52",
"trang_thai": 0,
"ngay_het_han": "22-10-2025 06:03:00",
"gia_net": 4189100
},
"hanh_khach": [{ "id": 107 }],
"chang_bay": [{ "key_chang_bay": 0 }]
},
"status": "success"
}
Save these values:
data.ve.id→ve_id(82)data.ve.pnr→pnr("AAMJ52")data.hanh_khach[0].id→hanh_khach_id(107)data.chang_bay[0].key_chang_bay→key_chang_bay_0(0)
⚠️ Important Notes
1. Names Must Be UPPERCASE
// ✅ Correct
ho: "NGUYEN VAN";
ten: "TEST";
// ❌ Wrong
ho: "Nguyen Van";
ten: "test";
2. Date Format
ngay_sinh: "01-01-1990"; // DD-MM-YYYY
3. Passenger Index vs Fare Index
{
"hanh_khach": [{
"index": 1 // ← Passenger index (1-based)
}],
"chuyen_bay": [{
"index": 1, // ← Segment index (1-based)
"index_hang_cho": 0 // ← Fare index (0-based from search)
}]
}
4. Save These Values
After HOLD, save for later operations:
ve_id- For get details, add services, paymentpnr- For customer referencehanh_khach_id- For add services/seatskey_chang_bay_0- For add services/seats
5. Payment Deadline
ngay_het_han: "22-10-2025 06:03:00"; // Usually +4 hours
Booking expires if not paid before deadline.
6. Services Array (dich_vu)
Empty (No Services):
"dich_vu": []
With Services (Baggage + Meal):
"dich_vu": [
{
"index_chang_bay": 1,
"index_chuyen_bay": 1,
"index_hanh_khach": 1,
"uuid": "044a181a-093d-8541-a41e-879caac6d017"
},
{
"index_chang_bay": 1,
"index_chuyen_bay": 1,
"index_hanh_khach": 1,
"uuid": "da38876a-cbcc-cfb3-76c0-f3fb5f6632db"
}
]
Service Item Structure:
index_chang_bay(1-based) - Journey/segment index (always 1 for one-way)index_chuyen_bay(1-based) - Flight index within journey (always 1 for direct flight)index_hanh_khach(1-based) - Which passenger gets this serviceuuid- Service UUID from Step 2.4 (Get Services List)
Important:
- UUIDs must come from Step 2.4 (danh-sach-phu-tro-tim-ve)
- UUIDs expire in ~5-10 minutes - fetch fresh before booking
- For multiple passengers, add separate service items for each
- Can leave empty
[]and add services later via MMB
7. Insurance (bao_hiem) - Optional
"bao_hiem": {
"uuid": "4dc7da23-8723-57e7-848f-5706bcf32257"
}
- Optional field for travel insurance
- Get UUID from insurance options (if available)
- Omit entire
bao_hiemobject if not selected
🐛 Common Issues
Missing Flight UUID
Response:
{
"message": "Không tìm thấy chuyến bay",
"status": "error"
}
Solution: Ensure uuid is from recent search result (not expired)
Invalid Date Format
Response:
{
"message": "Ngày sinh không hợp lệ",
"status": "error"
}
Solution: Use DD-MM-YYYY format (not YYYY-MM-DD)
Lowercase Names
Response:
{
"message": "Tên phải viết HOA",
"status": "error"
}
Solution: Convert names to UPPERCASE before sending
📊 Booking States
| trang_thai | Status | Description |
|---|---|---|
0 | HOLD | Booked but not paid - Has payment deadline |
1 | ISSUED | Ticket issued - Payment completed |
Transitions:
HOLD (0) --[Payment]--> ISSUED (1)
🔗 Next Steps
After HOLD, you can:
- Add Services →
../manage-booking/UPDATE-SERVICES.md - Add Seats →
../manage-booking/BUY-SEAT.md - Payment →
05-PAYMENT.md(HOLD → ISSUED)
📝 Notes
- HOLD booking has payment deadline (~4 hours)
- Can add services/seats before payment
- Names must be UPPERCASE
- Date format:
DD-MM-YYYY - Passenger index: 1-based
- Fare index: 0-based
- Save
ve_id,pnr,hanh_khach_id,key_chang_bayfor later use