NAV
javascript
Postman Collection

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 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
email 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.