Introduction
Welcome to the Hornblower API!! You can use our API to access Hornblower API endpoints.
We have language bindings in JavaScript! You can view code examples in the dark area to the right.
This document describes the standards used to establish connectivity between a Hornblower API and your system.
Authentication
Access control is achieved using HTTP’s basic access authentication. Hornblower expects for the Token to be included in API requests to the Hornblower API in a header that looks like the following:
Authorization: Basic MTM3Nzc1OmpmZGQzamdyc3NmZXdmcmZycmU4Zg==
Format
Request Format
Example
const url = "https://devshop.hornblower.com/api";
const res = await fetch(url, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: "Basic yourToken",
},
body: payload,
method: "POST",
});
The hornblower API expects regular HTTPS requests that contain data as JSON formatted payloads as per specifications. It is important that the HTTP Content-type header is set to all requests.
Please note as well that we always return a 200 HTTP status code, as long as the response contains an expected payload (this includes error codes).
Datetime Format
Points in time are expressed as strings using the ISO 8601 datetime format.
Example: 2019-10-30T18:30:00-07:00
We always expect the local time with its timezone as UTC offset.
Example:
hbsdogco_53
Ticket in San Francisco for the 30th of October 2019 at 18:30 (local time):
Expected:
2019-10-30T18:30:00-07:00
Not expected:
2019-10-30T21:30:00-04:00 / 2019-10-31T01:30:00-00:00
Endpoint
Tours
Get Tours Example
const apiUrl = "https://devshop.hornblower.com/api/gyg/1/get-tours";
const res = await fetch(apiUrl, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
method: "GET",
});
The above command returns JSON structured like this:
{
"data": {
"tours": [
{
"name": "Alcatraz Day Tour",
"productId": "hacco_1000016"
},
{
"name": "Chicago Seadog Lakefront Speedboat Tour",
"productId": "hbsdogco_53"
},
{
"name": "San Francisco Dinner Cruise",
"productId": "hbsdogco_53"
}
]
}
}
You can call this endpoint in order to get all available tours. Please contact us to set up tours for you if you don't see any tours returned.
Request sample
GET https://devshop.hornblower.com/api/gyg/1/get-tours
Pick Up Location List
Get Pick Up Location List Example
const apiUrl = `https://my.hornblower.com/api/gyg/1/get-pickupLocationList/?${productId}`;
const res = await fetch(apiUrl, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
method: "GET",
});
The above command returns JSON structured like this:
{
"data": {
"pickupLocationList": [
{
"address": "3475 S Las Vegas Blvd, Las Vegas, NV 89109, USA",
"latitude": "36.1194161",
"longitude": "-115.1707592",
"locationName": "Casino Royale (Best Western Plus)",
"hotelLocationId": "5893b243-87af-4d07-9acd-35620cf939f8",
"minutesPrior": "70",
"pickupInstructions": "Next door at Harrah's - outside of the Bus Depot"
},
{
"address": "3535 S Las Vegas Blvd, Las Vegas, NV 89109, USA",
"latitude": "36.1181779",
"longitude": "-115.1713151",
"locationName": "The LINQ",
"hotelLocationId": "5b3aa17b-85d2-442c-853d-b1b4e5da4a9e",
"minutesPrior": "70",
"pickupInstructions": "Next door at Harrah's - outside the Bus Depot"
}
]
}
}
You can call this endpoint in order to get all available pick up locations for each product.
Request sample
GET https://devshop.hornblower.com/api/gyg/1/get-pickupLocationList/?productId=mavlv_1108456
Parameter | Type | Description |
---|---|---|
productId | String | The ID of the requested product in the hornblower’s system. |
Response sample
Fields | Type | Description |
---|---|---|
address | String | The address of the pick up location |
latitude | String | The latitude of the pick up location |
longitude | String | The longitude of the pick up location |
locationName | String | The name of the pick up location |
hotelLocationId | String | The id of the pick up location |
minutesPrior | String | The minutes prior departure time of the pick up location |
pickupInstructions | String | The instruction of the pick up location |
Availability
Get Availabilities Example
const productId = "hbsdogco_53";
const fromDateTime = "2019-11-01T00:00:00-07:00";
const toDateTime = "2019-11-06T23:59:59-07:00";
const withProduct = true;
const priceBand = 'HB7'
const apiUrl = "https://devshop.hornblower.com/api/gyg/1/get-availabilities";
const url = `${apiUrl}/?productId=${productId}&fromDateTime=${fromDateTime}&toDateTime=${toDateTime}&withProduct=${withProduct}&weight=${weight}&COUNT_ADULT=${adultCount}&COUNT_CHILD=${childCount}&priceBand=${priceBand}`;
const res = await fetch(url, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
method: "GET",
});
The above command returns JSON structured like this:
{
"data": {
"availabilities": [
{
"dateTime": "2020-08-05T12:00:00-05:00",
"productId": "hbsdogco_53",
"vacancies": 30,
"cutoffSeconds": 18000,
"ticketsData": [
{
"taxes": [
{
"TaxIncluded": false,
"id": "24024",
"FixedTax": 0,
"TaxPercentage": 0,
"TaxName": "City Amusement Tax"
},
{
"TaxIncluded": false,
"id": "24025",
"FixedTax": 0,
"TaxPercentage": 0,
"TaxName": "Sales Tax"
}
],
"ticketPrice": 20.27,
"ticketDescription": "Adult",
"isTaxInclusive": false,
"category": "ADULT",
"ageRange": {
"min": 13,
"max": 54
}
}
],
"options": [
{
"type": "fromStopId",
"id": 682,
"name": "Swanage Pier"
},
{
"type": "toStopId",
"id": 683,
"name": "Poole Quay"
}
]
}
]
}
}
You can call this endpoint in order to get up to date availability information for each product. The response contains the availability for each time slot of the requested product that falls within the supplied time period.
If there is no availability for a timeslot that falls within the range return an entry with 0 availability e.g. vacancies: 0. We do not return a NO_AVAILABILITY error code when no availability for a timeslot. If there is no availability at all in the given time range we return an empty array.
The parameter withProduct
is optional. If that is true, we return ticket detail in time slot level, including ticketPrice
, taxes
, ticketDescription
, ticketType
and so on.
For some products, we require customers select departure and destination before reserving tickets. In this case, the availability response contains options
which include departure and destination info.
The options must be provided when reserve and book tickets if the product is a departure/destination product.
Request sample
GET https://devshop.hornblower.com/api/gyg/1/get-availabilities/?productId=hbsdogco_53&fromDateTime=2019-11-01T00:00:00+02:00&toDateTime=2019-11-05T23:59:59+02:00&withProduct=false
Parameter | Type | Description |
---|---|---|
productId | String | The ID of the requested product in the hornblower’s system. |
fromDateTime | String | Marks the start (inclusive) of the requested time period (ISO 8601). |
toDateTime | String | Marks the end (inclusive) of the requested time period (ISO 8601). |
withProduct(Optional) | Boolean | The flag to return product detail. |
weight(Optional) | Int | Combined weight of the reservation. |
COUNT_XXX (Optional) | Int | Product count of the XXX type (ADULT, CHILD,INFANT, SENIOR), this is used for weight calculations if weight not provided. |
priceBand (Optional) | String | Price Band code |
Response sample
Fields | Type | Description |
---|---|---|
cutoffSeconds | Integer | An integer representing the cut-off time in seconds. |
vacancies | Integer | An interger representing available time slots |
ticketsData(Optional) | Array | An array contains ticket detail info. |
ticketsData[].taxes | Array | An array of tax object. |
taxes[].TaxPercentage | Integer | An percentage for the tax. |
taxes[].TaxIncluded | Boolean | The Boolean indicates if this tax is included or not. |
taxes[].TaxName | String | The name of the tax |
ticketsData[].ticketPrice | Float | The price base on our agreement. |
ticketsData[].ticketDescription | String | The description of ticket. |
ticketsData[].isTaxInclusive | Boolean | The Boolean indicates if the tax is inclusive or not. |
ticketsData[].category | String | The category we expect in booking call(ADULT , CHILD ,INFANT , SENIOR ). |
options(Optional) | Array | The array which contains optional options, such as fromStopId and toStopId |
options[].type | String | The option type |
options[].id | String | The option id |
options[].name | String | The option name |
Reservation
Make Reservation Example
const url = "https://devshop.hornblower.com/api/gyg/1/reserve";
const payload = {
data: {
bookingItems: [
{
category: "ADULT",
count: 2,
weight: 300
},
{
category: "CHILD",
count: 1,
weight: 50
},
],
dateTime: "2019-11-01T19:00:00-07:00",
productId: "hbsdogco_53",
priceBand: 'HB7',
options: [
{
type: "fromStopId",
id: 682,
name: "Swanage Pier"
},
{
type: "toStopId",
id: 683,
name: "Poole Quay"
}
]
},
};
const res = await fetch(url, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
body: JSON.stringify(payload),
method: "POST",
});
The above command returns JSON structured like this:
{
"data": {
"reservationReference": "hbsf_1C9FC6D3-5FFE-445E-837D-01EFCED94BB2"
}
}
This call represents the first step of the booking process. It reserves the requested quantities in the Hornblower system for 15 minutes in order to guarantee a successful booking within the following 15 minutes.
Failure to do so will potentially incur in unconfirmed bookings if the product is no longer available.
HTTP Request
POST https://devshop.hornblower.com/api/gyg/1/reserve
Parameter | Type | Description |
---|---|---|
productId | String | The ID of the requested product in the hornblower’s system. |
dateTime | String | The date/time of the activity to be reserved (ISO 8601). |
bookingItems | Array | A list specifying the number of persons per category in this reservation. |
priceBand (Optional) | Array | Price Band Code |
bookingItems[].category | String | The category for which the number of persons is being provided |
bookingItems[].count | Integer | The number of persons being reserved for the specified category. |
bookingItems[].weight (Optional) | Integer | Combined weight of the category, in property default units. |
options(Optional) | Array | The array which contains optional options, such as fromStopId and toStopId |
options[].type | String | The option type |
options[].id | String | The option id |
options[].name | String | The option name |
Reservation Amend
Amend Reservation Example
const url = "https://devshop.hornblower.com/api/gyg/1/amend";
const payload = {
data: {
orderId: 'hbnycoB22143468',
newTourEventId: 9287992,
contact: {
fullName: 'Jake Sully',
firstName: 'Jake',
lastName: 'Sully',
postalCode: '85694',
emailAddress: 'sully.jake@hornblower.com',
phoneNumber: '+91XXXXXXXXX',
country: 'USA'
},
unitItems:[
{ productId: 'hbnyco.100769', qty: 7 },
{ productId: 'hbnyco.100771', qty: 2 },
{ productId: 'hbnyco.100772', qty: 3 }
]
}
};
const res = await fetch(url, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
body: JSON.stringify(payload),
method: "POST",
});
The above command returns JSON structured like this:
{
"data": {
"orderId": "hbnycoB22143468",
"message": "Operation Success!",
"err": null
}
}
Or An Error like this:
{
"data": {
"err": "Bad Request"
}
}
This Call enables an Authenticated user to make Amendments to their Booking for Contact Details, Tickets Count & Also, Allows one to Transfer Booking to a Future date Depending on availability.
HTTP Request
POST https://devshop.hornblower.com/api/gyg/1/amend
Parameter | Type | Description |
---|---|---|
orderId (Required) | String | A unique identifier for the order that needs to be amended. |
newTourEventId (Optional) | String | If this parameter is provided, it indicates that the user wants to transfer the booking to a future date. The value should be the ID of the new tour event. |
unitItems (Optional) | Array | An array containing details of the tickets to be amended with their desired quantities and IDs. |
unitItems[].productId (Required) | String | The fully qualified product ID of the ticket (e.g., property.12345). |
unitItems[].qty (Required) | Integer | The desired quantity of the ticket. This number will replace the previous ticket count. |
contact (Optional) | Object | An object containing updated contact details if the user wants to modify them. |
contact.firstName (Optional) | String | Updated first name of the contact. |
contact.lastName (Optional) | String | Updated last name of the contact. |
contact.postalCode (Optional) | String | Updated postal code of the contact in string format. |
contact.emailAddress (Optional) | String | Updated email address of the contact. |
contact.phoneNumber (Optional) | String | Updated phone number of the contact with the country code in string format. |
contact.country (Optional) | String | Updated country of the contact in string format. |
Reservation Cancellation
Cancel Reservation Example:
const url = "https://devshop.hornblower.com/api/gyg/1/cancel-reservation";
const payload = {
data: {
reservationReference: "hbsf_EBB72E93-3C11-4EFF-8B75-20F868ECFCB2",
},
};
const res = await fetch(url, {
headers: Object.assign({
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
}),
body: JSON.stringify(payload),
method: "POST",
});
The above command returns JSON structured like this:
{
"data": {}
}
This endpoint is able to cancel the reservation. This happens by default after 15 minutes.
HTTP Request
POST https://devshop.hornblower.com/api/gyg/1/cancel-reservation
Parameter | Type | Description |
---|---|---|
reservationReference | String | The identifier for the reservation in the hornblower’s system as returned by the reserve call. |
Booking
Book Example:
const url = "https://devshop.hornblower.com/api/gyg/1/book";
const payload = {
data: {
bookingItems: [
{
category: "ADULT",
count: 2,
weight: 300
},
{
category: "CHILD",
count: 1,
weight: 50
},
],
comment: "Require wheelchair assistance.",
dateTime: "2019-11-01T19:00:00-07:00",
gygBookingReference: "yourBookingRef",
language: "en",
productId: "hbsdogco_53",
reservationReference: "hbsf_1C9FC6D3-5FFE-445E-837D-01EFCED94BB2",
travelerHotel: "Hotel Name, Street, City, Country",
priceBand: 'HB7',
travelers: [
{
email: "john@john-smith.com",
firstName: "John",
lastName: "Smith",
phoneNumber: "+49 030 1231231",
passengerWeight: 170
},
{
email: "tom@tom-smith.com",
firstName: "Tom",
lastName: "Smith",
phoneNumber: "+49 030 1231232",
passengerWeight: 130
},
{
email: "sara@sara-smith.com",
firstName: "Sara",
lastName: "Smith",
phoneNumber: "+49 030 1231233",
passengerWeight: 50
}
],
options: [
{
type: "fromStopId",
id: 682,
name: "Swanage Pier"
},
{
type: "toStopId",
id: 683,
name: "Poole Quay"
}
]
},
};
const res = await fetch(url, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
body: JSON.stringify(payload),
method: "POST",
});
The above command returns JSON structured like this:
{
"data": {
"bookingReference": "hbsdogco_2087644",
"tickets": [
{
"category": "ADULT",
"ticketCode": "0005201907231624562430132112",
"ticketCodeType": "QR_CODE"
},
{
"category": "ADULT",
"ticketCode": "0005201907231624562430124303",
"ticketCodeType": "QR_CODE"
},
{
"category": "CHILD",
"ticketCode": "0005201907231624562430370991",
"ticketCodeType": "QR_CODE"
}
]
}
}
This endpoint confirms a reservation that has been placed previously and provides additional information.
The gygBookingReference
can be the booking reference in your system in case you need to do some mapping in your system.
HTTP Request
POST https://devshop.hornblower.com/api/gyg/1/book
Parameter | Type | Description |
---|---|---|
productId | String | The ID of the requested product in the hornblower’s system. |
reservationReference | String | The reservation reference returned by the reserve endpoint. |
gygBookingReference | String | The reference of this booking in your system. |
dateTime | String | The date/time of the activity to be reserved (ISO 8601). |
bookingItems | Array | A list specifying the number of persons per category in this reservation. |
bookingItems[].category | String | The category for which the number of persons is being provided. |
bookingItems[].count | Integer | The number of persons being booked for the specified category. |
bookingItems[].weight (Optional) | Integer | Combined weight of the category, in property default units. |
language | String | ISO 639-1 code of the language in which the product shall be booked. |
travelers | Array | A list of objects containing information about the travelers of this booking. The number of elements does not necessarily match the total indicated by the bookingItems parameter and in fact will most often include only the lead traveler. (Except when weight per passenger is required) |
travelers[].firstName | String | First name of the traveler. |
travelers[].lastName | String | Last name of the traveler. |
travelers[].email | String | Email address of the traveler |
travelers[].phoneNumber | String | Phone number of the traveler |
travelers[].passengerWeight (Optional) | Integer | Weight of the traveler, in property default units. |
comment | String | Additional information provided by the traveler e.g. special requests |
priceBand (Optional) | String | Price Band code |
travelerHotel (Optional) | String | Pickup location if available in the following format: "Hotel Name, Street, City, Country" |
options(Optional) | Array | The array which contains optional options, such as fromStopId and toStopId |
options[].type | String | The option type |
options[].id | String | The option id |
options[].name | String | The option name |
Get Booking
Get Booking Example:
const apiUrl = "https://devshop.hornblower.com/api/gyg/1";
const getOrder = async ({ url }) =>
fetch(url, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
method: "GET",
});
// Get Booking by bookingReference
const bookingReference = "hbny_1195572";
const bookingRefUrl = `${apiUrl}/get-booking/?bookingReference=${bookingReference}`;
const Booking = await getOrder({ url: bookingRefUrl });
// Get Booking By gygBookingReference
const gygBookingReference = "yourBookingRef";
const gygBookingRefUrl = `${apiUrl}/get-booking/?gygBookingReference=${gygBookingReference}`;
const Booking = await getOrder({ url: gygBookingRefUrl });
The above command returns JSON structured like this:
{
"data": {
"bookingReference": "hbny_1195572",
"tickets": [
{
"category": "adult",
"ticketCode": "0005201910161959436300613951",
"ticketCodeType": "QR_CODE"
},
{
"category": "adult",
"ticketCode": "0005201910161959436300863733",
"ticketCodeType": "QR_CODE"
},
{
"category": "child",
"ticketCode": "0005201910161959436300270374",
"ticketCodeType": "QR_CODE"
}
],
"orderInfo": {
"gygBookingReference": "GYG01234500",
"dateTime": "2019-12-29T18:30:00-05:00",
"productId": "hbny_1000023",
"comment": "",
"travelers": [
{
"firstName": "John",
"lastName": "Smith",
"phoneNumber": "+49 030 1231231",
"email": "john@john-smith.com"
}
]
}
}
}
This endpoint retrieves the booking information and tickets from hornblower system.
You can get the Booking by bookingReference
or gygBookingReference
.
HTTP Request
Get Booking by bookingReference
GET https://devshop.hornblower.com/api/gyg/1/get-booking/?bookingReference=hbny_1195572
Get Booking by gygBookingReference
GET https://devshop.hornblower.com/api/gyg/1/get-booking/?gygBookingReference=yourBookingRef
Parameter | Type | Description |
---|---|---|
bookingReference | String | The identifier for the booking in the hornblower’s system as returned by the book call. |
gygBookingReference | String | The identifier for the booking reference in your system as you provide to hornblower. |
Booking Cancellation
Cancel Booking Example:
const url = "https://devshop.hornblower.com/api/gyg/1/cancel-booking";
const payload = {
data: {
bookingReference: "hbsf_1088812",
},
};
const res = await fetch(url, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
body: JSON.stringify(payload),
method: "POST",
});
The above command returns JSON structured like this:
{
"data": {}
}
This endpoint cancels the booking in hornblower system.
HTTP Request
POST https://devshop.hornblower.com/api/gyg/1/cancel-booking
Parameter | Type | Description |
---|---|---|
bookingReference | String | The identifier for the booking in the hornblower’s system as returned by the book call. |
Gift Card Balance
Get Gift Card Balance Example:
const url = "https://my.hornblower.com/api/gyg/1/get-gift-card-balance/?giftCardNumber=VLOIWTOC";
const res = await fetch(url, {
headers: Object.assign({
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
}),
method: "GET",
});
The above command returns JSON structured like this:
{
"data": {
"totalBalance": 4378.62,
"giftcardNo": "VLOIWTOC"
}
}
HTTP Request
Parameter | Type | Description |
---|---|---|
giftCardNumber | String | This is the gift card number we want to check balance. |
Change Gift Card Balance Example:
const url = "https://my.hornblower.com/api/gyg/1/change-gift-card-balance";
const payload = {
"data":
{
"amount": -100,
"giftCardNumber": "VLOIWTOC",
"referenceNumber": "test 123456"
}
};
const res = await fetch(url, {
headers: {
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
},
body: JSON.stringify(payload),
method: "POST",
});
The above command returns JSON structured like this:
{
"data": {
"message": "Add balance -100 to GC VLOIWTOC"
}
}
HTTP Request
Parameter | Type | Description |
---|---|---|
amount | Number | This is the amount of gift card you want to add or subtract. |
giftCardNumber | String | This is the gift card number we want to add or subtract balance. |
referenceNumber | String | You can add reference notes to each transaction. |
Membership
Get Membership Example:
const url = "https://my.hornblower.com/api/gyg/1/get-membership/?membershipId=000511872676&propertyId=tozoo";
const res = await fetch(url, {
headers: Object.assign({
accept: "*/*",
"content-type": "application/json",
Authorization: basicToken,
}),
method: "GET",
});
The above command returns JSON structured like this:
{
"data": {
"membership": {
"importMembershipEndDate": 1708577999,
"importMembershipStartDate": 1676869200,
"orderId": "tozooB16974594",
"membershipStatus": "Active",
"importMembershipId": "000511872676",
"uses": 0,
"email": "shedley74@hotmail.com",
"membershipId": "000511872676",
"goodThru": 1708577999,
"membershipRelateNumber": 2000438854,
"transactionNumber": 511872676,
"customerProfile": {
"numberOfChild": 4,
"numberOfAdult": 2,
"info": [
{
"firstName": "Jennifer Susan Hedley",
"mainUser": true
},
{
"firstName": "Chris Paterson"
}
],
"numberOfSenior": 0,
"numberOfStudent": 0
},
"transactionDate": "02/20/2023",
"primaryContact": "Susan Hedley",
"id": 15178034,
"membershipTypeId": 130926,
"phone": "416-668-1371",
"barcode": "C2B-MLWpiw2Y-UKU7B9w-4rttYru-6D3m2Vzd2",
"dataType": "membership",
"propertyId": "tozoo",
"membershipSince": 1676869200,
"importChild": "4",
"transactionAmount": 85.19,
"importAdult": "2",
"membershipValidDays": 365,
"parkingId": "239002",
"membershipType": "Family Membership (2 Adults + up to 4 Children ages 3-15) - 1 Year",
"bookingTypeIdForMembership": 1107221,
"renewDiscountCostrate": 24969,
"propertyName": "Toronto Zoo",
"hasParkingPass": true,
"productConfig": {
"128714": 2,
"128715": 0,
"128716": 4,
"130643": 1
},
"costRate": 22660,
"memberCostRateMeta": [
{
"memberCostRate": 22660,
"costRateName": "Members"
},
{
"renewDiscountCostrate": 24969,
"costRateName": "Renewal Tier 1 (15%)"
}
],
"isActive": true,
"coupons": []
}
}
}
HTTP Request
Parameter | Type | Description |
---|---|---|
membershipId | String | After the completion of the Membership purchase, the customer is auto-generated a virtual Membership ID card which is emailed to them with a link to their customer account (this includes their membership ID number). |
propertyId | String | Property Id is our client unique identity, like toronto zoo's property id is tozoo. |
GraphQl APIs
GRAPHQL https://devshop.hornblower.com/graphql
Membership Card
Parameter | Type | Description |
---|---|---|
String | Member's email address. | |
membershipId: | String | After the completion of the Membership purchase, the customer is auto-generated a virtual Membership ID card which is emailed to them with a link to their customer account (this includes their membership ID number) |
membershipStatus | String | Current Active Status for the Member. |
membershipType | String | There are membership tiers, which come with different benefits (i.e. Silver = 10% discount, Gold = 15% + extra benefits) |
membershipSince | Int | Days since Membership Active. |
membershipValidDays | Int | Days Until Membership expires. |
hasParkingPass | Boolean | During the membership purchase, the customer can add on a parking pass to park for free during that same membership valid date range. |
photoUrl | String | All adults on the membership are required to submit their photo which is stored on the Member profile and cannot be updated. |
Note If customer's email is not supplied, Property Id and membership Id are needed to be passed in together
query MembershipProfile {
fetchMembershipProfile(email: "member@hornblower.com", correlationId: "membership_fetch_public_api", membershipId: "123456789", propertyId: "hornblower") {
membershipCard(correlationId: "membership_fetch_public_api") {
membershipId
membershipStatus
}
membershipId
membershipSince
membershipType
membershipTypeId
membershipValidDays
email
hasParkingPass
photoUrl
}
}
Frequently Asked Questions
1. Where can I get the token? Is there an endpoint allowing me to get a token?
There is no endpoint to get the token for now.
MTAwMDMzODpqZnFscmpncmhndTNyaXdmZThm
is the dev token, you can use it when developing.
2. Where can I get the list of productIds?
We don’t have all the products in our dev environment. You can always use hbsdogco_53
for testing.
When you are ready to move on to production, we can provide product mapping information for you.
On prod, you can get the list of active productId by calling Tours endpoint.
3. How long does it take for a reservation to expire?
The reservation will expire in 15 minutes.
4. Why do I get the NO_AVAILABILITY
error code when reserving the product?
We always return the tour local time with its timezone as UTC offset no matter where you are. Therefore, you need to exactly use what we return to reserve or book.
5. Can I reserve multiple products at the same time?
We only support one product per reservation. You have to reserve each product one by one if you want to reserve multiple products.
6. If there is any way to refine a search not only by passing in a date but also a time range?
We don't support the time range, we will return all available tours with correct times on that DATE. However, you have to use the correct date and time to reserve and book the tours.
7. How can I get the production credential?
We will issue the production credential only if you are able to book and cancel products successfully. Please please provide both canceled and valid bookingReferences to us. If everything looks good in our system, we will provide a production token to you.
Errors
When an error occurs, Hornblower API categorizes errors into one of the types listed in the table below in order to facilitate error handling and debugging. Additionally, an error message may be added to provide more detailed information.
A successful api call should always return a response object with a data field, which holds all the specified response data. In case of an error, two fields named errorCode and e rrorMessage should be set accordingly in the response instead.
{
"errorCode": "VALIDATION_FAILURE",
"errorMessage": "unknown category"
}
Error Code | Meaning |
---|---|
AUTHORIZATION_FAILURE | The provided credentials are not valid. |
NO_AVAILABILITY | The reservation or booking call cannot be fulfilled because there is insufficient availability. NO_AVAILABILITY must be use while handling a request for /reserve and /book only. |
INVALID_PRODUCT | The specified product does not exist or is broken for another reason (excluding availability issues). |
INVALID_RESERVATION | The specified reservation does not exist or is not in a valid state for the requested operation. |
INVALID_BOOKING | The specified booking does not exist or is not in a valid state. |
VALIDATION_FAILURE | The request object contains inconsistent or invalid data or is missing data. It must not be used for cases that are already covered by above errors. |
INVALID_TICKET_CATEGORY | The reservation or booking call specified a ticket category that is not configured for the requested product. This error requires an additional property in the JSON structure such as: |
INTERNAL_SYSTEM_FAILURE | An error occurred that is unexpected and/or doesn’t fit any of the types above. |