Developer Hub

Booking questions

The booking questions feature facilitates the collection of additional traveler details

Early access preview

This documentation is part of an early access preview initiative for selected partners only. Beta programs will launch in Q3 2026, with general availability in 2027.

If you are interested in becoming a beta partner, please reach out to your account manager.

Overview

The booking questions feature enables the collection of additional traveler data (e.g. height, weight, travel document information, dietary restrictions, etc.) in a flexible, type-safe manner.

Key benefits

  • Flexible: Add new data types without API versioning
  • Type-safe: JSON schema ensures correct structure
  • Discoverable: Ability to query available types via a catalog endpoint
  • Filtered: You only see activities you can support
  • Localized: Questions support multiple languages

Document glossary

  • Solution architecture
    Core concepts, generic data type models, activity requirements, partner capabilities, and structured answer submission.
  • API endpoints
    The data types catalog, activity filtering, and Price Check endpoints that expose booking questions.
  • Conditional questions
    How parent/child questions work and the operators that drive show/hide logic.
  • Integration flow
    End-to-end steps from discovery through booking submission.
  • Data type example
    A sample data type showing its schema definition and answer structure.
  • Localization
    How questions and options are returned in multiple languages while keeping IDs constant.
  • Validation
    Client-side and server-side validation rules and the error response format.

Solution architecture

Core concepts

Generic data type models

Reusable data type models represent categories of information (more can be added when needed), e.g. measurement, selection, address, and phone.

>> Find out more about data type models

For the full catalog of data-types call GET /experiences/booking-questions/data-types

Activity requirements

Activities declare which data types they require through booking questions, specifying:

  • Unique string ID for the question
  • Question text (localized)
  • Description of the question text (localized)
  • Data type reference
  • Whether it applies per-traveler or per-booking
  • Validation constraints (min/max values, lengths, etc.)
  • Which ticket(s) it applies to
  • Defines the child question for a given parent
  • Optional conditional logic (questions that depend on other answers)

Partner capabilities

You declare which data types you support using the supported_booking_data_types filter parameter on the search/content endpoints. This filters activities to only show those you can handle.

  • To handle any type dynamically, send supported_booking_data_types=*.
  • To support no booking questions, send supported_booking_data_types=none.

Structured answer submission

Answers are nested appropriately:

  • Per-traveler answers — In the booking_question_answers array on each traveler object.
  • Per-booking answers — In the booking_question_answers array at the booking level.

API endpoints

Get data types catalog

Endpoint: GET /experiences/booking-questions/data-types

Query Parameters: ?date_updated_start

>> See the Integration Flow: Step 1 for usage

Purpose: Returns a technical reference catalog of all available data type models.

Example request:

GET /experiences/booking-questions/data-types

Example response:

[
    {
      "date_added": "2026-07-14T11:30:08.104575+02:00",
      "date_updated": "2026-07-14T11:30:08.104575+02:00",
      "description": "Used for collecting any measurement with a numeric value and unit. Common examples include height (in/cm/foot/meter), weight (lb/kg/stone), shoe size (us_men/us_women/eu/uk/cm), helmet size (in/cm), waist size (in/cm), and chest size (in/cm). The allowed_units field specifies which units are valid for this measurement.",
      "name": "Measurement",
      "schema_definition": {
        "properties": {
          "unit": {
            "description": "Unit of measurement - must be one of the allowed_options specified for the question",
            "type": "string"
          },
          "value": {
            "description": "Numeric value as string to preserve precision",
            "pattern": "^[0-9]+(\\.[0-9]+)?$",
            "type": "string"
          }
        },
        "required": [
          "value",
          "unit"
        ],
        "type": "object"
      },
      "type": "measurement"
    },
]

Activity filtering

Query Parameter: supported_booking_data_types

Applies to: /experiences/activities/content and /experiences/activities/availability endpoints

Purpose: Filters results to only include activities whose required questions use the specified data types.

Example:

GET /experiences/activities/content
  ?activity_id=123&activity_id=456
  &language=en-US
  &supported_booking_data_types=measurement
  &supported_booking_data_types=selection
  &supported_booking_data_types=text
  • To handle all types and show all activities, use supported_booking_data_types=*. You are then responsible for handling all question types in Price Check and Booking.
  • To handle no booking questions use supported_booking_data_types=none. This will return only activities where there are no booking questions.

Price Check (includes booking questions)

Endpoint: GET /experiences/activities/{activity_id}/price-check

Purpose: Performs a price check and returns booking questions (if any) for the activity.

Example request:

GET /experiences/activities/12345/price-check?token=abc123&tickets=...

Example response:

{
  "status": "available",
  "offer_pricing": {
    "total": {
      "value": "150.00",
      "currency": "USD"
    }
  },
  "booking_questions": [
    {
      "id": "height_1",
      "type": "measurement",
      "question": "What is your height?",
      "description": "Required for safety equipment fitting",
      "applies_to": "per_traveler",
      "ticket_ids": ["12346","12345"]
      "allowed_options": [
        { "id": "in", "label": "in" },
        { "id": "cm", "label": "cm" }
      ]
    },
    {
      "id": "weight_1",
      "type": "measurement",
      "question": "What is your weight?",
      "description": "Required for zipline weight limits",
      "applies_to": "per_traveler",
      "ticket_ids": ["12346","12345"]
      "allowed_options": [
        { "id": "lb", "label": "lb" },
        { "id": "kg", "label": "kg" }
      ]
    }
  ],
  "links": {
    "create": {
      "method": "POST",
      "href": "/itineraries/activity"
    }
  }
}

Note: If you filtered activities using supported_booking_data_types in your earlier search/content calls, all returned questions will use data types you support.

Conditional questions

Questions can be conditional based on answers to previous questions. This is useful for collecting different information based on user choices.

How it works

  • Parent question — A question (typically a selection type) whose answer determines what follows.
  • Child questions — Questions with a conditional field that references the parent.
  • Bidirectional relationship — The parent lists children in its children array; children reference the parent with full conditional logic.

Example: Contact method selection

Parent question:

{
  "id": "contact_method_1",
  "type": "selection",
  "question": "How would you prefer to be contacted?",
  "applies_to": "per_traveler",
  "ticket_ids": ["12346","12345"]
  "children": ["contact_phone_1", "contact_whatsapp_1", "contact_email_1"],
  "allow_multiple": false,
  "allowed_options": [
    { "id": "phone", "label": "Phone Call" },
    { "id": "whatsapp", "label": "WhatsApp" },
    { "id": "email", "label": "Email" },
    { "id": "no_contact", "label": "No Contact" }
  ]
}

Conditional child questions:

[
  {
    "id": "contact_phone_1",
    "type": "phone",
    "question": "What is your phone number?",
    "applies_to": "per_traveler",
    "conditional": {
      "parent_question_id": "contact_method_1",
      "show_when": {
        "operator": "equals",
        "field": "selected",
        "values": ["phone"]
      }
    }
  },
  {
    "id": "contact_whatsapp_1",
    "type": "text",
    "question": "What is your WhatsApp username?",
    "applies_to": "per_traveler",
    "conditional": {
      "parent_question_id": "contact_method_1",
      "show_when": {
        "operator": "equals",
        "field": "selected",
        "values": ["whatsapp"]
      }
    }
  },
  {
    "id": "contact_email_1",
    "type": "email",
    "question": "What is your email address?",
    "applies_to": "per_traveler",
    "conditional": {
      "parent_question_id": "contact_method_1",
      "show_when": {
        "operator": "equals",
        "field": "selected",
        "values": ["email"]
      }
    }
  }
]

Conditional operators

OperatorMeaning
containsField contains any of the specified values
equalsField exactly matches any of the specified values
not_containsField does not contain any of the specified values
not_equalsField does not match any of the specified values

Integration flow

Step 1: Discovery phase

Call the data types catalog to determine which types can be supported:

GET /experiences/booking-questions/data-types?date_updated_start=2026-02-01

If date_updated_start is provided, only data types that have been added on or after the given date are returned.

Step 2: Search with filtering

Filter activities to only show those with compatible questions:

GET /experiences/activities/content
  ?activity_id=123&activity_id=456&activity_id=789
  &language=en-US
  &supported_booking_data_types=measurement
  &supported_booking_data_types=selection
  &supported_booking_data_types=text

This filters results to only include activities whose required questions use the specified data types.

Step 3: Price check

During price check, you receive booking questions in the response:

GET /experiences/activities/12345/price-check?token=abc123&tickets=...

The response includes a booking_questions array (if any). All questions use data types from your filter.

Step 4: Collect answers

Build UI to collect answers:

  • Render an appropriate input for each data type
  • Validate client-side using the schema from the data types catalog
  • For per-traveler questions, collect answers for each traveler
  • For per-booking questions, collect once
  • Handle conditional questions (show/hide based on parent answers)

Step 5: Submit booking

Submit answers with the booking request:

POST /itineraries/activity
{
  "primary_traveler": [
    {
      "given_name": "John",
      "family_name": "Doe",
      "booking_question_answers": [
        {
          "question_id": "height_1",
          "answer": {
            "value": "72",
            "unit": "in"
          }
        },
        {
          "question_id": "weight_1",
          "answer": {
            "value": "180",
            "unit": "lb"
          }
        }
      ]
    }
  ],
  "booking_question_answers": [
    {
      "question_id": "emergency_contact_1",
      "answer": {
        "value": "Jane Doe, +1-555-1234"
      }
    }
  ]
}

Data type example

Size (dimensional measurements)

Schema Definition:

{
  "type": "object",
  "required": ["value", "unit"],
  "properties": {
    "value": {
      "type": "string",
      "pattern": "^[0-9]+(\\.[0-9]+)?$"
    },
    "unit": {
      "type": "string"
    }
  }
}

Answer example:

{
  "value": "72",
  "unit": "in"
}

Localization

Questions support multiple languages through the language parameter on Price Check.

English example:

GET /experiences/activities/12345/price-check?token=...&language=en-US
{
  "id": "dietary_1",
  "type": "selection",
  "question": "Dietary preferences (optional)",
  "description": "Please share any dietary restrictions or allergies."
  "applies_to": "per_traveler",
  "allow_multiple": false
  "ticket_ids": ["12345", "12346"]
  "options": [
    { "id": "vegetarian", "label": "Vegetarian" },
    { "id": "vegan", "label": "Vegan" }
  ]
}

Spanish example:

Same question with language=es-ES.

GET /experiences/activities/12345/price-check?token=...&language=es-ES
{
  "id": "dietary_1",
  "type": "selection",
  "question": "Preferencias alimentarias (opcional)",
  "description": "Por favor, indica las restricciones alimentarias o alergias. "
  "applies_to": "per_traveler",
  "allow_multiple": false
  "ticket_ids": ["12345", "12346"]
  "options": [
    { "id": "vegetarian", "label": "Vegetariano" },
    { "id": "vegan", "label": "Vegano" }
  ]
}

Note: Question IDs and option IDs remain constant across languages for consistent answer submission.

Validation

Client-side validation

Partners should validate answers client-side using the schema from the data types catalog to ensure the correct structure.

Server-side validation

The booking endpoint validates that:

  • All required questions have answers
  • Answer structure matches the data type schema
  • Values meet validation constraints
  • Conditional questions are answered appropriately
  • Per-traveler questions are provided for each traveler
  • Per-booking questions are provided once

Error response

{
  "type": "validation_failed",
  "message": "One or more booking question answers are invalid",
  "errors": [
    {
      "type": "missing_required_answer",
      "message": "Required question 'height_1' not answered for traveler 1",
      "fields": [
        {
          "path": "$.travelers[0].booking_question_answers",
          "value": null
        }
      ]
    }
  ]
}
Was this page helpful?
How can we improve this content?
Thank you for helping us improve!