API
Booking Flow
Simple Booking Flow
Detailed Booking Flow
Click to show detailed booking flow

Testcases
Base Url
Main url (booking info, seatmap, pay, cancel, refund, etc.)
- Test environment (UAT): https://uat-api.vexere.net
- Production environment (PRO): https://api.vexere.com
Route url (search trip)
Note: api version /v2
* Test environment (UAT): https://uat-vroute.vexere.net
* Production environment (PRO): https://vroute.vexere.com
User profile url (company reviews, etc.)
- Test environment (UAT): https://uat-user-profile-service.vexere.net
- Production environment (PRO): https://user-profile-service.vexere.com
Account service url (authentication, etc.)
- Test environment (UAT): https://uat-account-service.vexere.net
- Production environment (PRO): https://account-service.vexere.com
Authentication
Authentication information request
curl -X POST \
{{account_service_url}}/v3/token
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=63950932-a8a3-40b6-bf17-b49d29d7789f' \
--data-urlencode 'client_secret=50dcca4f-1caf-45fa-be52-834ba11b31cb'
var request = require("request");
var options = {
method: 'POST',
url: '{{account_service_url}}/v3/token',
headers: {
'Postman-Token': '51038326-8fb5-4475-8ca3-586427efae3a',
'cache-control': 'no-cache'
},
form: {
grant_type: 'client_credentials',
client_id: '63950932-a8a3-40b6-bf17-b49d29d7789f',
client_secret: '50dcca4f-1caf-45fa-be52-834ba11b31cb'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
API Get token for serving access to other APIs. The validity period of the Token is 01 hour. After this time, another token is required.
Body Parameter
Parameter | Type | Required | Description |
---|---|---|---|
grant_type | String | True | Grant type. Available values: client_credentials |
client_id | String | True | Client Id. Available values: 63950932-a8a3-40b6-bf17-b49d29d7789f |
client_secret | String | True | Client secret. Available values: 50dcca4f-1caf-45fa-be52-834ba11b31cb |
Area
Getting the list of cities
curl -X GET \
{{main_url}}/v3/area/city \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 7d334dc5-5965-4d8a-a3ca-384155e98bb1' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/area/city',
headers: {
'Postman-Token': 'f97cabaa-6e36-42d4-aefb-3248fd7d3b4e',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"cities": [
{
"id": "1",
"code": "AGG",
"name": "An Giang"
}
]
}
}
Request
- This API has no parameter.
Response
Definitions | Type | Description |
---|---|---|
id | Integer | City Id |
code | String | City Code |
name | String | City Name |
Getting the list of districts
curl -X GET \
'{{main_url}}/v3/area/district?city_id=1' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: c9db45b7-04d6-42b7-847c-b81f5efebf76' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/area/district',
qs: {
city_id: '1'
},
headers: {
'Postman-Token': 'b1508fae-02a7-4323-9af5-db4736a0ad41',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"districts": [
{
"id": "64",
"code": "",
"name": "An Phú",
"city_id": "1",
"url_id": "1"
}
]
}
}
Request
- Query parameter
Parameter | Type | Required | Description |
---|---|---|---|
city_id | Integer | True | Id of the city |
Response
Definitions | Type | Description |
---|---|---|
id | Integer | District Id |
code | String | District Code |
name | String | District Name |
city_id | String | Id of province / city |
url_id | Integer | Id in url |
Getting list of cities and districts
curl -X GET \
{{main_url}}/v3/area/city_district \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 693ca100-8b05-497c-95a4-c38e10f6eb59' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/area/city_district',
headers: {
'Postman-Token': 'b7dbce91-2c6f-4fc3-b21b-8bbb53361bae',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": [
{
"id": "27",
"name": "Hải Phòng",
"code": "HPG",
"type": 3,
"url_id": "27",
"base_id": "1926"
}
]
}
Request
- This API has no parameter
Response
Definitions | Type | Description |
---|---|---|
id | Integer | Id of city / district |
code | String | City / district code |
name | String | City / District Name |
type | Integer | Type (3 = Province / City under Central Government, 5 = County / District / Town / City directly under the province) |
url_id | Integer | Id in url |
base_id | Integer | Id of administrative unit |
Route
Get the list of trips
curl -X GET \
'{{route_url}}/v2/route?filter[from]=29&filter[to]=417&filter[date]=2020-05-07&filter[online_ticket]=1&filter[is_promotion]=0&filter[fare][min]=0&filter[fare][max]=1000000&filter[available_seat][min]=0&filter[available_seat][max]=100&filter[rating][min]=4&filter[rating][max]=5&filter[time][min]=00:00&filter[time][max]=09:00&filter[limousine]=0&filter[seat_type][0]=2&page=1&pagesize=20' \
-H 'Accept-Language: en-US' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 4b04b2ac-5b55-4d23-8ad5-e475acb69272' \
-H 'cache-control: no-cache'
var request = require('request');
var options = {
'method': 'GET',
'url': '{{route_url}}/v2/route?filter[from]=29&filter[to]=417&filter[date]=2020-05-07&filter[online_ticket]=1&filter[is_promotion]=0&filter[fare][min]=0&filter[fare][max]=1000000&filter[available_seat][min]=0&filter[available_seat][max]=100&filter[rating][min]=4&filter[rating][max]=5&filter[time][min]=00:00&filter[time][max]=09:00&filter[limousine]=0&filter[seat_type][0]=2&page=1&pagesize=20',
'headers': {
'Authorization': 'Bearer {{access_token}}'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
The above command returns JSON structured like this:
{
"message": "success",
"data": [
{
"route": {
"id": 2727083,
"name": "Bình Dương - Sài Gòn - Quảng Ngãi",
"departure_date": "2020-05-07T00:00:00+07:00",
"departure_time": "00:00",
"vehicle_quality": 1,
"from": {
"id": 155749,
"name": "Bến xe Miền Đông (Cổng 1)",
"address": "292 Đinh Bộ Lĩnh",
"longitude": 106.71085349999998,
"latitude": 10.8148737
},
"to": {
"id": 153010,
"name": "Ngã 3 nhà máy sợi Nha Trang",
"address": "AH1, Vĩnh Phương, Thành phố Nha Trang, Khánh Hòa, Việt Nam",
"longitude": 106.71085349999998,
"latitude": 10.8148737
},
"duration": 510,
"full_trip": false,
"schedules": [
{
"trip_code": "v2COXACRCyqwkaAjAwIgIwMDCruaYBOgowNy0wNS0yMDIwSB1QoQM",
"hour": "01",
"minute": "00",
"pickup_date": "2020-05-07T01:00+07:00",
"arrival_time": "2020-05-07T09:30+07:00",
"fare": {
"original": 200000,
"discount": -1,
"max": 270000
},
"deposit_selling": 0,
"config": "ONLINE",
"seat_type": 2,
"available_seats": 21,
"vehicle_quality": 1,
"total_seats": 46,
"vehicle_type": "Giường nằm 46 chỗ",
"refundable": 1,
"unchoosable": 0,
"seat_template_id": 123,
}
]
},
"company": {
"id": 29228,
"name": "Thanh Thủy",
"images": [
{
"files": {
"1000x600": "//static.vexere.com/c/i/29228/xe-thanh-thuy---quang-ngai-VeXeRe-27BUwJo-1000x600.jpeg"
}
}
],
"ratings": {
"overall": 4.4,
"comments": 5
},
},
"available_seat_info": {
"seat_type": {
"3": {
"total_available_seat": 19,
"fare": [
225000,
405000
]
}
},
"seat_group": {
"Giường đơn": {
"total_available_seat": 9,
"fare": [
225000
]
},
"Giường đôi": {
"total_available_seat": 10,
"fare": [
405000
]
}
}
},
"max_total_seats": 6,
"status": 2
}
],
"page": "1",
"page_size": "20",
"total": 1,
"total_pages": 1,
"area": {
"from": {
"id": "29",
"name": "Hồ Chí Minh",
"code": "HCM",
"type": 3,
"id_url": 29,
"city": {},
"state": {
"id": "29",
"name": "Hồ Chí Minh"
}
},
"to": {
"id": "417",
"name": "Nha Trang",
"code": "NT",
"address": "",
"type": 5,
"id_url": "359",
"city": {
"id": "417",
"name": "Nha Trang"
},
"state": {
"id": "32",
"name": "Khánh Hòa"
}
}
},
"companies": []
}
Parameter
Parameter | Type | Required | Description |
---|---|---|---|
page | Integer | true | Current page |
pagesize | Integer | true | Maximum number of elements in the page. Note: current max pagesize is 20, the value will be reset to 20 if its greater than 20 |
sort | String | false | Sort condition. By format field:order. Order has 2 values for "asc" and "desc". Field has 3 values for "time", "fare", "rating" |
filter | Object | true | Filter information |
filter.from | Integer | true | Id points away |
filter.to | Integer | true | Destination id |
filter.date | String | true | Date of departure by format ("YYYY-MM-DD") |
filter.online_ticket | Integer | true | Filter by online trips. Allow 2 values: 0, 1 |
filter.online_reserved | Integer | false | Filter by pre-select seat position in the seatmap. Allow 2 values: 0, 1 |
filter.fare | Object | false | Fare |
filter.fare.min | Integer | false | Lowest ticket conditions. Default 0 |
filter.fare.max | Integer | false | The highest ticket price condition |
filter.available_seat | Object | false | Filter by empty seats. |
filter.available_seat.min | Integer | false | Minimum available empty seats. |
filter.available_seat.max | Integer | false | Maximum available empty seats. |
filter.limousine | Integer | false | Car vip. Allow 2 values: 0, 1 |
filter.companies[index] | Array | false | Filter by bus operator id |
filter.rating.min | Integer | false | Lowest rating condition. Default 1 |
filter.rating.max | Integer | false | Highest rating condition. Default 5 |
filter.time.min | String | false | From time. Format: HH:mm |
filter.time.max | String | false | To time. Format: HH:mm |
filter.is_promotion | Integer | false | Check out the promotion trip. Allow 2 values: 0,1 |
filter.seat_type.[index] | Integer | false | Get the trip with the seat type (1 - Ghế ngồi - AC Seater, 2 - Giường nằm - AC Sleeper, 7 - Giường nằm đôi - AC Double Sleeper) |
filter.covid_utility | Integer | false | Covid-19 safety guaranty. Allow 2 values: 0, 1. Default 0. |
filter.enabled_gps | Integer | false | Bus location tracking. Allow 2 values: 0, 1. Default 0. |
filter.full_trip | Integer | false | Full trip only (no leg search) or not. Allow 2 values: 0, 1. Default 0. |
filter[pickup_points][index][district] | String | false | Name of pickup district filter. |
filter[pickup_points][0][name] | String | false | Name of pickup filter. |
filter[dropoff_points][index][district] | String | false | Name of dropoff district filter. |
filter[dropoff_points][0][name] | String | false | Name of dropoff filter. |
How to add filter pickup_points and dropoff_points ?
Response
Definitions | Type | Description |
---|---|---|
data[index].route | Object | Trip information |
data[index].route.id | Integer | Trip Id |
data[index].route.name | String | Trip name |
data[index].route.departure_date | String | Departure date |
data[index].route.departure_time | String | Departure time: Please DO NOT use this field in product list / route list item, use schedules.pickup_date instead |
data[index].route.vehicle_quality | Integer | Vehicle type (1-Normal bus, 2-VIP bus) |
data[index].route.from | Object | Departure place |
data[index].route.from.id | Integer | Departure place id |
data[index].route.from.name | String | Departure place name |
data[index].route.from.longitude | String | Longitude |
data[index].route.to | Object | Arrival place |
data[index].route.to.id | Integer | Arrival place id |
data[index].route.to.name | String | Arrival place name |
data[index].route.to.latitude | String | Latitude |
data[index].route.duration | Integer | Journey time |
data[index].route.full_trip | Boolean | Is full trip ? (true - false) |
data[index].route.schedules | Array | Departure times |
data[index].route.schedules[index].trip_code | String | Trip code |
data[index].route.schedules[index].hour | Integer | Pickup hour |
data[index].route.schedules[index].minute | Integer | Pickup minute |
data[index].route.schedules[index].pickup_date | String | Pickup date: Please use this field for showing time in product list / route list |
data[index].route.schedules[index].arrival_time | String | Arrival time |
data[index].route.schedules[index].fare | Object | Fare information |
data[index].route.schedules[index].fare.original | Integer | Original fare |
data[index].route.schedules[index].fare.discount | Integer | Discounted price (Price after discount) |
data[index].route.schedules[index].fare.max | Integer | Max fare |
data[index].route.schedules[index].seat_type | Integer | Seat type |
data[index].route.schedules[index].available_seats | Integer | Available seat count |
data[index].route.schedules[index].total_seats | Integer | Total seats |
data[index].route.schedules[index].vehicle_type | String | Vehicle type |
data[index].route.schedules[index].refundable | Integer | Refundable status. Note: This value may be cached and could change during booking. For the final refund eligibility, please check the v3/booking/refund using the booking code AND v3/cancellation/policy |
data[index].route.schedules[index].unchoosable | Integer | Does the bus operator rearrange the seat when getting out? |
data[index].route.schedules[index].seat_template_id | Integer | Use this id to get bus amentity & bus policy |
data[index].company | Object | Bus operator information |
data[index].company.id | Integer | Bus operator id |
data[index].company.name | String | Bus operator name |
data[index].company.images | Array | Bus operator image |
data[index].company.ratings | Object | Bus operator rating |
data[index].company.ratings.overall | Float | Average rating |
data[index].company.ratings.comments | Integer | Total comments |
data[index].available_seat_info.seat_type | Object | Seat statistics by seat_type. Key is code of seat type and value contains total available seat and list of available prices |
data[index].available_seat_info.seat_group | Object | Seat statistics by seat_group. Key is code of seat group and value contains total available seat and list of available prices |
data[index].max_total_seats | Integer | Limited seats / ticket |
data[index].status | Integer | Trip type (2 - Online) |
data[index].notification | Object | Bus operator notification |
data[index].notification.category | Integer | Announcement / promotion group (1-Notice, 2-Discount, 3-Promotion) |
data[index].notification.label | String | Notice title |
data[index].notification.english_label | String | Notice title (English) |
data[index].notification.content | String | Notice content |
data[index].notification.english_content | String | Notice content |
data[index].important_notification | Object | Policy notification |
data[index].important_notification.category | Integer | Announcement / promotion group (4-Policy) |
data[index].important_notification.label | String | Notice title |
data[index].important_notification.english_label | String | Notice title (English) |
data[index].important_notification.content | String | Notice content |
data[index].important_notification.english_content | String | Notice content |
page | Integer | Current page |
page_size | Integer | Maximum number of elements in the page |
total | Integer | Total number of elements |
total_pages | Integer | Total pages |
area | Object | Location information |
area.from | Object | Departure place |
area.from.id | Integer | Departure place id |
area.from.name | String | Departure place name |
area.from.code | String | Departure place code |
area.from.id_url | Integer | Id information on url |
area.from.city | Object | In the city |
area.from.city.id | Integer | City id |
area.from.city.name | String | City name |
area.from.state | Object | In the state |
area.from.state.id | Integer | State id |
area.from.state.name | String | State name |
area.to | Object | Arrival place (like area.from) |
Get the number of trips
curl --location --request GET '{{route_url}}/v2/route/filter_statistic?filter[from]=29&filter[to]=21&filter[date]=2020-03-01&filter[online_ticket]=1' \
--header 'Authorization: Bearer {{access_token}}'
var request = require('request');
var options = {
'method': 'GET',
'url': '{{route_url}}/v2/route/filter_statistic?filter[from]=29&filter[to]=21&filter[date]=2020-03-01&filter[online_ticket]=1',
'headers': {
'Authorization': 'Bearer {{access_token}}'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
The above command returns JSON structured like this:
{
"message": "success",
"data": {
"total": 60,
"rating": {
"detail": [
{
"value": 3,
"count": 36
}
]
},
"template_seats": [
{
"type_number": 2,
"type": "Giường nằm",
"number": 60
}
],
"total_available_trips": 60,
"is_promotion": 1,
"vehicle_types": [
{
"value": "NORMAL",
"count": 35
},
],
"companies": {
"total": 14,
"data": [
{
"id": 28895,
"name": "An Phát",
"display_name": null,
"trip_count": 8
}
]
},
"online_ticket": 60,
"pickup_points": [
{
"district": "Bình Thạnh",
"trip_count": 147,
"points": [
{
"name": "Bến Xe Miền Đông - Quầy vé 49",
"trip_count": 15
}
]
}
],
"dropoff_points": [
{
"district": "Pleiku",
"trip_count": 26,
"points": [
{
"name": "Bến xe Đức Long Gia Lai",
"trip_count": 15
}
]
},
]
}
}
The parameters as API above
Response
Definitions | Type | Description |
---|---|---|
data.total | Integer | Total number of elements |
data.rating | Object | Bus operator rating |
data.rating.detail | Array | Bus operator rating detail |
data.rating.detail[index].value | Integer | Rating number |
data.rating.detail[index].count | Integer | Total rating |
data.template_seats | Array | Template seat info |
data.template_seats[index].type_number | Integer | Seat type |
data.template_seats[index].type | String | Name of seat type |
data.template_seats[index].number | Integer | Total number of seat type |
data.total_available_trips | Integer | Total number of available trips |
data.is_promotion | Integer | Total number of promotion trips |
data.vehicle_types | Array | Vehicle types in route |
data.vehicle_types[index].value | String | Type of vehicle |
data.vehicle_types[index].count | Integer | Total number of vehicle type |
data.companies | Object | Total bus operator in route |
data.companies.total | Integer | Total number of bus operator in route |
data.companies.data | Array | Bus operator info |
data.companies.data[index].id | Integer | Bus operator id |
data.companies.data[index].name | String | Bus operator name |
data.companies.data[index].display_name | String | Bus operator display name |
data.companies.data[index].trip_count | Integer | Total bus operator's trip |
data.online_ticket | Integer | Total number of trip can booking online |
data.pickup_points | Array | All pickup point in route |
data.pickup_points[index].district | String | Name of district |
data.pickup_points[index].trip_count | Integer | Total trips can pickup in district |
data.pickup_points[index].points | Array | All pickup point in route |
data.pickup_points[index].points[index].name | String | Name of pickup point |
data.pickup_points[index].points[index].trip_count | Integer | Total trips can pickup in this pickup point |
data.dropoff_points | Array | All dropoff point in route |
data.dropoff_points[index].district | String | Name of district |
data.dropoff_points[index].trip_count | Integer | Total trips can dropoff in district |
data.dropoff_points[index].points | Array | All dropoff point in route |
data.dropoff_points[index].points[index].name | String | Name of dropoff point |
data.dropoff_points[index].points[index].trip_count | Integer | Total trips can dropoff in this dropoff point |
Bus Amenity
Get the bus amenity
curl --location --request GET '{{main_url}}/v3/company/30353/utility?seat_template_id=6116' \
--header 'Authorization: Bearer {{access_token}}'
var request = require('request');
var options = {
'method': 'GET',
'url': '{{main_url}}/v3/company/30353/utility?seat_template_id=6116',
'headers': {
'Authorization': 'Bearer {{access_token}}'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": [
{
"icon_url": "static.vexere.net/uat/utilities/1585109859861.png",
"name": "An toàn mùa Covid-19",
"english_name": "Personal Protective Equipment For Covid-19",
"description": "Là chương trình bảo vệ an toàn cho hành khách sử dụng dịch vụ của VeXeRe trong mùa dịch Covid. VeXeRe đồng hành các nhà xe đối tác triển khai biện pháp bảo vệ an toàn cho hành khách, như sau: (1) - Kiểm tra thân nhiệt hành khách trước khi lên xe; (2) - Trang bị nước rửa tay; (3) - Có đảm bảo khuyến cáo tất cả hành khách đeo khẩu trang khi lên xe; (4) - Có thực hiện khử trùng xe",
"english_description": "\"This is a Safety Protection Service for customer on Covid-1 :\nVeXeRe will accompany with Bus Companies to deploy the best measures with the best possible safety protection: \n(1) - Check temperature measurement before boarding the bus \n(2) - Always equipped hand sanitizier \n(3) - Recommend Wearing Face Mask\n(4) - Disinfecting Bus\"",
},
]
}
Request
- Query parameter
Parameter | Type | Required | Description |
---|---|---|---|
seat_template_id | Integer | True | Seat template id of trip |
Response
Definitions | Type | Description |
---|---|---|
data[index].icon_url | String | Url of VeXeRe's icon for each amenity |
data[index].name | String | Name of amenity |
data[index].english_name | String | English name of amenity |
data[index].description | String | Description of amenity |
data[index].english_description | String | Amenity english description |
Trip
Get seat map
curl -X GET \
'{{main_url}}/v3/trip/seat_map?trip_code=v2CPQNEL6oBBoCMDciAjAwMMG4vAE6CjI2LTA5LTIwMTlIGFAm' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 99a7cfdf-7ba5-451f-8874-d1dd8a136580' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/trip/seat_map',
qs: {
trip_code: 'v2CPQNEL6oBBoCMDciAjAwMMG4vAE6CjI2LTA5LTIwMTlIGFAm'
},
headers: {
'Postman-Token': 'cfcab9bd-31cd-47f4-bcce-40a3082f6065',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"departure_time": "07:00 26-09-2019",
"name": "Limousine 21 Cabin VIP",
"max_total_seats": 6,
"is_hide_pickup_version_english": 1,
"type": 1,
"fare": 400000,
"eating_fare": 0,
"is_eat_commission": 0,
"eating_note": "",
"total_seats": "27",
"total_available_seats": 20,
"num_coaches": 2,
"from_area": "1780|16|7PVD|VP 7 Phạm Văn Đồng",
"to_area": "70718|16|SPA|VP Sapa",
"company_id": "80" or 80, -- int or string
"total_stage": 3,
"pickup_at_departure": 1,
"pickup_points": [
{
"id": 0,
"point_id": 1780,
"name": "VP 7 Phạm Văn Đồng",
"english_name": "7 Pham Van Dong Office",
"english_address": "7 Pham Van Dong Street",
"address": "Số 7 Phạm Văn Đồng",
"index": 0,
"near_by": "",
"is_vxr_display": true,
"time": 0,
"real_time": "07:00 26-09-2019",
"note": "",
"surcharge": 0,
"surcharge_description": "Operator",
"surcharge_type": 1,
"english_note": null,
"unfixed_point": 0,
"min_customer": null
}
],
"pickup_enable": 0,
"pickup_min_customers": 0,
"pickup_list_detail": {
"is_hide_version_english": true
},
"transfer_enable": 1,
"transfer_points": [],
"transfer_min_customers": 0,
"transfer_list_detail": {},
"drop_off_at_arrive_enable": 1,
"drop_off_points_at_arrive": [
{
"id": 0,
"point_id": 70718,
"name": "VP Sapa",
"english_name": "Sapa Office",
"english_address": "No 571 Dien Bien Phu Street",
"address": "Số 571 Điện Biên Phủ",
"index": 0,
"near_by": "",
"is_vxr_display": true,
"time": 370,
"real_time": "13:10 26-09-2019",
"note": "",
"surcharge": 0,
"surcharge_description": "Operator",
"surcharge_type": 1,
"english_note": null,
"unfixed_point": 0,
"min_customer": null
}
],
"drop_off_at_arrive_list_detail": {
"is_hide_version_english": true
},
"transfer_at_arrive_enable": 1,
"transfer_points_at_arrive": [
{
"id": 26879,
"point_id": 148519,
"name": "Thị trấn Sapa",
"english_name": "Sapa Town",
"english_address": "Sapa Town",
"address": "Thị trấn Sapa",
"index": 0,
"near_by": "",
"is_vxr_display": true,
"time": 370,
"real_time": "13:10 26-09-2019",
"note": "",
"surcharge": 0,
"surcharge_description": "Operator",
"surcharge_type": 1,
"english_note": "",
"unfixed_point": 1,
"min_customer": 0
}
],
"transfer_at_arrive_note": "Trả quanh thị trấn Sapa",
"transfer_at_arrive_required": 0,
"transfer_at_arrive_min_customers": 0,
"transfer_at_arrive_list_detail": {
"transfer_required": false,
"note": "Trả quanh thị trấn Sapa",
"type": 2,
"min_customer": 0,
"name": "trung chuyển trả tại sapa",
"hidden": 0,
"hidden_bms": 0,
"status": 1,
"pickup_time_for_print": 0,
"transfer_time_for_print": 0,
"phone_numbers": ""
},
"search_from": 24,
"search_to": 38,
"deposit_selling": 0,
"coach_seat_template": [
{
"coach_num": 1,
"coach_name": "Tầng 1",
"num_rows": 6,
"num_cols": 2,
"seats": [
{
"seat_type": 2,
"seat_code": "A1",
"row_num": 2,
"col_num": 1,
"full_code": "A1|1|2|1",
"row_span": 1,
"col_span": 1,
"seat_group": "CABIN ĐÔI",
"seat_group_english": "DOUBLE",
"is_available": true,
"is_locked_seat": false,
"fare": 650000,
"seat_color": "#0E7F3D",
"fares": {
"original": 700000,
"operator_discount": 50000,
"vexere_discount": 0
}
},
{
"seat_type": 7,
"seat_number": 0,
"seat_code": "1",
"row_num": 1,
"col_num": 1,
"full_code": "1|1|1|1",
"row_span": 1,
"col_span": 1,
"is_available": true,
"seat_group_code": "DOI",
"seat_group_id": 5955,
"seat_group": "Giường đôi 2 người nằm",
"seat_group_english": "couple for 2",
"fare": 600000,
"seat_color": "#FF1F1F",
"fares": {
"original": 600000,
"operator_discount": 0,
"vexere_discount": 0
},
"seat_groups": [
{
"seat_group_code": "DOI2",
"seat_group_id": 5957,
"seat_group": "Giường đôi 1 người nằm",
"seat_group_english": "couple for 1",
"fare": 400000,
"seat_color": "#ffe635",
"fares": {
"original": 400000,
"operator_discount": 0,
"vexere_discount": 0
}
},
{
"seat_group_code": "DOI",
"seat_group_id": 5955,
"seat_group": "Giường đôi 2 người nằm",
"seat_group_english": "couple for 2",
"fare": 600000,
"seat_color": "#FF1F1F",
"fares": {
"original": 600000,
"operator_discount": 0,
"vexere_discount": 0
}
}
]
}
]
}
],
"vehicle": {
"seat_type": 2,
"quality": 2,
"number": "",
"phone": "",
"driver": "",
"assistant": ""
},
"trip_note": "",
"trip_note_modified": "",
"trip_description": "6:00TND-6:10TKC-6:30GP",
"trip_drivers": {},
"config_note": "",
"receive_ticket_time": null,
"using_eticket": true,
"is_full_trip": true,
"must_call_before_booking": 0,
"is_cooperate": 1,
"is_difficult": 0,
"discount_info": {
"id": "27046",
"name": "Tri ân khách hàng",
"apply": "operator"
}
}
}
Request
- Query parameter
Parameter | Type | Required | Description |
---|---|---|---|
trip_code | String | True | Trip code |
Response
Definitions | Type | Description |
---|---|---|
departure_time | string | departure time |
name | string | Name of seat diagram |
max_total_seats | integer | Maximum number of seats per booking |
fare | integer | Fare |
eating_fare | integer | Eating fare (per seat) |
service_fee | integer | Service fee per booking(Just show for Bus Operator is Phuong Trang - bus_id = 11071) |
total_seats | integer | Total number of seats |
total_available_seats | integer | Total number of empty seats |
num_coaches | integer | Total number of floors |
company_id | integer | Bus operators id |
pickup_points | Array | Pick up list |
pickup_points[index].id | Integer | Id pick up points |
pickup_points[index].point_id | integer | Pick up detail id |
pickup_points[index].name | string | Pickup point name |
pickup_points[index].address | string | Pickup point address |
pickup_points[index].time | integer | Time to pick up in minutes |
pickup_points[index].real_time | string | Real time to pick up point |
pickup_points[index].unfixed_point | integer | Pick up point is fixed or not fixed (1-Not fixed, 0-Fixed)
|
pickup_points[index].surcharge | integer | Pick up surcharge (per seat) |
pickup_points[index].surcharge_type | integer | Type of surcharge (1-The garage will be collected later, 2-Collected directly from the guest) |
pickup_points[index].min_customer | integer | Minimum number of customer to choose a pick-up point |
transfer_points | Array | Similar pickup_points |
drop_off_points_at_arrive | Array | Similar pickup_points |
transfer_points_at_arrive | Array | Similar pickup_points |
coach_seat_template | Array | List of floors |
coach_seat_template[index].coach_num | integer | Coach num |
coach_seat_template[index].coach_name | string | Coach name |
coach_seat_template[index].num_rows | integer | Number of rows |
coach_seat_template[index].num_cols | integer | Number of columns |
coach_seat_template[index].seats | Array | List of floor chairs |
coach_seat_template[index].seats[index_2].seat_type | integer | Seat type |
coach_seat_template[index].seats[index_2].seat_code | string | Seat code |
coach_seat_template[index].seats[index_2].fare | integer | Fare |
coach_seat_template[index].seats[index_2].row_num | integer | Row |
coach_seat_template[index].seats[index_2].col_num | integer | Column |
coach_seat_template[index].seats[index_2].full_code | string | Full code |
coach_seat_template[index].seats[index_2].row_span | integer | Width in rows |
coach_seat_template[index].seats[index_2].col_span | integer | Column width |
coach_seat_template[index].seats[index_2].seat_group | string | Name of seat group |
coach_seat_template[index].seats[index_2].seat_groups | array | If this seat has multiple fare options, there will be this field (See how to handle seats have multiple fare options here) |
coach_seat_template[index].seats[index_2].is_availlable | integer | Still empty (1-Empty, 0-No longer available) |
vehicle | object | vehicle information |
vehicle.seat_type | integer | seat type (1 - Ghế ngồi - AC Seater, 2 - Giường nằm - AC Sleeper, 3 - Ghế nằm - AC Reclining Seater, 7 - Giường nằm đôi - AC Double) |
vehicle.number | string | plates |
vehicle.driver | string | name of drive |
vehicle.assistant | string | name of assistant |
Get bus operator policy
curl -X GET \
'{{main_url}}/v3/company_policy/config_detail?seat_template_id=5206&trip_code=v2CJWfCBCUnwgaAjIxIgIwMDCBuXw6CjA1LTA4LTIwMjFIoQNQHagBl7IB' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'cache-control: no-cache'
var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer {{access_token}}");
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch("{{main_url}}/v3/company_policy/config_detail?seat_template_id=5206&trip_code=v2CJWfCBCUnwgaAjIxIgIwMDCBuXw6CjA1LTA4LTIwMjFIoQNQHagBl7IB",
requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
The above command returns JSON structured like this:
{
"message": "Success",
"data": [
{
"id": "1",
"name": "An toàn Covid-19",
"english_name": "Covid-19 Alert",
"details": [
{
"id": "1",
"title": "Tạm ngưng phục vụ khách nước ngoài do diễn biến phức tạp của dịch Covid-19",
"english_title": "Temporarily stop serving foreign passengers due to the complex developments of the Covid-19 pandemic",
"content": null,
"english_content": null
},
{
"id": "2",
"title": "Xuất trình Khai báo Y tế trước khi lên xe",
"english_title": "Show health declaration before boarding trip",
"content": null,
"english_content": null
},
{
"id": "3",
"title": "Cung cấp đầy đủ họ tên, số điện thoại, địa chỉ cư trú khi đặt vé",
"english_title": "Provide full name, phone number, residence address when booking ticket",
"content": null,
"english_content": null
}
]
},
{
"id": "2",
"name": "Yêu cầu khi lên xe",
"english_name": "Onboarding",
"details": [
{
"id": "5",
"title": "Có mặt tại văn phòng/ quầy vé/ bến xe trước 30 phút để làm thủ tục lên xe",
"english_title": "Show up 30 minutes at the office / ticket counter / bus station before for check in",
"content": null,
"english_content": null
},
{
"id": "6",
"title": "Đổi vé giấy trước khi lên xe",
"english_title": "Redeem paper tickets before boarding",
"content": null,
"english_content": null
},
{
"id": "7",
"title": "Xuất trình SMS/ Email đặt vé trước khi lên xe",
"english_title": "Show off SMS / Email before boarding",
"content": null,
"english_content": null
},
{
"id": "8",
"title": "Không mang đồ ăn, thức ăn có mùi lên xe",
"english_title": "Do not bring food, smelly food to the bus",
"content": null,
"english_content": null
},
{
"id": "9",
"title": "Không hút thuốc, uống rượu, sử dụng chất kích thích trên xe",
"english_title": "Do not smoke, drink alcohol or use drugs on the bus",
"content": null,
"english_content": null
},
{
"id": "10",
"title": "Không mang các vật dễ cháy nổ lên xe",
"english_title": "Do not bring flammable objects to the vehicle",
"content": null,
"english_content": null
},
{
"id": "11",
"title": "Không vứt rác trên xe",
"english_title": "Do not litter in the bus",
"content": null,
"english_content": null
},
{
"id": "12",
"title": "Không làm ồn, gây mất trật tự trên xe",
"english_title": "Do not make noise in the bus",
"content": null,
"english_content": null
},
{
"id": "13",
"title": "Không mang giày, dép trên xe",
"english_title": "Take off shoes or sandals before boarding",
"content": null,
"english_content": null
}
]
},
{
"id": "3",
"name": "Hành lý xách tay",
"english_name": "Hand Baggage",
"details": [
{
"id": "14",
"title": "Tổng trọng lượng hành lý không vượt quá 10 kg",
"english_title": "The total weight of hand baggage item(s) must not exceed 10 kgs",
"content": null,
"english_content": null
},
{
"id": "15",
"title": "Phụ phí hành lý vượt quá quy định: 20000 VND/kg",
"english_title": "Surcharge for each kilogram exceeding the above standard: 20000 VND/kg",
"content": null,
"english_content": null
},
{
"id": "16",
"title": "Không vận chuyển hàng hóa cồng kềnh",
"english_title": "Refuse to transport overload/overweight goods",
"content": null,
"english_content": null
},
{
"id": "17",
"title": "Không hoàn tiền trong trường hợp hủy vé do vi phạm các quy định về hành lý",
"english_title": "No refund in case of cancellation due to violation of baggage regulations",
"content": null,
"english_content": null
}
]
},
{
"id": "4",
"name": "Trẻ em và Phụ nữ có thai",
"english_name": "Children & Pregnant Passengers",
"details": [
{
"id": "18",
"title": "Trẻ em dưới 6 tuổi hoặc dưới 100 cm được miễn phí vé nếu ngồi cùng ghế/ giường với bố mẹ",
"english_title": "Children under the age of 6 or under 100 cm are allowed to share seat / bed with their parents",
"content": null,
"english_content": null
},
{
"id": "19",
"title": "Trẻ em từ 7 tuổi hoặc cao từ 130 cm trở lên mua vé như người lớn",
"english_title": "Children from the age of 7 or from 130 cm have to buy ticket as adult",
"content": null,
"english_content": null
},
{
"id": "20",
"title": "Phụ nữ có thai cần đảm bảo sức khỏe trong suốt quá trình di chuyển",
"english_title": "Pregnant women need to ensure health during the trip",
"content": null,
"english_content": null
},
{
"id": "21",
"title": "Nhà xe có quyền từ chối phục vụ nếu hành khách không tuân thủ quy định về trẻ em và phụ nữ có thai",
"english_title": "The operator has the right to cancel tickets if passengers do not comply with the regulations on children and pregnant women",
"content": null,
"english_content": null
}
]
},
{
"id": "5",
"name": "Động vật cảnh/ Thú cưng",
"english_name": "Animals/ Pets",
"details": [
{
"id": "22",
"title": "Hành khách có động vật đi cùng vui lòng báo trước khi khởi hành và có mặt trước giờ khởi hành ít nhất 120 phút",
"english_title": "Passengers with pets are kindly requested to inform before departure and present at least 120 minutes before departure",
"content": null,
"english_content": null
},
{
"id": "23",
"title": "Động vật cảnh phải đảm bảo có sức khỏe tốt, thân thiện với con người, đã được tiêm phòng đầy đủ, không có mùi khó chịu, không gây ảnh hưởng đến hành khách và tài sản của họ",
"english_title": "Pets must be in good health, free of diseases communicable to humans, and must be properly vaccinated, should not have offensive smell or odor, and should not be predisposed to cause harm to other animals, people, or luggage.",
"content": null,
"english_content": null
},
{
"id": "24",
"title": "Thú cưng cần phải được đeo rọ mõm, nhốt trong lồng, túi, balo phi hành gia để đảm bảo cho việc vận chuyển an toàn, phòng tráng việc thú cưng chạy ra ngoài",
"english_title": "Pets need to be put on muzzle, cage, bag or backpack to ensure safe transportation, preventing pet from running out",
"content": null,
"english_content": null
},
{
"id": "25",
"title": "Hãng xe chỉ chấp nhận vận chuyển động vật như là một hành lý ký gửi; không cho phép mang lên xe cùng hành khách",
"english_title": "The carrier only accept to transport animals as a checked baggage; not allow to bring to the bus with the passengers",
"content": null,
"english_content": null
},
{
"id": "26",
"title": "Nhiệt độ thời tiết trong quá trình vận chuyển đôi khi ảnh hưởng đến sức khỏe của động vật cảnh, nhà xe không chịu trách nhiệm về sức khỏe động vật trong suốt chuyến đi",
"english_title": "Weather during transport sometimes affects the health of pets, the operator is not responsible for animal health during the trip",
"content": null,
"english_content": null
}
]
},
{
"id": "6",
"name": "Xuất hóa đơn GTGT",
"english_name": "VAT Invoice",
"details": [
{
"id": "27",
"title": "Nhà xe có cung cấp hóa đơn GTGT cho vé, phí xuất hóa đơn là 2 % trên giá vé quý khách đã mua",
"english_title": "The operator provides VAT invoice for the ticket, invoice fee is 2% of the ticket fare",
"content": null,
"english_content": null
},
{
"id": "28",
"title": "Quý khách vui lòng cung cấp đầy đủ, chính xác thông tin hóa đơn",
"english_title": "Please provide accurate invoice information",
"content": null,
"english_content": null
},
{
"id": "29",
"title": "Nhà xe từ chối xuất lại hóa đơn nếu hành khách cung cấp sai thông tin",
"english_title": "The operator refuses to re-issue the invoice if the passenger provides the inaccurate information",
"content": null,
"english_content": null
}
]
},
{
"id": "7",
"name": "Gửi xe đạp/ xe máy",
"english_name": "Bicycle/ Motobike Freight",
"details": [
{
"id": "30",
"title": "Cước gửi xe",
"english_title": "Freight",
"content": "<table><tbody><tr><td> </td><td><h4>Cước gửi kèm khách hàng</h4>Freight if accompanied with passenger</td><td><h4>Cước không kèm khách hàng</h4>Freight if not accompanied with passenger</td></tr><tr><td><h4>Xe đạp</h4>Bicycle</td><td>100000</td><td>100000</td></tr><tr><td><h4>Số xe</h4>Underbone</td><td>200000</td><td>200000</td></tr><tr><td><h4>Xe tay ga/ tay côn</h4>Scooter</td><td>300000</td><td>300000</td></tr><tr><td><h4>Xe giá trị cao</h4>High value motobike</td><td>400000</td><td>400000</td></tr></tbody></table>",
"english_content": "<table><tbody><tr><td> </td><td><h4>Cước gửi kèm khách hàng</h4>Freight if accompanied with passenger</td><td><h4>Cước không kèm khách hàng</h4>Freight if not accompanied with passenger</td></tr><tr><td><h4>Xe đạp</h4>Bicycle</td><td>100000</td><td>100000</td></tr><tr><td><h4>Số xe</h4>Underbone</td><td>200000</td><td>200000</td></tr><tr><td><h4>Xe tay ga/ tay côn</h4>Scooter</td><td>300000</td><td>300000</td></tr><tr><td><h4>Xe giá trị cao</h4>High value motobike</td><td>400000</td><td>400000</td></tr></tbody></table>"
},
{
"id": "31",
"title": "Hành khách đặt vé được gửi miễn phí tại bãi gửi xe của bến xe/ nhà xe trong 2 ngày",
"english_title": "Passengers booking tickets are free to park at the bus station / garage for 2 days",
"content": null,
"english_content": null
}
]
}
]
}
Request
- Query parameter
Parameter | Type | Required | Description |
---|---|---|---|
trip_code | String | True | Trip code |
seat_template_id | String | True | Seat template id |
Get value of trip_code and seat_template_id from response data of list of trips
Response
Definitions | Type | Description |
---|---|---|
id | string | group policy id |
name | string | name group by Vietnamese |
english_name | string | name group by English |
details | array | policy details of group |
details[id] | string | id policy |
details[title] | string | policy title by Vietnamese |
details[english_title] | string | policy title by English |
details[content] | string | content of policy by Vietnamese |
details[english_content] | string | content of policy by English |
Notes
At group has id = 7
, the response content
of details
, which has id = 30
, is an html table describe by both English and Vietnamese. In this case no need english_content
, which is the same as content
.
Image of group id = 7 / details id = 30
Example show policy
Pickup / Transfer
Get the information of a pickup / transfer point
curl -X GET \
'{{main_url}}/v3/pickup_point?point_id=765' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: f57615ab-a087-436c-8ded-552646805674' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/pickup_point',
qs: {
point_id: '765'
},
headers: {
'Postman-Token': 'c90d7a65-8658-4242-8535-ccdf60540004',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": [
{
"point_id": "765",
"address": "292 Đinh Bộ Lĩnh, Phường 26, Bình Thạnh, Hồ Chí Minh",
"longitude": 106.71085349999998,
"latitude": 10.8148737,
"url": "https://goo.gl/Exw48Z",
"introduction": "<p><strong><a href=\"http://vexere.com/ben-xe-mien-dong\"><span style=\"color:#0000FF\">Bến xe Miền Đông</span></a></strong> là bến xe khách lớn nhất Đông Nam Á và Việt Nam về số lượng khách và lưu lượng xe đi lại mỗi năm.<span style=\"color:#0000FF\"> </span><a href=\"http://vexere.com/ben-xe-mien-dong/so-dien-thoai-dia-chi-ben-xe-mien-dong\"><span style=\"color:#0000FF\">Địa chỉ Bến xe miền Đông</span></a> hiện tại đang nằm ở đường Đinh Bộ Lĩnh, quận Bình Thạnh, Tp. Hồ Chí Minh. Dự kiến sau năm 2015, địa chỉ mới của bến xe sẽ ở khu vực Suối Tiên. Đây là bến xe đầu mối cho tất cả các chuyến xe khách từ Sài gòn đi các tỉnh miền Bắc, Trung và Tây Việt Nam.</p>\r\n\r\n<p> </p>\r\n\r\n<p>Qua hơn 30 năm hoạt động, Bến xe khách Miền Đông luôn đặt lợi ích phục vụ vận chuyển hành khách lên hàng đầu. Bến xe hiện là nơi lưu đậu các phương tiện vận tải hành khách cố định, tổ chức bán vé cho các hãng xe theo hợp đồng uỷ thác và tổ chức điều hành xe ra vào bến. Nhờ đó, việc đón trả khách, giờ xe xuất bến luôn được đảm bảo theo quy định.</p>\r\n\r\n<p> </p>\r\n\r\n<p>Ngoài ra, bến xe khách miền Đông vẫn luôn đặt công tác an ninh trật tự làm nhiệm vụ trọng tâm của Bến xe Miền Đông. Bến đã kết hợp với Công an để giữ an ninh trật tự giúp hành khách đi lại luôn được an toàn.</p>\r\n\r\n<p> </p>\r\n\r\n<p>Mọi thắc mắc, xin vui lòng bấm vào link sau để gọi <a href=\"http://vexere.com/ben-xe-mien-dong/so-dien-thoai-dia-chi-ben-xe-mien-dong\"><span style=\"color:#0000FF\">số điện thoại bến xe miền Đông</span></a>.</p>\r\n",
"suggestion": "",
"english_suggestion": "",
"note": "",
"name": "Bến xe Miền Đông",
"english_name": "Mien Dong Bus Station"
}
]
}
Request
- Path parameter
Parameter | Type | Required | Description |
---|---|---|---|
point_id | Integer | True | point_id is returned for each location (Note - not id) |
Response
Definitions | Type | Description |
---|---|---|
point_id | Integer | Id of the place to be picked up |
address | String | Address |
longitude | String | Longitude |
latitude | String | Latitude |
introduction | String | Location introduction (Location characteristics) |
enlish_introduction | String | Location introduction (Location characteristics) (English) |
suggestion | String | Information on driving directions |
english_suggestion | String | Information on driving directions (English) |
name | String | Location name |
english_name | String | Location name (English) |
image_urls | String | Information Photos locations |
note | String | Note |
url | String | Url google map (if have) |
Ticket
Booking one way ticket (1 chiều)
curl -X POST \
'{{main_url}}/v3/booking/reserve' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Content-Type: application/json' \
-H 'Postman-Token: f45894a5-2172-40ea-a2d2-af731917adfb' \
-H 'cache-control: no-cache' \
-d 'trip_code=v2CK6TCRCRCBoCMDgiAjAwMOCmywE6CjI2LTA5LTIwMTlIDlAM&seats=A5%7C1%7C1%7C2&customer_phone=0123456789&customer_name=test&customer_email=test%40gmail.com&pickup=C%E1%BB%95ng%20B%C6%B0u%20%C4%90i%E1%BB%87n%20Tam%20Trung&pickup_id=26032&drop_off_info=C%C3%A1i%20%C4%90%C3%B4i%20V%C3%A0m&drop_off_point_id=26033&have_eating=1'
var request = require("request");
var options = {
method: 'POST',
url: '{{main_url}}/v3/booking/reserve',
headers: {
'Postman-Token': 'f0e2c2e0-4185-4ccc-82a7-d4a3fe47c46f',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}',
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
trip_code: 'v2CK6TCRCRCBoCMDgiAjAwMOCmywE6CjI2LTA5LTIwMTlIDlAM',
seats: 'A5|1|1|2',
customer_phone: '0123456789',
customer_name: 'test',
customer_email: '[email protected]',
pickup: 'Cổng Bưu Điện Tam Trung',
pickup_id: '26032',
drop_off_info: 'Cái Đôi Vàm',
drop_off_point_id: '26033',
have_eating: '1'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"data": {
"message": "success",
"tickets": [
52053508
],
"code": "NO97T9",
"booking_code": "Q7E6J4M"
}
}
Request
- Body parameter
Parameter | Type | Required | Description |
---|---|---|---|
trip_code |
String | True | Trip code |
seats |
String | True | List of seat. Each seat code is full_code of seat. The seat are separated by commas “," Maximun number of seats is 8. See how to handle seats have multiple fare options here |
customer_phone |
String | True | Customer phone |
customer_name |
String | True | Customer name |
customer_email |
String | True | Customer email |
customer_id_number |
String | False | Customer's identity card (Just required for Phuong Trang bus operator - bus_id = 11071) |
pickup |
String | False | Name of the pickup point. Rules:
|
pickup_id |
Integer | False | ID of the pickup point. Rules:
|
transfer |
String | False | Name of the transfer point. Rules:
|
transfer_id |
Integer | False | ID of the transfer point. Rules:
|
drop_off_info |
String | False | Name of the drop-off point. Rules:
|
drop_off_point_id |
Integer | False | ID of the drop-off point. Rules:
|
drop_off_transfer_info |
String | False | Name of the drop-off transfer point. Rules:
|
arrive_transfer_id |
Integer | False | ID of the drop-off transfer point. Rules:
|
have_eating |
Integer | False | Eat or not (1/0). Do not eat can be ignored. |
note |
String | False | Note for Bus Operator |
user_agent |
String | False | Device Information |
Response
Definitions | Type | Description |
---|---|---|
tickets | Array | Ticket id list |
code | String | Ticket code |
booking_code | String | Booking code |
Booking two way ticket (khứ hồi)
curl -X POST '{{main_url}}/v3/booking/reserve' \
-H 'authority: uat-api.vexere.net' \
-H 'accept: application/json, text/plain, */*' \
-H 'authorization: bearer {{access_token}}' \
-H 'accept-language: vi-VN' \
-H 'content-type: application/json' \
-H 'referer: https://uat-fe.vexere.net/vi-VN/ve-xe-khach-tu-sai-gon-di-da-lat-lam-dong-129t23991.html?date=10-09-2020' \
--data-raw '[
{
"trip_code": "v2CKOnCRCipwkaAjIzIgIwMDDZ5ZMBOgoxMC0wOS0yMDIwSB1QyQOoAdzfAQ",
"customer_phone": "779505654",
"customer_name": "nguyen van loi",
"customer_email": "[email protected]",
"customer_id_number": "191679545",
"note": "",
"country_code": "VN",
"area_id": 152483,
"have_eating": 0,
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36",
"pickup_id": 0,
"pickup": "Trạm Đầm Sen",
"transfer_id": null,
"transfer": null,
"drop_off_point_id": 0,
"drop_off_info": "Văn phòng Đà Lạt||||0|152482",
"drop_off_transfer_info": null,
"arrive_transfer_id": null,
"seats": "7|1|3|3"
},
{
"trip_code": "v2CKOnCRCipwkaAjIzIgIwMDDZ5ZMBOgoxMC0wOS0yMDIwSB1QyQOoAdzfAQ",
"customer_phone": "779505654",
"customer_name": "nguyen van loi",
"customer_email": "[email protected]",
"customer_id_number": "191679545",
"note": "",
"country_code": "VN",
"area_id": 152483,
"have_eating": 0,
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36",
"pickup_id": 0,
"pickup": "Trạm Đầm Sen",
"transfer_id": null,
"transfer": null,
"drop_off_point_id": 0,
"drop_off_info": "Văn phòng Đà Lạt||||0|152482",
"drop_off_transfer_info": null,
"arrive_transfer_id": null,
"seats": "7|1|3|3"
}
]'
var request = require('request');
var options = {
'method': 'POST',
'url': '{{main_url}}/v3/booking/reserve',
'headers': {
'accept': 'application/json, text/plain, */*',
'authorization': 'bearer {{access_token}}',
'accept-language': 'vi-VN',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36',
'content-type': 'application/json',
'origin': 'https://uat-fe.vexere.net',
'referer': 'https://uat-fe.vexere.net/vi-VN/ve-xe-khach-tu-sai-gon-di-da-lat-lam-dong-129t23991.html?date=10-09-2020'
},
body: JSON.stringify([{"trip_code":"v2CKOnCRCipwkaAjIzIgIwMDDZ5ZMBOgoxMC0wOS0yMDIwSB1QyQOoAdzfAQ","customer_phone":"779505654","customer_name":"nguyen van loi","customer_email":"[email protected]","customer_id_number":"191679545","note":"","country_code":"VN","area_id":152483,"have_eating":0,"user_agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36","pickup_id":0,"pickup":"Trạm Đầm Sen","transfer_id":null,"transfer":null,"drop_off_point_id":0,"drop_off_info":"Văn phòng Đà Lạt||||0|152482","drop_off_transfer_info":null,"arrive_transfer_id":null,"seats":"7|1|3|3"},{"trip_code":"v2CKOnCRCipwkaAjIzIgIwMDDZ5ZMBOgoxMC0wOS0yMDIwSB1QyQOoAdzfAQ","customer_phone":"779505654","customer_name":"nguyen van loi","customer_email":"[email protected]","customer_id_number":"191679545","note":"","country_code":"VN","area_id":152483,"have_eating":0,"user_agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36","pickup_id":0,"pickup":"Trạm Đầm Sen","transfer_id":null,"transfer":null,"drop_off_point_id":0,"drop_off_info":"Văn phòng Đà Lạt||||0|152482","drop_off_transfer_info":null,"arrive_transfer_id":null,"seats":"7|1|3|3"}])
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
The above command returns JSON structured like this:
{
"data": [
{
"booking_code": "26B4W50",
"code": "D2985L",
"message": "success",
"tickets": [
60905932
]
},
{
"booking_code": "26B4W51",
"code": "D2985M",
"message": "success",
"tickets": [
60905933
]
}
]
}
Request
- Body parameter, array contain each item as bellow:
Parameter | Type | Required | Description |
---|---|---|---|
trip_code | String | True | Trip code |
seats | String | True | List of seat. Each seat code is full_code of seat. The seat are separated by commas “," Maximun number of seats is 8. See how to handle seats have multiple fare options here |
customer_phone | String | True | Customer phone |
customer_name | String | True | Customer name |
customer_email | String | True | Customer email |
customer_id_number | String | False | Customer's identity card (Just required for Phuong Trang bus operator - bus_id = 11071) |
pickup | String | False | Name of pick up point.
|
pickup_id | Integer | True | Pickup id |
transfer | String | False | Transshipment place.
|
transfer_id | Integer | False | Transfer id |
drop_off_info | String | True | Drop off.
|
drop_off_point_id | Integer | True | Drop off id |
drop_off_transfer_info | String | False | Drop off transfer point.
|
arrive_transfer_id | Integer | False | Drop off transfer id |
have_eating | Integer | False | Eat or not (1/0). Do not eat can be ignored. |
note | String | False | Note for Bus Operator |
user_agent | String | False | Device Information |
Response
Definitions | Type | Description |
---|---|---|
data | Array | array of bookings |
data[].tickets | Array | Ticket id list |
data[].code | String | Ticket code |
data[].booking_code | String | Booking code |
Get booking information
curl -X GET \
'{{main_url}}/v3/booking?code=Q7E6J4M' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 3f01697b-57d3-4f0f-82f3-a116cf8eeed5' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/booking',
qs: {
code: 'Q7E6J4M'
},
headers: {
'Postman-Token': 'aceca5a3-b294-4418-9a15-e7a5c24c2135',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": [
{
"seats": 1,
"code": "Q7E6J4M",
"status": 1,
"description": "NEW",
"transactions": {},
"amount_booking": 890000,
"amount_obj": {
"all_fare": 1050000,
"all_surcharge": 40000,
"all_discount": 200000,
"coupon_value": 0,
"campaign_value": null,
"bus_total_cost": 890000,
"bus_total_discount": 0
},
"cancelled_amount": 0,
"cancelled_amount_obj": {
"all_fare": 0,
"all_surcharge": 0,
"all_discount": 0,
"coupon_value": 0,
"campaign_value": null,
"bus_total_cost": 0,
"bus_total_discount": 0
},
"fare": 1000000,
"eating_fare": 50000,
"final_price": 1000000,
"from": "Thác Bản Giốc",
"to": "Bến Tàu Đầm Dơi",
"from_id": 149934,
"to_id": 1041,
"from_state_id": "14",
"from_city_id": "193",
"ticket": {
"code": "NO97T9",
"status": 1,
"ids": [
"52053508"
],
"detail_status": [
1
],
"detail_info": [
{
"status": 1,
"fare": 1000000,
"seat": "A5|1|1|2",
"bus_operator_status": 0,
"customer_status": 0,
"discount": 0,
"vxr_discount_value": 200000,
"surcharge": 0,
"name": "test",
"secondary_commission": 50000
}
]
},
"created_user": "test.client.vxr",
"seat_codes": [
"A5"
],
"created_date": "11:06PM 25/09/2019",
"created_date_iso": "2019-09-25T23:06:16.163Z",
"agent_id": "29446",
"company": "Xe Ty Le",
"comp_id": "27091",
"trip_id": "3330912",
"trip_date": "08:00AM 26/09/2019",
"vehicle": {
"number": "",
"driver": "",
"phone_info": "",
"assistant": ""
},
"pickup_date": "08:00AM 26/09/2019",
"trip_code": "v2CK6TCRCRCBoCMDgiAjAwMOCmywE6CjI2LTA5LTIwMTlIDlAM",
"trip_name": "Cao Bằng - Cà Mau",
"payment_info": "6:29446:",
"transfer_ids": [],
"type": 2,
"discount": 200000,
"vxr_discount_value": 200000,
"discount_not_confirm": 0,
"discount_reason_id": 0,
"discount_reason_info": "",
"vxr_discount_reason_id": 1,
"vxr_discount_reason_info": "giảm giá (27491)",
"expired_time": "11:21PM 25/09/2019",
"expired_time_iso": "2019-09-25T23:21:00.000Z",
"coupon": null,
"cancelled_date": null,
"charge_date": null,
"language_info": "vi-VN",
"surcharge_booking": null,
"refundable": 1,
"round_trip_date": null,
"drop_off_transfer_info": "",
"surcharge": 0,
"pickup_info": "Cổng Bưu Điện Tam Trung|||26032",
"pickup_surcharge": 20000,
"pickup_id": 26032,
"transfer_id": 0,
"transfer_surcharge": 0,
"arrive_transfer_surcharge": 0,
"drop_off_surcharge": 20000,
"drop_off_info": "Cái Đôi Vàm",
"drop_off_point_id": 26033,
"last_updated_date": "23:06 25/09/2019",
"trip_code_info": {
"search_from": 14,
"search_to": 12
},
"pickup_time_expected": "08:15",
"pickup_time_expected_full": "08:15 26/09/2019",
"pickup_guide": "<ul>\n <li>Để kiểm tra điểm đón quý khách xem tại đây: null</li>\n</ul>",
"pickup_english_guide": "<ul>\n <li>Please check your pickup point here: null</li>\n</ul>",
"arrival_date": "02:00AM 28/09/2019",
"total_cancel_fee": 0,
"all_tickets_cancelled": [
{
"seat_code": "5",
"ids": "61063101",
"cancelled_date": "04-05-2022 23:10:22",
"cancelled_user": "[email protected]",
"cancel_info": "",
"cancel_fee": 50000,
"refund_fee": 950000,
"agent_refund_fee": 0,
"agent_cancel_fee": 50000,
"cancel_type": 11,
"fare": 1000000,
"bus_operator_status": 0,
"customer_status": 0,
"cancel_total_cost": 1000000,
"discount": 0,
"vxr_discount_value": 0,
"surcharge": 0,
"secondary_commission": 0,
"user_charge": "fe.client.vxr",
"date_charge": "2022-05-04T23:08:39.000Z"
}
]
}
]
}
Request
- Query parameter
Parameter | Type | Required | Description |
---|---|---|---|
code | String | True | Booking code |
checking_status_only | Integer | False | 1 |
Response
Definitions | Type | Description |
---|---|---|
id | Integer | Booking id |
seats | Integer | Number of tickets |
code | String | Booking id code |
status | Integer | Booking status (1-Reserve, 4-Paid, 5-Refund) |
transactions | Object | Transaction codes of partners |
description | String | Describe the reservation status |
amount_booking | Integer | Total money |
from | String | Departure place |
to | String | Destination |
customer | Object | Customer information |
customer.name | String | Customer name |
customer.phone | String | Customer phone number |
customer.email | String | Email customer |
ticket | Object | Ticket information |
ticket.code | String | Ticket code |
ticket.status | Integer | Ticket status |
ticket.detail_info | Object | Details of each ticket |
user_charge | String | Payment account |
charge_date | String | Date of payment |
cancelled_date | String | Cancellation date |
created_user | String | Booking account |
seat_codes | Array | Seat code |
created_date | String | Booking date |
expired_time | String | Expiration date |
company | String | Name of Bus operators |
trip_date | String | Trip date |
vehicle | Object | Vehicle info |
vehicle.number | String | Plate |
vehicle.driver | String | Driver's name |
vehicle.phone_info | String | Number phone of driver and assistant |
vehicle.assistant | String | Assistant's name |
arrival_date | String | Estimated arrival time |
trip_name | String | Route name |
trip_code | String | Time code |
pickup_date | String | Pick up time |
pickup_guide | String | Guide to the bus (HTML code) |
pickup_english_guide | String | Guide to the bus (English)(HTML code) |
pickup_time_expected_full | String | Pick up time |
pickup_info | String | Pickup point info |
pickup_surcharge | Integer | Pickup point surcharge |
pickup_id | Integer | Pickup point Id |
transfer_id | Integer | Transshipment point Id |
transfer_surcharge | Integer | Transshipment point surcharge |
arrive_transfer_surcharge | Integer | Arrive transfer surcharge |
drop_off_surcharge | Integer | Drop off surcharge |
drop_off_info | String | Drop off info |
drop_off_point_id | Integer | Drop off point id |
all_tickets_cancelled | Array | List all ticket cancelled |
Pay
Pay booking 1 chiều
curl -X POST \
{{main_url}}/v3/booking/pay \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Postman-Token: 7c0190dc-6b6c-41c2-be58-9850542a8bf3' \
-H 'cache-control: no-cache' \
-d 'code=YD1SD6Y&transaction_id=123456789'
var request = require("request");
var options = {
method: 'POST',
url: '{{main_url}}/v3/booking/pay',
headers: {
'Postman-Token': '49827b37-d096-43ea-8c20-89b2f97d0f45',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}',
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
code: 'YD1SD6Y',
transaction_id: '123456789'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"data": {
"message": "success",
"ticket_code": "G81G04",
"booking_code": "5MN04PD"
"vxr_transaction_id": "v2Uxc9_sr-KgzGCrMhVQ"
}
}
Request
- Body parameter
Parameter | Type | Required | Description |
---|---|---|---|
code | String | True | Booking code |
transaction_id | String | False | Transaction code arising from partners, used for control. |
coupon | String | False | Coupon code (If available) |
payment_info | Object | False | Information when payment |
payment_info.order_code | String | False | Order code |
payment_info.order_status | String | False | Payment status in service |
Response
Definitions | Type | Description |
---|---|---|
ticket_code | String | Ticket code |
vxr_transaction_id | String | VXR transaction code incurred for the partner |
Pay booking khứ hồi
curl --location --request POST '{{main_url}}/v3/booking/pay' \
--header 'Authorization: Bearer {{access_token}}' \
--header 'Content-Type: application/json' \
--data-raw '[
{
"code": "5MN04PD",
"coupon": "H8606H"
},
{
"code": "SSEE738",
"coupon": "U4ERT7"
}
]'
var request = require("request");
var options = {
method: 'POST',
url: '{{main_url}}/v3/booking/pay',
headers: {
Authorization: 'Bearer {{access_token}}',
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
data: [{code: 'YD1SD6Y', coupon: '111111'}, {code: 'YD1SD6Z'}],
transaction_id: '123456789'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"data": [
{
"message": "success",
"ticket_code": "P895XX",
"vxr_transaction_id": "v2EQx6_sr-RgW5acNHSA",
"booking_code": "5MN04PD"
},
{
"message": "success",
"ticket_code": "1VYJL0",
"vxr_transaction_id": "v2ZTI7_sr-IBuyHMAkNA",
"booking_code": "SSEE738"
}
]
}
Request
- Body parameter
Parameter | Type | Required | Description |
---|---|---|---|
data | Array | True | List of pair of Booking code, coupon |
transaction_id | String | False | Transaction code arising from partners, used for control. |
data[].code | String | False | Booking code |
data[].coupon | String | False | Coupon code (If available) |
data[].payment_info | Object | False | Information when payment |
data[].payment_info.order_code | String | False | Order code |
data[].payment_info.order_status | String | False | Payment status in service |
Response
Definitions | Type | Description |
---|---|---|
ticket_code | Array | Array of ticket code |
vxr_transaction_id | Array | Array of VXR transaction code incurred for the partner |
Apply coupon
curl -X PUT \
{{main_url}}/v3/booking/{{booking_code}}/coupon \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Postman-Token: 7c0190dc-6b6c-41c2-be58-9850542a8bf3' \
-H 'cache-control: no-cache' \
--data-urlencode 'coupon=DAOBRT61Z'
var request = require("request");
var options = {
method: 'PUT',
url: '{{main_url}}/v3/booking/Q7E6J4M/coupon',
headers: {
'Postman-Token': '49827b37-d096-43ea-8c20-89b2f97d0f45',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}',
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
coupon: 'DAOBRT61Z'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"final_price": 360000,
"amount_obj": {
"coupon_value": 40000
},
"coupon_info": {
"not_included_date": [
{
"from": "2019-09-23T17:00:00.000Z",
"to": "2019-09-24T16:59:59.999Z"
}
],
"not_included_booking_date": [
{
"from": "2019-09-24T17:00:00.000Z",
"to": "2019-09-25T16:59:59.999Z"
}
],
"name": "HAUTEST",
"code": "HAU8EK581",
"coupon_code": "HAU8EK581",
"type": 2,
"unit": 2,
"coupon_value": 10,
"min_num_of_ticket": 1,
"max_num_of_ticket": null,
"min_affect_value": null,
"max_affect_value": null,
"max_discount_value": null,
"unit_description": "percent",
"fare_info": {
"booking_fare": 400000,
"coupon_value": 40000,
"final_fare": 360000
}
}
}
}
Request
- Path parameter
Parameter | Type | Required | Description |
---|---|---|---|
booking_code | String | True | Booking code |
- Body parameter
Parameter | Type | Required | Description |
---|---|---|---|
coupon | String | True | Coupon code |
Response
Definitions | Type | Description |
---|---|---|
final_price | Number | fare after applying coupon |
amount_obj.coupon_value | Number | Coupon value |
coupon_info | Object | Coupon detail infomation |
coupon_info
definition
Definitions | Type | Description |
---|---|---|
not_included_date | Array | Not include some date |
not_included_date[index].from | String | Not include from date |
not_included_date[index].to | String | Not include to date |
not_included_booking_date | Array | Not include some booking date |
not_included_booking_date[index].from | String | Not include from booking date |
not_included_booking_date[index].to | String | Not include to booking date |
name | String | Campaign name |
type | Integer | Coupon type |
code | String | Coupon code |
unit | Integer | Unit (1: %, 2: VND) |
unit_description | String | Description of calculation units |
coupon_value | Integer | Coupon value |
max_discount_value | Integer | The maximum amount of reduction |
min_affect_value | Integer | Minimum value applied |
min_num_of_ticket | Integer | Minimum ticket number applied |
max_num_of_ticket | Integer | Maximum ticket number applied |
start_booking_date | String | From booking date |
end_booking_date | String | To booking date |
start_date | String | From departure date |
expire_date | String | To departure date |
fare_info | Object | Ticket price information when applying coupon |
fare_info.booking_fare | Integer | Fare |
fare_info.final_fare | Integer | Final fare after applying coupon |
fare_info.coupon_value | Integer | The value of the coupon applies to the booking |
Get refund mechanism
curl -X GET \
'{{main_url}}/v3/booking/refund?code=YD1SD6Y' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 260ceac4-6228-4965-a7d8-df98b2a98cb9' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/booking/refund',
qs: {
code: 'YD1SD6Y'
},
headers: {
'Postman-Token': '0ebfd356-2838-4fb8-99e6-ad7b051dde10',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"data": {
"fare": 850000,
"num_of_ticket": 1,
"total_fare": 890000,
"cancel_fee": 0,
"refund": 890000,
"refundList": [
{
"rule": 1,
"cancel_fee": 0,
"time": 120,
"type": 1,
"value": 0,
"pre_time": 0,
"is_selected": false,
"cancelable": true
}
],
"percent": 0,
"is_vexere_rule": false,
"type": 1,
"cancelable": true,
"total_refund_fare": 1090000,
"detail_fare_arr": [
{
"total_refund_fare": 1090000,
"total_fare": 890000,
"cancel_fee": 0,
"refund": 890000
}
],
"is_over_trip_date": 0
}
}
Request
- Query parameter
Parameter | Type | Required | Description |
---|---|---|---|
code | String | True | Booking code |
Response
Definitions | Type | Description |
---|---|---|
fare | Integer | Price per ticket |
total_fare | Integer | Total fare |
num_of_ticket | Integer | Number of tickets |
refund | Integer | Refund level |
cancel_fee | Integer | Cancellation fee |
cancelable | Boolean | Specifies whether the ticket can be canceled or not |
refundList[index].pre_time | Integer | Determine range of time before departure time (details) (No.5 FAQ) |
refundList[index].time | Integer | Determine range of time before departure time (details) (No.5 FAQ) |
refundList[index].value | Integer | Cancellation fee |
refundList[index].type | Integer | Charge unit type of the value above (type = 1 -> percentage, type = 2 -> fixed VNĐ) |
refundList[index].cancel_fee | Integer | Calculated cancellation fee in VNĐ |
refundList[index].is_selected | Boolean | Its value is true if the rule is matched |
Cancelling ticket
Note: Hủy bằng Ticket Code, do email gửi khách là ticket code, khách có thể chỉ biết ticket code để yêu cầu hủy
curl -X POST \
{{main_url}}/v3/booking/refund \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Postman-Token: 2e304f44-73a2-4a25-a110-c215e0e74951' \
-H 'cache-control: no-cache' \
-d 'code=G81G04'
var request = require("request");
var options = {
method: 'POST',
url: '{{main_url}}/v3/booking/refund',
headers: {
'Postman-Token': '9504faab-2f2e-46a5-a45d-1acb12e0c481',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}',
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
code: 'G81G04'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"data": {
"message": "success",
"vxr_transaction_id": "v2Uww__sr-KgzGCrMhVQ",
"cancel_fee": 0,
"refund": 890000
}
}
Request
- Body parameter
Parameter | Type | Required | Description |
---|---|---|---|
code | String | True | Ticket code |
transaction_id | String | False | Transaction code arising from partners, used for control |
Response
Definitions | Type | Description |
---|---|---|
vxr_transaction_id | String | VXR transaction code incurred for the partner |
cancel_fee | Integer | Cancellation fee |
refund | Integer | Refund level |
Update ticket info
Note: required booking status = 4
- (VN): Thay đổi thông tin vé đã thanh toán dành cho đại lý API
- (EN): Change paid ticket information for API agents
curl -X PUT \
{{main_url}}/v3/booking/{{code}}/agent_api \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Postman-Token: 2e304f44-73a2-4a25-a110-c215e0e74951' \
-H 'cache-control: no-cache' \
-d 'code=G81G04'
var request = require("request");
var options = {
method: 'PUT',
url: '{{main_url}}/v3/booking/{{code}}/agent_api',
headers: {
'Postman-Token': '9504faab-2f2e-46a5-a45d-1acb12e0c481',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}',
'Content-Type': 'application/x-www-form-urlencoded'
},
from: {
customer_name: 'Customer Name',
customer_email: '[email protected]',
pickup: '123 Nguyễn Thị MinhKhai',
pickup_id: '30986',
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"booking_code": "FIB4R76",
"updated_ticket": [
"61110084"
]
}
}
Request
- Path variables
Parameter | Type | Required | Description |
---|---|---|---|
code | String | True | Booking code |
- Body parameter
Parameter | Type | Required | Description |
---|---|---|---|
customer_name | String | False | Customer name |
customer_email | String | False | Customer phone |
pickup | String | False | Pickup info |
pickup_id | String | False | Pickup point id |
area_id | String | False | Area id |
transfer | String | False | Transfer info |
transfer_id | String | False | Transfer point id |
drop_off_transfer_info | String | False | Arrive transfer info |
arrive_transfer_id | String | False | Arrive transfer point id |
drop_off_info | String | False | Drop off info |
drop_off_point_id | String | False | Drop off pint id |
Response
Definitions | Type | Description |
---|---|---|
booking_code | String | Booking code |
updated_ticket | Array | Ticket list has been updated |
Coupon
Coupon check
curl -X GET \
'{{main_url}}/v3/campaign/coupon?code=QUANKUNX38G47&booking_code=BG572WL' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 11e09101-deb9-4733-8710-cb2edb5e9ead' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/campaign/coupon',
qs: {
code: 'QUANKUNX38G47',
booking_code: 'BG572WL'
},
headers: {
'Postman-Token': 'f269d2d1-84ec-4450-b1e9-6d5bb7691b34',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"info": {
"not_included_date": [
{
"from": "2019-09-23T17:00:00.000Z",
"to": "2019-09-24T16:59:59.999Z"
}
],
"not_included_booking_date": [
{
"from": "2019-09-24T17:00:00.000Z",
"to": "2019-09-25T16:59:59.999Z"
}
],
"name": "Quan test 2309 - 03",
"unit": 1,
"start_booking_date": "2019-09-23",
"end_booking_date": "2019-09-30",
"type": 1,
"coupon_value": 10000,
"min_num_of_ticket": 2,
"max_num_of_ticket": 3,
"min_affect_value": 100000,
"code": "QUANKUNX38G47",
"coupon_code": "QUANKUNX38G47",
"unit_description": "VND",
"fare_info": {
"booking_fare": 890000,
"final_fare": 10000,
"coupon_value": 880000
}
}
}
}
The information of max_discount_value, min_affect_value, min_num_of_ticket, max_num_of_ticket only valid when greater than 0. Coupon type:
- Fixed price coupon – the amount of money collected on each ticket is equal to the value of the coupon. Ex: fare 80,000 VND, Coupon value is 10,000 VND, Guests buy 2 tickets, the amount collected will be 20,000 VND.
- Discount coupons – the amount collected will be equal to the price of tickets minus the value of the coupon. Ex: fare 100,000 VND, coupon 5%, Guests buy 1 ticket, the guest collection amount will be 95,000 VND.
The maximum amount of reduction: Maximum discount value for discount coupon. Ex: Fare 300, 000 VND, coupon 5%, Customers buy 2 tickets, the maximum discount amount is 20, 000 VND, the guest collection amount will be 580, 000 VND. If the customer buys 1 ticket, the guest fee will be 285, 000 VND.
If coupon type = 1, we will check the "unit". - unit = 1, coupon discount in %. - unit = 2, coupon discount in VND.
Request
- Query parameter
1 field of trip_code or booking_code required
Parameter | Type | Required | Description |
---|---|---|---|
code | String | True | Coupon code |
trip_code | String | True | Trip code |
booking_code | String | True | Booking code |
Response
Definitions | Type | Description |
---|---|---|
info | Object | Coupon information |
not_included_date | Array | Not include some date |
not_included_date[index].from | String | Not include from date |
not_included_date[index].to | String | Not include to date |
not_included_booking_date | Array | Not include some booking date |
not_included_booking_date[index].from | String | Not include from booking date |
not_included_booking_date[index].to | String | Not include to booking date |
name | String | Campaign name |
type | Integer | Coupon type |
code | String | Coupon code |
unit | Integer | Unit (1: %, 2: VND) |
unit_description | String | Description of calculation units |
coupon_value | Integer | Coupon value |
max_discount_value | Integer | The maximum amount of reduction |
min_affect_value | Integer | Minimum value applied |
min_num_of_ticket | Integer | Minimum ticket number applied |
max_num_of_ticket | Integer | Maximum ticket number applied |
start_booking_date | String | From booking date |
end_booking_date | String | To booking date |
start_date | String | From departure date |
expire_date | String | To departure date |
fare_info | Object | Ticket price information when applying coupon |
fare_info.booking_fare | Integer | Fare |
fare_info.final_fare | Integer | Final fare after applying coupon |
fare_info.coupon_value | Integer | The value of the coupon applies to the booking |
Ticket cancellation policy
Get the cancellation policy
curl -X GET \
'{{main_url}}/v3/cancellation/policy?trip_code=v2CK6TCRCRCBoCMDgiAjAwMOCmywE6CjI2LTA5LTIwMTlIDlAM' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: a2dbd829-ef92-4180-a5db-30a6f9d1db54' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/cancellation/policy',
qs: {
trip_code: 'v2CK6TCRCRCBoCMDgiAjAwMOCmywE6CjI2LTA5LTIwMTlIDlAM'
},
headers: {
'Postman-Token': '8e15ec53-94e1-4e5e-b242-b008df57d564',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"name": "Miễn phí hủy",
"detail": [
{
"from": 0,
"to": 2,
"fee": "0",
"currency": "1",
"disable_cancel": false,
"currency_description": "%",
"cancelable": true
}
],
"note": "Phí huỷ sẽ được tính trên giá gốc, không giảm trừ khuyến mãi hoặc giảm giá; đồng thời không vượt quá số tiền quý khách đã thanh toán. \n",
"english_note": "Cancellation fee is calculated on original price, excluding discount and not exceeding your paid amount. \n",
"internal_note": "",
"use_all_route": 0
}
}
When the bus operator does not have a cancellation policy, the default cancellation policy will apply.
- 1 hour before departure: No refund.
- Before 1 hour before departure time: 5% cancellation of ticket value.
Request
- Query parameter
Parameter | Type | Required | Description |
---|---|---|---|
trip_code | String | True | Trip code |
Response
Definitions | Type | Description |
---|---|---|
name | String | Name of cancellation policy |
start_date | String | Start date of the policy “YYYY-MM-DD” |
end_date | String | Policy end date “YYYY-MM-DD” |
detail | Array | List of cancellation tickets |
detail[index].from | Float | How long before departure (h), e.g. 1.5, 1 |
detail[index].to | Float | How long before departure time, e.g. 1.5, 1 |
detail[index].fee | Integer | Cancellation fee |
detail[index].currency | Integer | Charge unit type when canceling tickets |
detail[index].currency_description | Integer | Description of unit charge |
detail[index].cancelable | Boolean | Allow cancellation of tickets |
note | String | Note |
english_note | String | English note |
internal_note | String | Own notes |
Bus operator
Get the image list of bus operators
curl -X GET \
{{main_url}}/v3/company/2/image \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: f2477d29-f2ef-4906-b591-29417de52a2e' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/company/2/image',
headers: {
'Postman-Token': '49522975-8c8c-4528-87b1-1a83a3bc803b',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": [
{
"image_id": 31,
"company": {
"id": 2
},
"caption": {
"vi": "Xe Giường nằm VIP Limousine",
"en": "Tiến Oanh bus photos - VeXeRe.com"
},
"title": {
"vi": "Xe Tiến Oanh - VeXeRe.com",
"en": "Tiến Oanh bus - VeXeRe.com"
},
"alt": {
"vi": "Xe Giường nằm VIP Limousine",
"en": "Tiến Oanh bus - VeXeRe.com"
},
"files": {
"1000x600": "////static.vexere.com/c/i/2/xe-tien-oanh-VeXeRe-5f2OULo-1000x600.jpg"
}
}
]
}
Request
- Path parameter
Parameter | Type | Required | Description |
---|---|---|---|
id | Integer | True | Bus operator id |
Response
Definitions | Type | Description |
---|---|---|
caption | Object | Caption |
title | Object | Title |
files | Object | List of images according to each resolution |
Get info of bus operators
curl -X GET \
{{main_url}}/v3/company/2/info_for_agent \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: e875b9c3-5f0b-4e5b-9157-bee72528d8d2' \
-H 'cache-control: no-cache'
var request = require("request");
var options = {
method: 'GET',
url: '{{main_url}}/v3/company/2/info_for_agent',
headers: {
'Postman-Token': '1920a8b6-007e-4f48-bf8b-4ebf70a508f2',
'cache-control': 'no-cache',
Authorization: 'Bearer {{access_token}}'
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"id": "2",
"hotline_info": "0905 882 082 , 083 811 0779",
"name": "Tiến Oanh"
}
}
Request
- Path parameter
Parameter | Type | Required | Description |
---|---|---|---|
id | Integer | True | Bus operator id |
Response
Definitions | Type | Description |
---|---|---|
id | Integer | Bus operators id |
name | String | Bus operators name |
hotline_info | String | Bus hotline |
Review bus operator
Get the review bus operators information
curl -X GET \
'{{user_profile_url}}/company/28636/reviews?per_page=5&page=1' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 078d6007-c104-4583-90ed-e343886b9efc' \
-H 'cache-control: no-cache'
var request = require('request');
var options = {
'method': 'GET',
'url': '{{user_profile_url}}/company/28636/reviews?per_page=5&page=1',
'headers': {
'Authorization': 'Bearer {{access_token}}'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"page": 1,
"page_size": 5,
"total_pages": 1,
"total": 1,
"items": [
{
"id": 1051,
"status": 2,
"trip_id": 2421465,
"trip_name": "Sài Gòn - Đà Lạt",
"name": "Huy",
"comp_id": 28636,
"comment": "Detail review",
"created_at": "2020-06-12T03:08:44.694Z",
"approved_at": "2020-06-12T03:08:44.694Z",
"rating": "4",
"company_reply": []
}
]
}
}
Request
- Path parameter
Parameter | Type | Required | Description |
---|---|---|---|
id | Integer | True | Bus operator id |
- Query parameter
Parameter | Type | Required | Description |
---|---|---|---|
per_page | Integer | False | Maximum number of elements in the page |
page | Integer | False | Number of page |
rating[min] | Integer | False | From min rating |
rating[max] | Integer | False | To max rating |
Response
Definitions | Type | Description |
---|---|---|
page | Integer | Current page |
page_size | Integer | Maximum number of elements in the page |
total | Integer | Total number of elements |
total_pages | Integer | Total pages |
items | Array | Review Company |
items[index].id | Integer | Review Id |
items[index].name | String | Reviewer’s name |
items[index].rating | String | Rating score |
items[index].comment | String | Comment content |
items[index].trip_name | String | Name of trip |
items[index].created_at | String | Time review |
company_reply | Array | List comment of the company |
company_reply[index].id | Integer | Id of company's comment |
company_reply[index].content | String | Content of the comment |
company_reply[index].is_activated | Integer | Its value is 1 if is active |
company_reply[index].created_at | String | Comment's creation time in ISO format |
company_reply[index].created_by | String | Username of the user create the comment |
Get rating point and all other info (bus operator phone number) of bus operators
curl -X GET \
'{{user_profile_url}}/company/28636' \
-H 'Authorization: Bearer {{access_token}}' \
-H 'Postman-Token: 078d6007-c104-4583-90ed-e343886b9efc' \
-H 'cache-control: no-cache'
var request = require('request');
var options = {
'method': 'GET',
'url': '{{user_profile_url}}/company/28636',
'headers': {
'Authorization': 'Bearer {{access_token}}'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
The above command returns JSON structured like this:
{
"message": "Success",
"data": {
"overall": {
"id": "3621",
"comp_id": 28636,
"rv_main_name": "overall",
"rv_main_value": "3.7",
"label": "Mức độ hài lòng của bạn với nhà xe",
"label_english": "Rate the overall experience of your recent trip",
"count": 18
},
"rating": [
{
"id": "3619",
"comp_id": 28636,
"rv_main_name": "amenity",
"rv_main_value": "3.9",
"label": "Tiện ích",
"label_english": "Amenities",
"count": 18
},
],
"company_info": {
"id": "28636",
"phone_info": "02543.515.200 02543.515.369 02543.531.982 02543.833.333",
"name": "Đan Anh",
"full_name": "Công ty TNHH Du Lịch và Vận Tải Đan Anh ",
"description": "<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Bất kỳ thời điểm nào trong năm, Đà Lạt luôn là địa điểm thu hút nhiều chuyến xe di chuyển từ Sài Gòn lên và ngược lại. Chất lượng xe trên tuyến đường Sài Gòn - Đà Lạt đều rất tốt, có chất lượng cao. Trong thời gian này, VeXeRe.com mở bán tân binh mới toanh nhưng chất lượng vô cùng cạnh tranh là xe Đan Anh limousine. Dòng chuyên cơ mặt đất làm hài lòng nhiều hành khách được nhà xe đưa vào vận hành. Sự chuẩn bị kỹ lưỡng trong khâu phục vụ hành khách của Đan Anh limousine đi Đà Lạt từ Sài Gòn hứa hẹn sẽ mang đến những trải nghiệm mới mẻ nhất. </span><span style=\"color:rgb(0, 0, 0); font-family:arial; font-size:14.6667px\">Ngoài ra, nhà xe còn mở rộng dịch vụ vận chuyển tuyến Sài Gòn - Mũi Né và Mũi Né - Đà Lạt, mang lại nhiều lựa chọn cho nhu cầu đi lại của hành khách.</span></p>\n\n<h1 style=\"text-align:justify\"><strong>1. Đặt vé </strong><a href=\"https://vexere.com/vi-VN/xe-dan-anh?utm_source=blogvxr&utm_campaign=SEO&utm_content=ha\" style=\"text-decoration-line: none;\"><strong>xe Đan Anh limousine</strong></a><strong> và vấn đề cần lưu ý:</strong></h1>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Hãng xe Đan Anh limousine hỗ trợ dòng xe Limousine 9 chỗ. Số lượng ghế ít và chất lượng dịch vụ cao nên nếu đặt quá gần ngày đi sẽ không còn những vị trí tốt hoặc hết vé. Bạn có thể đặt vé trước xe Đan Anh limousine các tuyến dễ dàng và thanh toán tiện lợi qua hệ thống đặt vé trực tuyến </span><a href=\"https://vexere.com?utm_source=blogvxr&utm_campaign=SEO&utm_content=ha\" style=\"text-decoration-line: none;\"><span style=\"background-color:transparent; color:rgb(17, 85, 204); font-family:arial; font-size:11pt\">VeXeRe.com</span></a></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Loại xe hỗ trợ tốt về chất lượng ghế ngồi người đi. Tuy nhiên xe không có gầm xe lớn như các loại xe giường nằm. Nên trong trường hợp có hành lý quá nhiều hoặc kích thước lớn, bạn cần liên hệ tổng đài tư vấn để kiểm tra xem có đủ chỗ không trước khi thanh toán.</span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\"><img src=\"https://lh5.googleusercontent.com/w-RslFxfycS_HEAOKMTkF9U7-oPfzcBlWrWB5wSo44VqyapsUFrZzevIKikHn2Ci4YiiommBpgSK1eoafqym413j_BotS4fRX6607hloifR2iLh7WKIe1l6uBfci34GGD34_AxUG\" style=\"height:361px; width:602px\" /></span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Bên cạnh đó, xe Đan Anh limousine hỗ trợ xe ghế ngã là loại ghế có nệm dày. Người ngồi sẽ trải nghiệm được cảm giác êm ái, thoải mái nhất. Nếu hành khách có em bé, hoặc đi cả gia đình, nên lựa chọn băng chung 3 người ở phía cuối. Cả gia đình sẽ có chỗ rộng rãi và thoải mái hơn so với các ghế lẻ ở giữa xe.</span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Xe Đan Anh limousine có chấp nhận vé điện tử. Bạn chỉ cần đưa mã vé cho nhân viên hoặc tài xế là có thể lên xe. Nhân viên hãng xe có thể liên hệ qua số điện thoại đặt vé để xác nhận trước khi đi. Bạn nên lưu ý giữ điện thoại thường xuyên để tiện liên hệ.</span></p>\n\n<h1 style=\"text-align:justify\"><strong>2. </strong><a href=\"https://vexere.com/vi-VN/xe-dan-anh/so-dien-thoai-dia-chi-xe-dan-anh?utm_source=blogvxr&utm_campaign=SEO&utm_content=ha\" style=\"text-decoration-line: none;\"><strong>Địa chỉ và số điện thoại đặt xe Đan Anh limousine</strong></a></h1>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Tại Sài Gòn, xe có văn phòng tại cổng công viên 23/9, quận 1, Sài Gòn. Xe hỗ trợ trung chuyển tại một số địa điểm cố định ở Sài Gòn: Q.1,3,10,11... và đón trả tận nơi tại sân bay Tân Sơn Nhất. Hành khách có thể liên hệ trực tiếp hoặc gọi về tổng đài 1900 7070 để được tư vấn và hỗ trợ. </span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Tại Đà Lạt, hành khách có thể liên hệ trực tiếp tại số 54 Mai Anh Đào, phường 8, Đà Lạt. Xe hỗ trợ trung chuyển một số địa điểm trong nội thành Đà Lạt<br />\nTại Mũi Né, nhà xe có văn phòng tại đường Huỳnh Thúc Kháng, Mũi Né, Bình Thuận. Hành khách có thể liên hệ 1900 7070 để được tư vấn hoặc đặt vé trực tiếp:</span></p>\n\n<p style=\"text-align:center\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\"><a href=\"https://vexere.com/vi-VN/ve-xe-khach-dan-anh-tu-sai-gon-di-mui-ne-binh-thuan-129t27071-28636.html?utm_source=blogvxr&utm_campaign=SEO&utm_content=ha\">Xe từ Sài Gòn đi Mũi Né</a><br />\n<a href=\"https://vexere.com/vi-VN/ve-xe-khach-dan-anh-tu-mui-ne-binh-thuan-di-sai-gon-2707t1291-28636.html?utm_source=blogvxr&utm_campaign=SEO&utm_content=ha\">Xe từ Mũi Né đi Sài Gòn</a></span></p>\n\n<h1 style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">3. </span><strong>Tại sao nên chọn xe Đan Anh limousine cao cấp?</strong></h1>\n\n<p style=\"text-align:justify\"><a href=\"https://vexere.com/vi-VN/xe-dan-anh/danh-gia\" style=\"text-decoration-line: none;\"><span style=\"background-color:transparent; color:rgb(17, 85, 204); font-family:arial; font-size:11pt\">Đánh giá xe Đan Anh limousine</span></a><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\"> từ khách hàng khá tốt. Hãng xe cam kết luôn mang đến chất lượng cao cấp nhất, sự hỗ trợ khách hàng tận tình nhất.</span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Được thiết kế cải tiến từ xe lớn thành loại xe ít chỗ ngồi hơn. Thành ghế rộng rãi hơn tương đương với ghế hạng thương gia của các hãng hàng không. Thậm chí các hành khách cao to cũng phù hợp.</span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\"><img src=\"https://lh5.googleusercontent.com/4rANZ_2glIeUHps34esbIRFQD7_hxS1TLUEo2WS6B-69rsuGFUd0jlQxwG35VkfySgsQdgosMahxBwNp7OVjc-Ev7f74uZNi7ytiH9_THWlxj0q88_A0RIeoaYoo4BHOXqlRONXa\" style=\"height:361px; width:602px\" /></span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Xe Đan Anh limousine là dòng xe Limousine có thiết kế 11 ghế cao cấp từ xe 16 chỗ thông thường. Không gian rộng rãi, kích thước ghế lớn. Các ghế giữa xe có chỗ để tay, có thể ngả từ 10~45 độ tùy theo nhu cầu. Trên xe trang bị Wifi, cổng sạc USB ngay gần tại vị trí các ghế. Màn hình cỡ lớn LED 21 inches và khăn lạnh, nước suối miễn phí.</span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Các ghế ngồi được thiết kế trượt ngã bằng các nút điều chỉnh. Hành khách có thể lựa chọn tư thế phù hợp và thoải mái nhất một cách dễ dàng, nhanh chóng.</span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Nhân viên phục vụ luôn nhiệt tình hỗ trợ khách hàng trong mọi tình huống. Tài xế được lựa chọn kỹ lưỡng, luôn đặt sự an toàn và thoải mái của hành khách lên trên hết.</span></p>\n\n<p style=\"text-align:justify\"><span style=\"background-color:transparent; color:rgb(0, 0, 0); font-family:arial; font-size:11pt\">Xem thêm thông tin các hãng xe cùng tuyến đường và đặt vé với giá thấp nhất:</span></p>\n\n<p style=\"text-align:center\"><a href=\"https://vexere.com/vi-VN/ve-xe-khach-tu-sai-gon-di-da-lat-lam-dong-129t23991.html?utm_source=blogvxr&utm_campaign=SEO&utm_content=ha\" style=\"text-decoration-line: none;\"><strong>Xe từ Sài Gòn đi Đà Lạt</strong></a></p>\n\n<p style=\"text-align:center\"><strong><a href=\"https://vexere.com/vi-VN/ve-xe-khach-tu-da-lat-lam-dong-di-sai-gon-2399t1291.html?utm_source=blogvxr&utm_campaign=SEO&utm_content=ha\" style=\"text-decoration-line: none;\">Xe từ Đà Lạt đi Sài Gòn</a></strong></p>\n\n<div> </div>\n",
"english_description": "Dan Anh Limousine specializes in providing travel services, transporting customers from Saigon to Da Lat by Limousine Vip Bus",
},
"statisticsReview": {
"4": "1",
"detail_review": "2",
}
}
}
Request
- Path parameter
Parameter | Type | Required | Description |
---|---|---|---|
id | Integer | True | Bus operator id |
Response
Definitions | Type | Description |
---|---|---|
overall | Object | Overall rati |
overall.comp_id | Integer | Bus operator id |
rv_main_name | String | Name of review |
rv_main_value | String | Value of review |
label | String | Label review in Vietnamese |
label_english | String | Label review in English |
rating | Array[Object] | Each rating type. (Each object in rating has same info in overall) |
company_info | Object | Bus operator info |
company_info.name | String | Name of Bus operator |
company_info.full_name | String | Full name of Bus operator |
statisticsReview | Object | Number of each rating type |
statisticsReview.detail_review | String | Number of ratting without review |
Show rating and review
Webhook Integration Document | Tài liệu tích hợp Webhook
📌 Overview | Tổng quan
Our system will send webhook requests to the partner's configured URL.
Hệ thống sẽ gửi HTTP request (webhook) đến URL mà đối tác đã cấu hình.
📤 Webhook Request Format | Định dạng Webhook Request
🔗 HTTP Headers
Header | Description |
---|---|
x-signature |
HMAC-SHA256 signature used to verify the authenticity of the request body. |
Dùng để xác minh tính xác thực của dữ liệu webhook bằng thuật toán HMAC-SHA256.
📦 Request Body
There are two types of events:
Có hai loại sự kiện được gửi qua webhook:
ticket_updated
ticket_cancelled
1. ticket_updated
Sample Payload | Ví dụ dữ liệu cho sự kiện ticket_updated
{
"event_type": "ticket_updated",
"event_timestamp": "2025-04-08T11:33:18.302Z",
"booking_code": "WGU9AU7",
"payload": {
"list_updated_ticket": [
{
"ticket_id": 61374781,
"ticket_code": "SM3M1J",
"updated_trip_date": "2025-04-10T15:00:00.000Z",
"updated_pickup_date": "2025-04-10T03:00:00.000Z",
"updated_expected_pickup_time": "2025-04-10T03:00:00.000Z",
"last_trip_date": "2025-04-10T15:00:00.000Z",
"last_pickup_date": "2025-04-10T15:00:00.000Z",
"last_expected_pickup_time": "2025-04-10T03:00:00.000Z"
},
{
"ticket_id": "61374782",
"ticket_code": "SM3M1J",
"updated_trip_date": "2025-04-10T15:00:00.000Z",
"updated_pickup_date": "2025-04-10T03:00:00.000Z",
"updated_expected_pickup_time": "2025-04-10T03:00:00.000Z",
"last_trip_date": "2025-04-10T15:00:00.000Z",
"last_pickup_date": "2025-04-10T15:00:00.000Z",
"last_expected_pickup_time": "2025-04-10T03:00:00.000Z"
}
]
}
}
2. ticket_cancelled
Sample Payload | Ví dụ dữ liệu cho sự kiện ticket_cancelled
{
"event_type": "ticket_cancelled",
"event_timestamp": "2025-04-08T11:48:05.835Z",
"booking_code": "2AHQ73L",
"payload": {
"list_cancelled_ticket": [
{
"ticket_id": 61374796,
"ticket_code": "G5A768",
"cancel_fee": 305000,
"refund_amount": 0
}
]
}
}
🧾 Data Types | Định nghĩa kiểu dữ liệu
Common Fields | Trường chung
Property | Type | Description |
---|---|---|
event_type |
string | Type of event (ticket_updated or ticket_cancelled ) |
event_timestamp |
string | ISO 8601 timestamp of the event |
booking_code |
string | Code of the booking |
ticket_updated
Payload
Property | Type | Description |
---|---|---|
ticket_id |
number or string | ID of the ticket |
ticket_code |
string | Code of the ticket |
updated_trip_date |
string | New trip date (ISO 8601) |
updated_pickup_date |
string | New pickup date (ISO 8601) |
updated_expected_pickup_time |
string | New expected pickup time (ISO 8601) |
last_trip_date |
string | Last known trip date |
last_pickup_date |
string | Last known pickup date |
last_expected_pickup_time |
string | Last known expected pickup time |
ticket_cancelled
Payload
Property | Type | Description |
---|---|---|
ticket_id |
number | ID of the cancelled ticket |
ticket_code |
string | Code of the cancelled ticket |
cancel_fee |
number | Fee charged for cancellation |
refund_amount |
number | Amount refunded |
🔐 Signature Verification | Xác thực chữ ký
🔧 Algorithm: HMAC-SHA256
- Key: Partner’s
client_secret
- Data: A string constructed from body fields in a specific order.
🧱 String Construction Rules | Cách build string để hash
- Format:
key1=value1&key2=value2&...
- Fields with
null
value → convert to empty string. - For array fields, repeat the pattern for each item with order preserved.
✅ Fields for ticket_updated
event_type, event_timestamp, booking_code, payload.list_updated_ticket[index].ticket_id, payload.list_updated_ticket[index].ticket_code, payload.list_updated_ticket[index].updated_trip_date, payload.list_updated_ticket[index].updated_pickup_date, payload.list_updated_ticket[index].updated_expected_pickup_time, payload.list_updated_ticket[index].last_trip_date, payload.list_updated_ticket[index].last_pickup_date, payload.list_updated_ticket[index].last_expected_pickup_time
Example:
event_type=ticket_updated&
event_timestamp=2025-04-08T11:33:18.302Z&
booking_code=WGU9AU7&
payload.list_updated_ticket[0].ticket_id=61374781&
payload.list_updated_ticket[0].ticket_code=SM3M1J&
payload.list_updated_ticket[0].updated_trip_date=2025-04-10T15:00:00.000Z&
payload.list_updated_ticket[0].updated_pickup_date=2025-04-10T03:00:00.000Z&
payload.list_updated_ticket[0].updated_expected_pickup_time=2025-04-10T03:00:00.000Z&
payload.list_updated_ticket[0].last_trip_date=2025-04-10T15:00:00.000Z&
payload.list_updated_ticket[0].last_pickup_date=2025-04-10T15:00:00.000Z&
payload.list_updated_ticket[0].last_expected_pickup_time=2025-04-10T03:00:00.000Z&
payload.list_updated_ticket[1].ticket_id=61374782&
payload.list_updated_ticket[1].ticket_code=SM3M1J&
payload.list_updated_ticket[1].updated_trip_date=2025-04-10T15:00:00.000Z&
payload.list_updated_ticket[1].updated_pickup_date=2025-04-10T03:00:00.000Z&
payload.list_updated_ticket[1].updated_expected_pickup_time=2025-04-10T03:00:00.000Z&
payload.list_updated_ticket[1].last_trip_date=2025-04-10T15:00:00.000Z&
payload.list_updated_ticket[1].last_pickup_date=2025-04-10T15:00:00.000Z&
payload.list_updated_ticket[1].last_expected_pickup_time=2025-04-10T03:00:00.000Z
✅ Fields for ticket_cancelled
event_type, event_timestamp, booking_code, payload.list_cancelled_ticket[index].ticket_id, payload.list_cancelled_ticket[index].ticket_code, payload.list_cancelled_ticket[index].cancel_fee, payload.list_cancelled_ticket[index].refund_amount
Example:
event_type=ticket_cancelled&
event_timestamp=2025-04-08T11:48:05.835Z&
booking_code=2AHQ73L&
payload.list_cancelled_ticket[0].ticket_id=61374796&
payload.list_cancelled_ticket[0].ticket_code=G5A768&
payload.list_cancelled_ticket[0].cancel_fee=305000&
payload.list_cancelled_ticket[0].refund_amount=0
🧪 Verification Logic | Mô tả logic xác thực
- Partner builds the string from body using the order above.
- Hash it using
HMAC-SHA256
withclient_secret
. - Compare with
x-signature
in the request header.
✅ Expected Response | Phản hồi mong đợi từ đối tác
- HTTP Status Code:
200
- Response Body (JSON):
{ "code": "00", "message": "Webhook received" }
- If the response does not meet the above conditions (
code != '00'
or status ≠ 200), our system will retry up to 4 times.
🧷 Notes | Lưu ý
- Ensure your system can handle retries safely (idempotency).
- If the signature is invalid, the webhook should be rejected.
FAQ
English Version
- What are pick-up point, drop-off point, transshipment pick-up points, transshipment drop-off points?
- Pick-up point: an office/ ticket booth/ or place where a bus driver would stop to pick up passengers. This place may be the starting point or different places in the journeys. Pick-up point is often the starting point of a journey by default.
- Drop-off point: a place where the bus would stop to drop passengers off (this could be the bus ticket booth, office). Drop-off point is often the destination point of a journey by default.
- Transshipment pick-up points: places where the bus service provider would summon its current bus or any other vehicles (4 seats - 16 seats car, bike) to pick passenger up right at where they are. In this case, there may be no exact address, since it depends on the passenger’s demand or the bus provider’s resources.
- Transshipment drop-off points: places where the bus service provider would summon its current bus or any other vehicles (4 seats - 16 seats car, bike) to carry passengers to the places which they requested. In this case, there may be no exact address, since it depends on the passenger’s demand or the bus provider’s resources.
- Pay attention to these params of pick-up, drop-off, transshipment points
- min_customers: minimum customers count required to select that pick-up, drop-off point
- surcharge: surcharge fee when customer select that pick-up, drop-off point
- surcharge_type: 1 - Bus operator would collect this fee, 2 - Agent would collect this fee Default surcharge_type is 1. Only consider surcharge_type when surcharge > 0.
- Unfixed_point: is that point fixed or not (0: unfixed, 1: fixed). Allow customer to enter the address only in case 1.
- Using id to book a ticket, not point_id, even when id = 0 (point_id is used to check that point ‘s info only (long, lat)).
- While booking ticket, you have to provide either pick-up point (pair of parameters pickup_id and pickup) or transshipment pick-up point (pair of parameters transfer_id and transfer) information via
Booking one and two way ticket
API. - How long is the ticket expiry time?
- Ticket expiry time is 15 minutes
- How to display the ticket cancellation policy in the booking UI?
- There’re both from and to: From {{ from }} to {{ to }} hours before departure time
- There’s only from: {{ from }} hours before departure time
- There’s only to: In {{ to }} hours before departure time
- If from == 0: cancel fee is always {{ fee }}
- Example:
-
from: "0", to: "48", fee: "80", currency: "1", disable_cancel: false, currency_description: "%", cancelable: true
- In 48 hours before departure time: 80% cancelation fee
- How to display the ticket cancellation policy in the ticket cancellation UI?
- There’re both pre_time and time: From {{ pre_time }} to {{ time }} minutes before departure time
- There’s only pre_time: {{ pre_time }} minutes before departure time
- There’s only time: In {{ to }} minutes before departure time
- If pre_time == 0: cancel fee is always {{ fee }}
- Example:
-
"rule": 1, "cancel_fee": 40000, "time": 60, "type": 1, "value": 50, "pre_time": 0, "is_selected": false, "cancelable": true
- In 60 minutes before departure time: 50% cancelation fee or 40000 VNĐ
- How to add filter pickup_points and dropoff_point?
- When call API [Get the number of trips](/#get-the-number-of-trips) you will have response like this:
-
"pickup_points": [ { "district": "Bình Thạnh", "trip_count": 147, "points": [ { "name": "Bến Xe Miền Đông - Quầy vé 49", "trip_count": 15 } ] }, { "district": "Tân Bình", "trip_count": 147, "points": [ { "name": "Bệnh viện Phụ sản Mê Kông", "trip_count": 15 } ] } ], "dropoff_points": [ { "district": "Pleiku", "trip_count": 26, "points": [ { "name": "Bến xe Đức Long Gia Lai", "trip_count": 15 } ] }, ]
- If you want to filter the pickup "Bến Xe Miền Đông - Quầy vé 49" you need add info of district and name of it to params filter like this:
-
filter[pickup_points][0][district]=Bình Thạnh&filter[pickup_points][0][name]=Bến Xe Miền Đông - Quầy vé 49
- If you want to filter the pickup district "Bình Thạnh" you need add info of district to params filter like this:
-
filter[pickup_points][0][district]=Bình Thạnh
- If you want to filter 2 pickups "Bến Xe Miền Đông - Quầy vé 49" and "Bệnh viện Phụ sản Mê Kông" you need add info of district and name of it to params filter like this:
-
filter[pickup_points][0][district]=Pleiku&filter[pickup_points][0][name]=Bến Xe Miền Đông - Quầy vé 49&filter[pickup_points][1][district]=Tân Bình&filter[pickup_points][1][name]=Bệnh viện Phụ sản Mê Kông
- The filter dropoff_points is same to pickup_points
- Why is the ID in Area APIs responsed with datatype STRING while it needs to be NUMBER?
- When will the popup "Seat is finally handed out at a first-come-first-served basis" be showed?
- Handle booking flow for seats have multiple fare options?
- Why
Number
datatype fields in response definition sometimes response inString
datatype? - What is formula for total price of each ticket?
First, rely on the cancelable
field from the Get refund mechanism
API. If its value is false
, ticket(s) cannot be canceled, otherwise follow the instructions below.
Below is refundList item:
Because that ID's datatype is BIGINT in database. BIGINT maximum value is 2^63-1, javascript can safely represent up to 2^53. To be on the safe side libraries (Sequelize) return those numbers as strings.
There is a field 'unchoosable' in response of the API 'Get the list of trips /v2/route'. When this field is 1, that popup will show up
How to handle booking flow for this type of trip? For example, the trip's seat map has 2 groups of fare: 100,000 VNĐ and 200,000 VNĐ. The customer wants to book 2 tickets priced at 100,000 VNĐ and 3 tickets priced at 200,000 VNĐ. In this case, you should randomly select out 2 seats from the seat group priced at 100,000 VNĐ and 3 seats from the seat group priced at 200,000 VNĐ. Of course, those seats must be available. Then call the API normally with those randomized seats.
If there is coach_seat_template[index].seats[index_2].seat_groups
field in a seat in response of API 'Get seat map /v3/trip/seat_map', this seat has multiple fare options.
Each element in coach_seat_template[index].seats[index_2].seat_groups
array contains information about each fare option (Please pay attention to the coach_seat_template[index].seats[index_2].seat_groups[index_3].seat_group_id
field, it will be important in the ticket booking APIs).
To specify seat's fare option in ticket booking APIs, put the coach_seat_template[index].seats[index_2].seat_groups[index_3].seat_group_id
's value to the end of seat's full code.
For example, this seat below is a seat has multiple fare options (400.000 VNĐ or 600.000 VNĐ). If customer select 400.000 VNĐ fare option, the full code of seat in the request's body of ticket booking APIs now become 'A1|1|1|1|5957' (5957 is seat_group_id
of 400.000 VNĐ fare option). Similarly, the full code of seat for 600.000 VNĐ fare option is 'A1|1|1|1|5955'. If no option is specified (full code of seat in the request's body is 'A1|1|1|1'), the fare option with highest fare will be selected implicitly.
{ "seat_type": 7, "seat_number": 0, "seat_code": "A1", "row_num": 1, "col_num": 1, "full_code": "A1|1|1|1", "row_span": 1, "col_span": 1, "is_available": true, "seat_group_code": "DOI", "seat_group_id": 5955, "seat_group": "Giường đôi 2 người nằm", "seat_group_english": "couple for 2", "fare": 600000, "seat_color": "#FF1F1F", "fares": { "original": 600000, "operator_discount": 0, "vexere_discount": 0 }, "seat_groups": [ { "seat_group_code": "DOI2", "seat_group_id": 5957, "seat_group": "Giường đôi 1 người nằm", "seat_group_english": "couple for 1", "fare": 400000, "seat_color": "#ffe635", "fares": { "original": 400000, "operator_discount": 0, "vexere_discount": 0 } }, { "seat_group_code": "DOI", "seat_group_id": 5955, "seat_group": "Giường đôi 2 người nằm", "seat_group_english": "couple for 2", "fare": 600000, "seat_color": "#FF1F1F", "fares": { "original": 600000, "operator_discount": 0, "vexere_discount": 0 } } ] }
Because of system reasons, Number
datatype fields are sometimes converted to String
datatype. It's better to always cast those fields to Number
datatype.
exact_fare_per_ticket = fare - discount - vxr_discount_value + eating_fare + surcharge + pickup_surcharge + transfer_surcharge + drop_off_surcharge + arrive_transfer_surcharge
Vietnamese Version
- Thế nào là điểm đón, trả, trung chuyển đón, trung chuyển trả?
- Điểm đón: là văn phòng / quầy vé / địa điểm nhà xe có thể dừng xe để đón khách, đây có thể là nơi xe khởi hành cũng có thể là điểm trên lộ trình xe đi. Thường điểm đón mặc định là điểm đón đầu chuyến.
- Điểm trung chuyển đón: là những khu vực nhà xe có thể dùng chính xe chở khách hoặc các phương tiện khác như xe 4 chỗ - 16 chỗ, xe máy để đến tận nơi đón khách. Các địa điểm này thường không có địa chỉ chính xác mà tùy thuộc vào nhu cầu của khách & khả năng của nhà xe mà nhà xe sẽ bố trí vị trí đón thích hợp.
- Điểm trả: là những địa điểm trên lộ trình xe đi mà xe có thể trả khách hoặc là văn phòng/quầy vé của nhà xe. Điểm trả mặc định là điểm cuối chuyến.
- Điểm trung chuyển trả: là những khu vực nhà xe có thể dùng chính xe chở khách hoặc các phương tiện khác như xe 4 chỗ - 16 chỗ, xe máy để trả khách tận nơi. Các địa điểm này thường không có địa chỉ chính xác mà tùy thuộc vào nhu cầu của khách & khả năng của nhà xe mà nhà xe sẽ bố trí vị trí trả khách thích hợp.
- Các điểm nào cần chú ý trên các điểm đón, trả, trung chuyển?
- min_customers: Số khách tối thiểu để chọn điểm đón (trả) đó.
- surcharge: Số tiền phụ thu khi khách chọn điểm đón (trả) đó.
- surcharge_type: Loại phụ thu (1 - nhà xe thu, 2 - thu trực tiếp khách) Chỉ khi nào surcharge > 0 mới xét surcharge_type vì surcharge_type luôn mặc định là 1.
- unfixed_point: Điểm có cố định hay không. (0 - cố định, 1 - không cố định) Chỉ khi là 1 mới cho khách nhập địa chỉ.
- Khi đặt vé dùng id để đặt vé, không dùng point_id, kể cả khi id = 0 (point_id chỉ để check thông tin điểm (long, lat, ...)).
- Khi đặt vé, cần phải cung cấp hoặc là thông tin điểm đón (cặp tham số pickup_id và pickup) hoặc là thông tin điểm trung chuyển đón (cặp tham số transfer_id và transfer) thông qua API
Đặt vé 1 và 2 chiều
. - Thời gian giữ vé là bao lâu?
- Thời gian giữ vé là 15p.
- Cách hiển thị chính sách hủy vé tại màn hình đặt vé?
- Nếu có from và to: Từ {{ from }} đến {{ to }} tiếng trước giờ khởi hành
- Nếu chỉ có from: Trước {{ from }} tiếng trước giờ khởi hành
- Nếu chỉ có to: Trong vòng {{ to }} tiếng trước giờ khởi hành
- Nếu from == 0: Hủy lúc nào thì phí cũng là {{ fee }}
- Ví dụ:
-
from: "0", to: "48", fee: "80", currency: "1", disable_cancel: false, currency_description: "%", cancelable: true
- Trong vòng 48 tiếng trước giờ khởi hành phí hủy: 80 %
- Cách hiển thị chính sách hủy vé tại màn hình hủy vé?
- Nếu có cả pre_time và time: Từ {{ pre_time }} đến {{ time }} phút trước giờ khởi hành
- Nếu chỉ có pre_time: Trước {{ pre_time }} phút trước giờ khởi hành
- Nếu chỉ có time: Trong vòng {{ to }} phút trước giờ khởi hành
- Nếu pre_time == 0: Hủy lúc nào thì phí cũng là {{ cancel_fee }}
- Example:
-
"rule": 1, "cancel_fee": 40000, "time": 60, "type": 1, "value": 50, "pre_time": 0, "is_selected": false, "cancelable": true
- Trong vòng 60 phút trước giờ khởi hành: phí hủy là 50% hay 40000 VNĐ
- Làm thế nào để thêm filter pickup_points và dropoff_point?
- Khi call API [Get the number of trips](/#get-the-number-of-trips) bạn sẽ nhận được thông tin response trả về như:
-
"pickup_points": [ { "district": "Bình Thạnh", "trip_count": 147, "points": [ { "name": "Bến Xe Miền Đông - Quầy vé 49", "trip_count": 15 } ] }, { "district": "Tân Bình", "trip_count": 147, "points": [ { "name": "Bệnh viện Phụ sản Mê Kông", "trip_count": 15 } ] } ], "dropoff_points": [ { "district": "Pleiku", "trip_count": 26, "points": [ { "name": "Bến xe Đức Long Gia Lai", "trip_count": 15 } ] }, ]
- Nếu bạn muốn lọc "Bến Xe Miền Đông - Quầy vé 49" bạn cần thêm lọc quận và tên của điểm đón như sau:
-
filter[pickup_points][0][district]=Bình Thạnh&filter[pickup_points][0][name]=Bến Xe Miền Đông - Quầy vé 49
- Nếu bạn muốn lọc quận "Bình Thạnh" bạn cần thêm thông tin như sau:
-
filter[pickup_points][0][district]=Bình Thạnh
- Nếu bạn muốn lọc 2 điểm đón "Bến Xe Miền Đông - Quầy vé 49" và "Bệnh viện Phụ sản Mê Kông" bạn cần thêm lọc quận và tên của điểm đón như sau:
-
filter[pickup_points][0][district]=Pleiku&filter[pickup_points][0][name]=Bến Xe Miền Đông - Quầy vé 49&filter[pickup_points][1][district]=Tân Bình&filter[pickup_points][1][name]=Bệnh viện Phụ sản Mê Kông
- Cách lọc dropoff_points giống với cách lọc pickup_points
- Tại sao field ID trong nhóm API Area lại trả về kiểu STRING trong khi thực tế nó phải lại kiểu NUMBER?
- Khi nào thông báo 'Việc sắp xếp ghế khi khách ra xe sẽ do nhà xe quyết định' sẽ hiển thị?
- Xử lý luồng đặt vé đối với các ghế có nhiều lựa chọn về giá?
- Tại sao các field được định nghĩa là kiểu
Number
trong response đôi khi lại response với kiểuString
?
Trước tiên, hãy dựa vào giá trị của field cancelable
ở API Get refund mechanism
. Nếu giá trị của nó là false
, thì (các) vé này không được phép hủy, nếu không thì làm theo các chỉ dẫn dưới đây.
Dưới đây là chi tiết item của field refundList
Vì field ID đó được lưu kiểu BIGINT trong database. Kiểu BIGINT có giá trị max là 2^63-1 và trong javascript chỉ có thể biểu diễn tối đa tới giá trị 2^53. Vì vậy nên để tránh gây ra lỗi nên Sequelize đã parse field đó về STRING.
Trong API 'Get the list of trips /v2/route' có 1 field 'unchoosable'. Khi field này là 1 thì thông báo trên sẽ được hiện.
Xử lý luồng đặt vé với chuyến có 'unchoosable' = 1 như thế nào? Ví dụ, sơ đồ ghế của chuyến có 2 nhóm giá: 100,000 VNĐ và 200,000 VNĐ. Khách hàng muốn đặt 2 vé có giá 100,000 VNĐ và 3 vé có giá 200,000 VNĐ. Ở trường hợp này, bạn sẽ chọn ngẫu nhiên 2 ghế từ nhóm giá 100,000 VNĐ và 3 ghế từ nhóm giá 200,000 VNĐ. Tất nhiên là những ghế đó phải đang còn trống. Sau đó sử dụng các ghế vừa chọn nhẫu nhiên trên để gọi API một cách bình thường.
Nếu ghế nào có field coach_seat_template[index].seats[index_2].seat_groups
trong response của API 'Get seat map /v3/trip/seat_map' có nghĩa là ghế đó có nhiều sự lựa chọn về giá.
Mỗi một phần tử trong mảng coach_seat_template[index].seats[index_2].seat_groups
là thông tin về mỗi lựa chọn về giá ghế (Chú ý field coach_seat_template[index].seats[index_2].seat_groups[index_3].seat_group_id
sẽ phục vụ việc chỉ định lựa chọn giá ghế trong các API đặt chỗ).
Để chỉ định lựa chọn về giá ghế trong các API đặt chỗ, Đặt giá trị của field coach_seat_template[index].seats[index_2].seat_groups[index_3].seat_group_id
vào cuối full code của ghế.
Ví dụ, JSON object bên dưới là data của một ghế có nhiều lựa chọn về giá (giá 400.000 VNĐ hoặc giá 600.000 VNĐ). Nếu khách lựa chọn giá 400.000 VNĐ, full code của ghế trong request của API đặt chỗ sẽ là 'A1|1|1|1|5957' (5957 là seat_group_id
của lựa chọn giá ghế 400.000 VNĐ). Tương tự như vậy, full code của ghế cho lựa chọn giá ghế 600.000 VNĐ là 'A1|1|1|1|5955'. Nếu không chỉ định lựa chọn giá ghế nào (full code của ghế trong request là 'A1|1|1|1'), thì VXR sẽ ngầm hiểu là lựa chọn giá ghế cao nhất.
{ "seat_type": 7, "seat_number": 0, "seat_code": "A1", "row_num": 1, "col_num": 1, "full_code": "A1|1|1|1", "row_span": 1, "col_span": 1, "is_available": true, "seat_group_code": "DOI", "seat_group_id": 5955, "seat_group": "Giường đôi 2 người nằm", "seat_group_english": "couple for 2", "fare": 600000, "seat_color": "#FF1F1F", "fares": { "original": 600000, "operator_discount": 0, "vexere_discount": 0 }, "seat_groups": [ { "seat_group_code": "DOI2", "seat_group_id": 5957, "seat_group": "Giường đôi 1 người nằm", "seat_group_english": "couple for 1", "fare": 400000, "seat_color": "#ffe635", "fares": { "original": 400000, "operator_discount": 0, "vexere_discount": 0 } }, { "seat_group_code": "DOI", "seat_group_id": 5955, "seat_group": "Giường đôi 2 người nằm", "seat_group_english": "couple for 2", "fare": 600000, "seat_color": "#FF1F1F", "fares": { "original": 600000, "operator_discount": 0, "vexere_discount": 0 } } ] }
Vì một số lý do trong hệ thống, trường hợp trên đôi khi sẽ xuất hiện. Vì vậy, tốt nhất nên luôn luôn ép kiểu các field đó về kiểu Number
.
Route API Error Code
Error code is returned in http status code - 200: success - 401: unauthorized - others: error
Booking API Error Code
code | codeError | message | vietnamese meaning message | type |
---|---|---|---|---|
3100 | INVALID_PARAMETER | Invalid Parameter | Tham số không hợp lệ | BAD_REQUEST |
3101 | INVALID_BOOKING_CODE | Invalid Booking Code | Mã đặt chỗ không hợp lệ | BAD_REQUEST |
3102 | INVALID_TRANSACTION_ID | Invalid Transaction Id | Id giao dịch không hợp lệ | BAD_REQUEST |
3103 | INVALID_COMPANY_ID | Invalid Company Id | Id nhà xe không hợp lệ | BAD_REQUEST |
3104 | INVALID_TRIP_ID | Invalid Trip | Trip id không hợp lệ | BAD_REQUEST |
3110 | INVALID_COUPON | Invalid Coupon Code | Mã giảm giá không hợp lệ | BAD_REQUEST |
3115 | INVALID_TICKET_CODE | Invalid ticket code | Mã vé không hợp lệ | BAD_REQUEST |
3118 | INVALID_SEAT_CODE | Invalid seat code | Mã chỗ ngồi không hợp lệ | BAD_REQUEST |
3119 | INVALID_AREA | Invalid area | Địa điểm không hợp lệ | BAD_REQUEST |
3120 | INVALID_TRIP_CODE | Invalid trip code | Mã chuyến đi không hợp lệ | BAD_REQUEST |
3201 | BOOKING_NOT_FOUND | Booking Not Found | Không tìm thấy đặt chỗ | NOT_FOUND |
3203 | TRIP_NOT_FOUND | Trip Not Found | Không tìm thấy chuyến đi | NOT_FOUND |
3204 | TICKET_NOT_FOUND | Ticket Not Found | Không tìm thấy vé | NOT_FOUND |
3205 | AREA_NOT_FOUND | Area not found | Không tìm thấy địa điểm | NOT_FOUND |
3301 | BOOKING_PAID | Booking has been paid | Booking đã được thanh toán | BAD_REQUEST |
3302 | BOOKING_CANCELLED | Booking has been cancelled | Booking đã bị hủy | BAD_REQUEST |
3308 | TRIP_IS_NOT_BOOKABLE | Trip isn't configured for online booking | Chuyến đi không được định cấu hình để đặt chỗ trực tuyến | BAD_REQUEST |
3317 | BOOKING_EXPIRED | Booking has been expired | Booking đã hết hạn | BAD_REQUEST |
3403 | SEAT_IS_NOT_AVAILABLE | Seat is not available | Ghế không hợp lệ | BAD_REQUEST |
3413 | SEAT_IS_NOT_CANCELABLE | Seat is not able to cancel | Không thể hủy ghế | BAD_REQUEST |
3439 | TICKET_NOT_CANCELABLE | Ticket is not able to cancel | Không thể hủy vé | BAD_REQUEST |
3130 | INVALID_COUPON_APPLY | Channel not applicable | Kênh bán không áp dụng cho coupon | BAD_REQUEST |
3131 | INVALID_COUPON_SCOPE | Scope of application is not appropriate | Phạm vi áp dụng coupon không phù hợp | BAD_REQUEST |
3132 | INVALID_COUPON_DATE | Does not match departure date | Ngày khởi hành không hợp lệ | BAD_REQUEST |
3133 | INVALID_COUPON_BOOKING_DATE | Does not match booking date | Ngày đặt không hợp lệ | BAD_REQUEST |
3134 | INVALID_COUPON_MAX_NUM_OF_TICKET | Number of ticket is bigger than number of allowed | Số lượng vé lớn hơn số lượng cho phép | BAD_REQUEST |
3144 | INVALID_COUPON_MIN_NUM_OF_TICKET | Number of ticket is smaller than number of allowed! | Số lượng vé nhỏ hơn số lượng cho phép! | BAD_REQUEST |
3135 | INVALID_COUPON_MIN_AFFECT | Minimum value does not match | Giá trị tối thiểu đơn hàng chưa đủ | BAD_REQUEST |
3136 | INVALID_COUPON_EXPIRED | Coupon is not exist or expired | Phiếu giảm giá không tồn tại hoặc đã hết hạn | BAD_REQUEST |
3137 | INVALID_CAMPAIGN_EXPIRED | Campaign is not exist or expired | Chiến dịch không tồn tại hoặc đã hết hạn | BAD_REQUEST |
3138 | INVALID_COUPON_USED | Coupon has been used | Phiếu giảm giá đã được sử dụng | BAD_REQUEST |
3139 | INVALID_COUPON_SCOPE_ROUTE | Does not apply the right Route | Lộ trình tuyến đường không hợp lệ | BAD_REQUEST |
3140 | INVALID_COUPON_SCOPE_COMPANY | Does not apply the right Bus Operator | Nhà xe không hợp lệ | BAD_REQUEST |
3153 | INVALID_PICKUP_OR_DROP_OFF_POINT_INFO | Specific address is required for unfixed point (pickup, drop-off, transfer info) | Cần nhập địa chỉ cụ thể với điểm đón, trả, trung chuyển không cố định | BAD_REQUEST |
3427 | COUPON_NOT_FOUND | Coupon not found | Không tìm thấy phiếu giảm giá | BAD_REQUEST |
3473 | COUPON_IS_NOT_APPLICABLE | Coupon cannot be applied to new booking | Phiếu giảm giá không thể áp dụng cho đặt chỗ mới | BAD_REQUEST |
3141 | INVALID_APPLY_COUPON_BOOKING_STATUS | Booking was paid or cancelled | Đặt chỗ đã được thanh toán hoặc bị hủy | BAD_REQUEST |
3466 | INVALID_REVIEW_EXPIRED | Review is not exist or expired! | Đánh giá không tồn tại hoặc đã hết hạn! | BAD_REQUEST |
3467 | REVIEW_RATING_ERROR_SUBMIT | Have error in transaction! | Có lỗi xảy ra, vui lòng thử lại ! | BAD_REQUEST |
3468 | REVIEW_RATING_BOOKING_CODE_NOT_FOUND | booking_code not found! | không tìm thấy mã đặt chỗ! | BAD_REQUEST |
3469 | REVIEW_RATING_BOOKING_CODE_CONFLICT | Booking code already exists! | Mã đặt chỗ đã tồn tại! | BAD_REQUEST |
3497 | INVALID_MIN_CUSTOMER_POINT | The number of seat must be greater than or equal to min customer at this point | Số ghế không được nhỏ hơn số lượng khách tối thiểu của địa điểm này | BAD_REQUEST |
3498 | INVALID_SURCHARGE_POINT | The surcharge at this point must be equal to the current point | Chỉ có thể chọn địa điểm có cùng mức phụ thu | BAD_REQUEST |
What new in our docs ?
Day | New Infomation |
---|---|
06-05-2020 |
|
07-05-2020 | Add FAQ to docs |
18-06-2020 | Fix require or not in API Booking ticket and API Get the list of trip |
26-06-2020 | Add Phuong Trang info in API Booking ticket and API Get seat map |
21-08-2020 | Add new filter in API Get the list of trip |
03-09-2020 | Add info when book round trip Booking two way ticket |
04-09-2020 | Add info when review bus operator Review bus operator |
09-09-2020 | Add image of Review bus operator and new Error code |
22-09-2020 | Add Amentity API Amenity and filter pickup_points (dropoff_points) in API Get the list of trip |
Dynamic Link
Gen dynamic link
curl --location 'https://vconfiguration.vexere.com/dynamic_link' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic bWFzb2ZmZXI6REhRdXRJNVd1WXJK' \
--data '{
"aid": 180,
"click_id": "123123123123"
}'
var request = require('request');
var auth = new Buffer(user + ':' + pass).toString('base64');
var options = {
'method': 'POST',
'url': 'https://vconfiguration.vexere.com/dynamic_link',
'headers': {
Authorization: 'Basic ' + auth,
'Content-Type': 'application/json'
},
body: {
"aid": 180,
"click_id": "123123123123",
"utm_source": "something..."
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
The above command returns JSON structured like this:
{
"message": "success",
"data": {
"shortLink": "https://vexere.page.link/55PpCyYoAZBKrwg6A",
"previewLink": "https://vexere.page.link/55PpCyYoAZBKrwg6A?d=1"
}
}
Parameter
Parameter | Type | Required | Description |
---|---|---|---|
aid | Integer | false | là aid hằng số được vxr cấp |
click_id | string | true | dựa theo aff |
utm_source | String | false | tùy ý |
Response
Definitions | Type | Description |
---|---|---|
data.shortlink | string | Dynamic link return |
Webview
Overview
Purpose
Document describes the integration between Vexere and Agent. This webview can:
- Completely allow customers to book ticket from Vexere platform
- Pay to agent's system
Scope
The document briefly describes the connection model, sequence diagrams, and APIs related to the connection between the two systems
Related Document
Agent's connection information is emailed by Vexere
Terms
No. | Name | Description |
---|---|---|
1 | URL | Used to refer to resources on the Internet. |
2 | MAC | MAC (Message Authentication Code) is a message authentication code that ensures data integrity |
3 | HMAC | HMAC or Hash-based MAC is a function used to implement MAC mechanism |
4 | SHA-256 | SHA-256 is a 256-bit secure hashing algorithm and is used to create unique and irreversible hashing functions. |
5 | Signature | Information goes with data to ensure data is not changed |
Data Encryption
The transmitted data must be encrypted to protect customer transaction information
Shared Secret key
Agent will be provided by Vexere a Shared Secret Key to use for checking data
Creating signature
Vexere uses HMAC-SHA256 to create signature
Signature will be sent with Data to agent
Signature confirmation
After receiving data, agent needs to check that data is secured
- Using the data received from Vexere, recalculate the Signature with HMAC-SHA256 with Shared Secret Key
- Data is secured only if the calculated signature of agent (calculate from above step) is the same with Vexere Signature received from Vexere
Integrate Process
The integrate process to Vexere system includes the following steps:
Step 1: Agent provides agent's document to Vexere:
Vexere account's on agent's system
Agent's integration document
Step 2: After receiving the information from agent, Vexere will create an agent account and send the following information to agent:
Vexere webview link
Vexere's integration document
Step 3: Integrate and reconcile
Webview Flow
Webview Booking Flow
Cancel Ticket Flow
Webview Layout
Ticket searching page
Route page
Detail Integration Process
Webview Initiation
- Vexere provides a link to vexere's webview for agent.
- Agent uses this link to display UI on agent's application.
- Ticket-booking is performed on this webview.
- When customers pay, the webview will send an event to notify
Payment event
// for iframe embed
window.addEventListener("message", event => {
if (event.origin.startsWith("https://agentwebview.vexere.com")) {
var data = event.data;
switch (data.key) {
case "PAY": { // At this step, the booking is reserved, you (bank, wallet, Vxr's partner) need to charge user for booking amount
// Process payment here: the booking code is: data.booking_code
// Step 1: get amount_booking from booking info API https://vdoc.vexere.net/#get-booking-information
// Step 2: charge user amount_booking at your side
// Step 3: call to pay API https://vdoc.vexere.net/#pay (hach toan) if user paid successfully
// Step 4: redirect user to homepage https://uat-agentwebview.vexere.net/agent/webview/home?client_id={client_id}
break;
}
default:
break;
}
}
});
// for IOS
var mNativeToWebHandler : String = “jsMessageHandler”
mWebKitView.configuration.userContentController.add(self, name: mNativeToWebHandler)
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == mNativeToWebHandler {
print("message: \(message.body)")
}
}
// for Android
class JSBridge(){
@JavascriptInterface
fun showMessageInNative(message:String){
//Received message from webview in native, process data
}
}
mWebViewComponent.settings.javaScriptEnabled = true
mWebViewComponent.addJavascriptInterface(JSBridge(),"JSBridge")
// for iframe embed
window.addEventListener("message", event => {
if (event.origin.startsWith("https://agentwebview.vexere.com")) {
var data = event.data;
switch (data.key) {
case "PAY": { // At this step, the booking is reserved, we need charge user for booking amount
// Process payment here
// Step 1: the booking code is: data.booking_code
// Step 2: get amount_booking from booking info API https://vdoc.vexere.net/#get-booking-information
// Step 3: charge user amount_booking
// Step 4: if charge user successfully, call pay API https://vdoc.vexere.net/#pay (hach toan)
// Step 5: redirect user to homepage https://uat-agentwebview.vexere.net/agent/webview/home?client_id={client_id}
break;
}
default:
break;
}
}
});
// for IOS native
// reference: https://developer.apple.com/documentation/webkit/wkscriptmessage
var mNativeToWebHandler : String = “jsMessageHandler”
mWebKitView.configuration.userContentController.add(self, name: mNativeToWebHandler)
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == mNativeToWebHandler {
print("message: \(message.body)")
}
}
// for Android native
// reference: https://developer.android.com/develop/ui/views/layout/webapps/webview
class JSBridge(){
@JavascriptInterface
fun showMessageInNative(message:String){
//Received message from webview in native, process data
}
}
mWebViewComponent.settings.javaScriptEnabled = true
mWebViewComponent.addJavascriptInterface(JSBridge(),"JSBridge")
Description
- After receiving payment request, Vexere will send an event to notify to agent to charge customer fee.
- Agent listens to this event and processes payment
Look on the right side in javascript tab to see example code for catching event from webview
Document
Type: Message
Event Data Explanation:
Field | Type | Description |
---|---|---|
type | string | Event Type |
data.booking_code | string | Vexere booking code identifier |
data.amount | number | The total amount the agent needs to pay |
data.timestamp | number | The moment webview starts sending this event, is in milisecond unit |
data.signature | string | Signature is created from Data encryption order by data.signed_field_names with query string format |
data.signed_field_names | string | The order of input data for Data encryption |
Example
- Event data Look on the right side to see example data
{
"type": "PAY",
"data": {
"amount": 220000,
"booking_code": "F5I4MJB",
"signature": "cd8fa6fee1c12cb087e572a886a9171bf796c4f1388b6f8d87182e0e4e4ef638",
"signed_field_names": "booking_code,amount,timestamp",
"timestamp": 1585648362535
}
}
After receiving the above data, agent call
Get booking information
API for booking's informationProcess payment with booking's information above (The value of the
amount_booking
field is the amount that customer needs to pay).
Payment API
After payment, agent must send an request to this API to update ticket status (to be paid)
Authentication before using this API
Get Ticket Information API
Allow agent to retrieve the details of booked tickets
Authentication before using this API
Canceling ticket API
Allow agent to cancel booked/paid tickets
Authentication before using this API
Testing Information
This is agent information for testing on vexere's UAT environment
Account
key | value |
---|---|
vxr_lang | vi or en, default: vi |
client_id | 63950932-a8a3-40b6-bf17-b49d29d7789f |
client_secret | 50dcca4f-1caf-45fa-be52-834ba11b31cb |
shared_secret_key | +MbPeShVmYq3t6w9z$C&F)J@NcRfTjWnZr4u7x!A%D*G-KaPdSgVkXp2s5v8y/B? |
Webview Link
UAT
https://uat-agentwebview.vexere.net/agent/webview/home?client_id={client_id}
Production
https://agentwebview.vexere.com/agent/webview/home?client_id={client_id}