Skip to main content

Airport transfer

Airport pickups and drop-offs. Discovery is a live search against supplier availability; each result is a priced, bookable offering with its own quote.

1 · Find the locations

GET /api/v1/airport-transfer/locations?q=KLIA

No API key required. Returns the code values you search with:

[
{ "code": "KUL-T1", "name": "KLIA Terminal 1", "kind": "AIRPORT" },
{ "code": "KUL-T2", "name": "KLIA Terminal 2", "kind": "AIRPORT" }
]
POST /api/v1/airport-transfer/search
{
"originCode": "KUL-T1",
"destCode": "KL-SENTRAL",
"travelAt": "2026-09-12T06:30:00Z",
"paxAdult": 2,
"paxChild": 0,
"luggage": 1
}

Each offering carries a quoteId and a sellAmount, and lives 15 minutes:

{
"offerings": [
{
"quoteId": 90188,
"offeringRef": "at|KUL-T1|KL-SENTRAL|PRIVATE|budget-day",
"productName": "Budget (Day)",
"mode": "TAXI",
"direction": "OUTBOUND",
"sellAmount": 48.00,
"sellCurrency": "MYR",
"travelAt": "2026-09-12T06:30:00Z",
"expiresAt": "2026-09-12T05:45:00Z"
}
]
}

direction is relative to the airport: INBOUND is toward it, and has genuinely scarce inventory with an 8-hour booking cutoff. OUTBOUND is treated as always available.

3 · Book

POST /api/v1/bookings
{
"idempotencyKey": "a1f4c2e0-77b2-4c31-9c2e-6b1f0a9d3e55",
"items": [{
"quoteId": 90188,
"details": {
"travelAt": "2026-09-12T06:30:00Z",
"paxAdult": 2, "paxChild": 0, "luggage": 1,
"flightNo": "AK6042",
"pickupAddress": "KLIA Terminal 1, Arrival Hall, Door 5",
"passengerFirstName": "Xin", "passengerLastName": "Tan",
"passengerContactNo": "60123456789",
"passengerEmailAddress": "xin@example.com",
"passengerNationality": "MY",
"emergencyFirstName": "Jane", "emergencyLastName": "Tan",
"emergencyContactNo": "60129876543"
}
}]
}

The details bag

FieldRequiredNotes
travelAtyesMust be the instant you searched with — a different value books a different trip than you priced
paxAdult, paxChildyesSummed into the supplier's pax count
luggageyesForwarded as the medium-luggage count
passengerFirstName, passengerLastName, passengerContactNo, passengerEmailAddress, passengerNationalityyesThe supplier rejects an incomplete passenger
emergencyFirstName, emergencyLastName, emergencyContactNoyesSame
flightNonoSnapshotted for operations and support
pickupAddressnoForwarded to the supplier — what the driver actually reads
pickupLatitude, pickupLongitudenoForwarded alongside the address
passengersnoFree-form list, stored with the booking

The eight passenger and emergency fields are validated before any money moves, so a missing one costs nothing: 400, naming every field you left out.

4 · Deliver the coupon

"detail": {
"type": "TAXI_COUPON",
"coupons": [{
"couponNo": "TC-9",
"qrCode": "2,TC-9,gohub,budget-day",
"expiredDate": "2026-09-12T14:30:00",
"taxiTypeName": "Budget (Day)",
"price": 48.00
}]
}
qrCode is the ride

It is what the driver scans. Forward it to your customer — without it there is no trip. It is also mirrored as the item's redemptionRef.

supplierBookingRef is the supplier's own booking number; quote it in supplier-side support.

Round trips

Two searches, two quotes, two items in one order. Each leg gets its own details bag with its own travelAt.