openapi: 3.1.0
info:
  title: Holiday Taxis Supplier Connect
  version: 17 Jan 2025
  description: |-
    Holiday Taxis Supplier Connect is an API for transfer companies that require an easy way to connect to Holiday Taxis
    and retrieve booking information.
    This document is aimed at developers and technical personnel who will be integrating the API.
    
    ## Work In Progress
    
    This document is a work in progress, and currently includes only very brief summaries of most operations.
    
    For the current documentation, see https://developer.holidaytaxis.com/supplier-connect/overview.html
    
    ## Driver Information & Events
    
    Three new operations are currently in development for suppliers to push live tracking details of an in-progress transfer.
    These are fully documented in this file:
    
    * `PUT /bookings/{bookingRef}/vehicles/{vehicleIdentifier}` - Provide details of the driver and vehicle assigned to a booking,
      including a way for the customer to contact the driver
    * `DELETE /bookings/{bookingRef}/vehicles/{vehicleIdentifier}` - De-allocate a vehicle from a booking, in order to use a new
      identifier for a replacement vehicle
    * `POST /bookings/{bookingRef}/vehicles/{vehicleIdentifier}/location` - Provide current location of a vehicle, and the status of the transfer
servers:
  - url: 'https://suppliers.holidaytaxis.com'
    description: Production
  - url: 'https://suppliers.htxstaging.com'
    description: Staging / Integration Testing
security:
  - "API_KEY": []
tags:
  - name: search
  - name: booking-retrieve
  - name: booking-update
  - name: driver-events
  - name: metadata
paths:
  "/bookings/search/since/{dateFrom}/until/{dateTo}/page/{pageNumber}":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-any'
      - $ref: '#/components/parameters/dateFrom'
      - $ref: '#/components/parameters/dateTo'
      - $ref: '#/components/parameters/pageNumber'
    get:
      operationId: SearchByLastAction
      summary: Search bookings by last action date
      tags:
        - search
      description: |-
        Details are currently documented here: https://developer.holidaytaxis.com/supplier-connect/search-bookingdate.html
  "/bookings/search/arrivals/since/{dateFrom}/until/{dateTo}/page/{pageNumber}":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-any'
      - $ref: '#/components/parameters/dateFrom'
      - $ref: '#/components/parameters/dateTo'
      - $ref: '#/components/parameters/pageNumber'
    get:
      operationId: SearchByArrivalDate
      summary: Search bookings by arrival date
      tags:
        - search
      description: |-
        Details are currently documented here: https://developer.holidaytaxis.com/supplier-connect/search-arrival.html
  "/bookings/search/departures/since/{dateFrom}/until/{dateTo}/page/{pageNumber}":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-any'
      - $ref: '#/components/parameters/dateFrom'
      - $ref: '#/components/parameters/dateTo'
      - $ref: '#/components/parameters/pageNumber'
    get:
      operationId: SearchByDepartureDate
      summary: Search bookings by last action date
      tags:
        - search
      description: |-
        Details are currently documented here: https://developer.holidaytaxis.com/supplier-connect/search-departures.html
  "/bookings/{bookingRef}":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-any'
      - $ref: '#/components/parameters/bookingRef'
    get:
      operationId: RetrieveIndividualBooking
      summary: Retrieve details of an individual booking
      tags:
        - booking-retrieve
      description: |-
        Details are currently documented here: https://developer.holidaytaxis.com/supplier-connect/retrieve.html
    put:
      operationId: UpdateIndividualBooking
      summary: Update details and notes of an individual booking
      tags:
        - booking-update
      description: |-
        Details are currently documented here: https://developer.holidaytaxis.com/supplier-connect/update-single.html
  "/bookings/notes/{bookingRef}":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-any'
      - $ref: '#/components/parameters/bookingRef'
    get:
      operationId: RetrieveBookingNotes
      summary: Retrieve the notes on a booking
      tags:
        - booking-retrieve
      description: |-
        Details are currently documented here: https://developer.holidaytaxis.com/supplier-connect/retrieve.html
  "/bookings":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-any'
    post:
      operationId: UpdateMultipleBookings
      summary: Update details and notes of multiple bookings
      tags:
        - booking-update
      description: |-
        Details are currently documented here: https://developer.holidaytaxis.com/supplier-connect/update-multiple.html
  "/bookings/reconfirm":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-any'
    post:
      operationId: ReconfirmMultipleBookings
      summary: Reconfirm multiple bookings
      tags:
        - booking-update
      description: |-
        Details are currently documented here: https://developer.holidaytaxis.com/supplier-connect/update-reconfirm.html
  "/bookings/{bookingRef}/vehicles/{vehicleIdentifier}":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-min-2025-01'
      - $ref: '#/components/parameters/bookingRef-syntheticTesting'
      - $ref: '#/components/parameters/vehicleIdentifier'
    put:
      operationId: SetDriverAndVehicle
      summary: Provide driver and vehicle details for a booking
      tags:
        - driver-events
      description: |-
        This request allows the supplier to provide information about the driver(s) and vehicle(s) assigned to a booking.
        Holiday Taxis will then share this directly with the customer, so that they can contact or locate the driver
        at the pickup point.
        
        Details of how this will be communicated to the customer are subject to change, and suppliers are encouraged
        to supply as much information as they have available to avoid needing later changes as recommendations evolve.
        
        Please inform [spm@holidaytaxis.com](mailto:spm@holidaytaxis.com) if you are planning to start sending any Driver Events data.
        
        This request should normally be sent once per vehicle per booking.
        
        It is requested that details are provided in English where applicable, e.g. for the "color" and "description" fields.
        
        Please also see the [Driver events booking flow](/supplier-connect/booking-flow.html)
        ### Vehicle Identifiers
        
        The `vehicleIdentifier` allows the system to distinguish between multiple vehicles fulfilling one booking,
        and to link the contact, vehicle, status, and location for that vehicle.
        
        The identifier for each physical vehicle or driver should be unique within a booking, but does not need to be
        consistent between bookings.
        
        Integrators are free to use any identifier that is convenient, subject to the following constraints:
        
        - Each identifier must be no longer than 40 characters.
        - Each identifier must contain only characters unreserved in URIs (as defined by RFC 3986): uppercase and lowercase
          letters, decimal digits, hyphen, period, underscore, and tilde.
        
        Examples of identifiers which could be used:
        
        - A number incremented within the booking for each vehicle added or replaced, e.g. `/bookings/HTX-12345678/vehicles/3`
        - An internal identifier for the vehicle or transfer from a fleet management system, e.g. `/bookings/HTX-12345678/vehicles/to_pr_jo_03`
          or `/bookings/HTX-12345678/vehicles/bc9f89ab-285f-410e-913e-464d4adbaa53`
        - The registration plate of the vehicle, e.g. `/bookings/HTX-12345678/vehicles/AB-123-XYZ`
        - The driver's internal username, e.g. `/bookings/HTX-12345678/vehicles/j.smith`
        - A hash of an identifier which you do not want to expose, or which would not meet the length and character requirements,
          e.g. calculate `sha_256('minnie.driver@example.com')` and shorten to `/bookings/HTX-12345678/vehicles/81c35bb182ed10e371b0`
        
        Within a booking, the number of distinct vehicle identifiers in use must not exceed the number of vehicles
        requested by the customer (as indicated by `novehicles` when retrieving the booking information).
        If a replacement vehicle is allocated to the booking, a `DELETE /bookings/{bookingRef}/vehicles/{vehicleIdentifier}`
        request should be sent, and the new vehicle should be given a new identifier.
        
        Additional requests for the same vehicle identifier on the same booking will overwrite all previous values, even if a field is omitted or null
        in the new request. For example, if no driver name is provided in the request, any previous driver name for that
        vehicle on that booking will be deleted.
        
        ### Example flow: Provide contact details when driver is assigned
    
        ```
        PUT /bookings/HTX-12345678/vehicles/81c35bb182ed10e371b0
        { "driver": { "phoneNumber": "+441273828200" } }
        ```
        
        ### Example flow: Extended driver and vehicle details
        
        ```
        PUT /bookings/HTX-12345678/vehicles/AB-123-XYZ
        {
          "driver": {
            "name": "Joe", "licenseNumber": "A42", "phoneNumber": "+441273828200", "preferredContactMethod": "VOICE", "contactMethods": ["VOICE", "SMS", "WHATSAPP"]
          },
          "vehicle": { "brand": "Toyota", "model": "Prius", "color": "blue", "description": "Branded with 'Acme Transfers'", "registration": "AB-123-XYZ" }
        }
        ```
        
        ### Example flow: Provide details of each vehicle and driver when customer has requested 3 taxis
        
        ```
        PUT /bookings/HTX-12345678/vehicles/1
        {
          "driver": { "name": "Joe", "phoneNumber": "+4401111222333", "preferredContactMethod": "VOICE", "contactMethods": ["VOICE", "SMS", "VIBER"] },
          "vehicle": { "brand": "Toyota", "model": "Prius", "color": "blue", "description": "Branded with 'Acme Transfers'", "registration": "AB-123-XYZ" }
        }
        PUT /bookings/HTX-12345678/vehicles/2
        {
          "driver": { "name": "Sue", "phoneNumber": "+4401111444555", "preferredContactMethod": "VOICE", "contactMethods": ["VOICE", "SMS", "VIBER"] },
          "vehicle": { "brand": "Toyota", "model": "Prius", "color": "red", "description": "Branded with 'Acme Transfers'", "registration": "AB-456-JKL" }
        }
        PUT /bookings/HTX-12345678/vehicles/3
        {
          "driver": { "name": "Alex", "phoneNumber": "+4401111666777", "preferredContactMethod": "VOICE", "contactMethods": ["VOICE", "SMS", "VIBER"] },
          "vehicle": { "brand": "Vauxhall", "model": "Astra", "color": "pink", "registration": "AB-789-PQR" }
        }
        ```
        
        #### Example flow: Re-allocating a driver/vehicle in a two-vehicle booking
        
        ```
        PUT /bookings/HTX-12345678/vehicles/jo_03
        { "driver": { "name": "Joe", "phoneNumber": "+4401111222333" } }
        PUT /bookings/HTX-12345678/vehicles/sa_07
        { "driver": { "name": "Sam", "phoneNumber": "+4401111444555" } }
        ...
        DELETE /bookings/HTX-12345678/vehicles/sa_07
        PUT /bookings/HTX-12345678/vehicles/al_01
        { "driver": { "name": "Alex", "phoneNumber": "+4401111666777" } }
        ```
        
        ### XML request example
        
        ```xml
        <?xml version="1.0" encoding="UTF-8"?>
        <request>
          <driver>
            <phoneNumber>+441273828200</phoneNumber>
            <preferredContactMethod>VOICE</preferredContactMethod>
            <contactMethods>
              <contactMethod>VOICE</contactMethod>
              <contactMethod>SMS</contactMethod>
            </contactMethods>
          </driver>
          <vehicle>
            <color>Red</color>
            <description>White stripe on front &amp; sides</description>
          </vehicle>
        </request>
        ```
      requestBody:
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              xml:
                name: request
              required:
                - driver
              properties:
                driver:
                  type: object
                  additionalProperties: false
                  required:
                    - phoneNumber
                    - preferredContactMethod
                  properties:
                    name:
                      type: string
                      minLength: 1
                      maxLength: 256
                      description: The name of the driver assigned to the booking
                      example: Joe
                    phoneNumber:
                      type: string
                      description: A phone number which the customer can use to contact the driver directly, in international E.164 format
                      pattern: "^\\+[1-9]\\d{1,14}$"
                      example: "+441273828200"
                    preferredContactMethod:
                      $ref: "#/components/schemas/contact-method"
                      description: The driver's preferred contact method
                    contactMethods:
                      type: array
                      xml:
                        wrapped: true
                      items:
                        $ref: "#/components/schemas/contact-method"
                        xml:
                          name: contactMethod
                    licenseNumber:
                      type: string
                      minLength: 1
                      maxLength: 256
                      description: A license number issued to the driver by a relevant local authority
                      example: A42
                vehicle:
                  type: object
                  additionalProperties: false
                  minProperties: 1
                  properties:
                    brand:
                      type: string
                      minLength: 1
                      maxLength: 256
                      description: The manufacturer or brand of the vehicle
                      example: Toyota
                    model:
                      type: string
                      minLength: 1
                      maxLength: 256
                      description: The model of the vehicle
                      example: Prius
                    color:
                      type: string
                      minLength: 1
                      maxLength: 256
                      description: The main color of the vehicle (in English)
                      example: blue
                    description:
                      type: string
                      minLength: 1
                      maxLength: 256
                      description: Any additional description of the vehicle (in English)
                      example: Branded with 'Acme Transfers'
                    registration:
                      type: string
                      minLength: 1
                      maxLength: 256
                      description: The registration / license plate of the vehicle
                      example: AB-123-XYZ
            example:
              {
                "driver": {
                  "name": "Joe", "licenseNumber": 42, "phoneNumber": "+441273828200", "preferredContactMethod": "VOICE", "contactMethods": ["VOICE", "SMS", "WHATSAPP"]
                },
                "vehicle": { "brand": "Toyota", "model": "Prius", "color": "blue", "description": "Branded with 'Acme Transfers'", "registration": "AB-123-XYZ" }
              }
          application/xml:
            # This long reference allows us to re-use the JSON definition for XML ("~1" is the escape for "/" in JSON Pointer)
            $ref: "#/paths/~1bookings~1{bookingRef}~1vehicles~1{vehicleIdentifier}/put/requestBody/content/application~1json"
            example: |-
              <?xml version="1.0" encoding="UTF-8"?>
              <request>
                <driver>
                  <phoneNumber>+441273828200</phoneNumber>
                  <preferredContactMethod>VOICE</preferredContactMethod>
                  <contactMethods>
                    <contactMethod>VOICE</contactMethod>
                    <contactMethod>SMS</contactMethod>
                  </contactMethods>
                </driver>
                <vehicle>
                  <color>Red</color>
                  <description>White stripe on front &amp; sides</description>
                </vehicle>
              </request>
      responses:
        '200':
          $ref: '#/components/responses/success-acknowledgement'
        '202':
          $ref: '#/components/responses/success-non-committal'
        '400':
          $ref: '#/components/responses/error-response'
        '401':
          $ref: '#/components/responses/error-response'
        '404':
          $ref: '#/components/responses/error-response'
    delete:
      operationId: DeallocateVehicleAndDriver
      summary: De-allocate a vehicle and driver from a booking
      tags:
        - driver-events
      description: |-
        As described under `PUT /bookings/{bookingRef}/vehicles/{vehicleIdentifier}`, a vehicle identifier is associated
        with all vehicle, driver, status, and location information, to distinguish multiple vehicles fulfilling one booking.
        
        Please inform [spm@holidaytaxis.com](mailto:spm@holidaytaxis.com) if you are planning to start sending any Driver Events data.
        
        If a change in circumstances means that a new vehicle is being allocated to the booking, this operation can be used
        to indicate that information associated with a vehicle identifier is no longer applicable.
        The replacement vehicle can then be allocated by sending a new vehicle identifier in a
        `PUT /bookings/{bookingRef}/vehicles/{vehicleIdentifier}` or
        `POST /bookings/{bookingRef}/vehicles/{vehicleIdentifier}/location` request.
        
        No information for a de-allocated vehicle will be shown to the customer, but some anonymised history may be retained
        for use in later investigations, in line with the Holiday Taxis data protection policy.
        
        ### Example flow: Re-allocating a vehicle after providing both contact and location
        
        ```
        PUT /bookings/HTX-12345678/vehicles/jo_03
        { "driver": { "name": "Joe", "phoneNumber": "+4401111222333" } }
        POST /bookings/HTX-12345678/vehicles/jo_03/location
        { "timestamp": "2019-08-17T12:30:00+00:00", "location": {"lat": 50.82109, "lng": -0.141366 } }
        ...
        POST /bookings/HTX-12345678/vehicles/jo_03/location
        { "timestamp": "2019-08-17T12:30:05+00:00", "location": {"lat": 50.82108, "lng": -0.141367 } }
        ...
        DELETE /bookings/HTX-12345678/vehicles/jo_03
        PUT /bookings/HTX-12345678/vehicles/al_01
        { "driver": { "name": "Alex", "phoneNumber": "+4401111666777" } }
        POST /bookings/HTX-12345678/vehicles/al_01/location
        { "timestamp": "2019-08-17T12:30:06+00:00", "location": {"lat": 35.815875, "lng": -85.363947 } }
        ```
      responses:
        '200':
          $ref: '#/components/responses/success-acknowledgement'
        '202':
          $ref: '#/components/responses/success-non-committal'
        '400':
          $ref: '#/components/responses/error-response'
        '401':
          $ref: '#/components/responses/error-response'
        '404':
          $ref: '#/components/responses/error-response'
  "/bookings/{bookingRef}/vehicles/{vehicleIdentifier}/location":
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-min-2025-01'
      - $ref: '#/components/parameters/bookingRef-syntheticTesting'
      - $ref: '#/components/parameters/vehicleIdentifier'
    post:
      operationId: SetVehicleLocation
      summary: Provide current location of a vehicle
      tags:
        - driver-events
      description: |-
        This operation is used to provide live status and location information, which will be shared with the customer,
        and may be stored for use in later enquiries.
        
        Each request must include either a status, a location, or both.
        
        Please inform [spm@holidaytaxis.com](mailto:spm@holidaytaxis.com) if you are planning to start sending any Driver Events data.
        
        If available, a new status should be sent when the driver arrives at the pickup point (WAITING_FOR_CUSTOMER),
        once the customer is on board (AFTER_PICKUP), and once the customer has been dropped off (COMPLETED).
        
        If available, a new location should be sent every 5 seconds until the transfer is completed. However, if this
        update frequency is not possible, you must provide a location at least every 60 seconds.
        Each request may include a status, even if it has not changed; if the status is not provided, it is assumed
        that the last status sent is still accurate.
        
        The `vehicleIdentifier` must be used to distinguish status and location information when a booking is fulfilled
        by multiple vehicles (as indicated by `novehicles` when retrieving the booking information). For details, see
        the description of `PUT /bookings/{bookingRef}/vehicles/{vehicleIdentifier}`.
        
        It is not required to send a `PUT /bookings/{bookingRef}/vehicles/{vehicleIdentifier}` request before sending
        status or location information, but the `vehicleIdentifier` values used must be consistent across both operations.
        
        Please also see the [Driver events booking flow](/supplier-connect/booking-flow.html)
        
        ### Example flow: Update status at key points in the transfer
       
        ```
        POST /bookings/HTX-12345678/vehicles/81c35bb182ed10e371b0/location
        { "timestamp": "2019-08-17T12:30:00+00:00", "status": "BEFORE_PICKUP" }
        ...
        POST /bookings/HTX-12345678/vehicles/81c35bb182ed10e371b0/location
        { "timestamp": "2019-08-17T12:55:15+00:00", "status": "WAITING_FOR_CUSTOMER" }
        ...
        POST /bookings/HTX-12345678/vehicles/81c35bb182ed10e371b0/location
        { "timestamp": "2019-08-17T13:10:50+00:00", "status": "AFTER_PICKUP" }
        ...
        POST /bookings/HTX-12345678/vehicles/81c35bb182ed10e371b0/location
        { "timestamp": "2019-08-17T13:57:25+00:00", "status": "COMPLETED" }
        ```
        
        ### Example flow: Location tracking - send a vehicle location every 5-60 seconds
        
        ```
        POST /bookings/HTX-12345678/vehicles/AB-123-XYZ/location
        { "timestamp": "2019-08-17T12:30:00+00:00", "location": {"lat": 50.82109, "lng": -0.141366 } }
        POST /bookings/HTX-12345678/vehicles/AB-123-XYZ/location
        { "timestamp": "2019-08-17T12:30:05+00:00", "location": {"lat": 50.82108, "lng": -0.141367 } }
        ...
        POST /bookings/HTX-12345678/vehicles/AB-123-XYZ/location
        { "timestamp": "2019-08-17T12:55:15+00:00", "location": {"lat": 50.82107, "lng": -0.141368 } }
        ...
        POST /bookings/HTX-12345678/vehicles/AB-123-XYZ/location
        { "timestamp": "2019-08-17T13:10:50+00:00", "location": {"lat": 50.82106, "lng": -0.141369 } }
        ...
        POST /bookings/HTX-12345678/vehicles/AB-123-XYZ/location
        { "timestamp": "2019-08-17T13:57:25+00:00", "location": {"lat": 50.82105, "lng": -0.141370 } }
        ```
        
        ### Example flow: Combined status and location
        
        ```
        POST /bookings/HTX-12345678/vehicles/bc9f89ab-285f-410e-913e-464d4adbaa53/location
        { "timestamp": "2019-08-17T12:30:00+00:00", "location": {"lat": 50.82109, "lng": -0.141366 }, "status": "BEFORE_PICKUP" }
        POST /bookings/HTX-12345678/vehicles/bc9f89ab-285f-410e-913e-464d4adbaa53/location
        { "timestamp": "2019-08-17T12:30:05+00:00", "location": {"lat": 50.82108, "lng": -0.141367 }, "status": "BEFORE_PICKUP" }
        ...
        POST /bookings/HTX-12345678/vehicles/bc9f89ab-285f-410e-913e-464d4adbaa53/location
        { "timestamp": "2019-08-17T12:55:15+00:00", "location": {"lat": 50.82107, "lng": -0.141368 }, "status": "WAITING_FOR_CUSTOMER" }
        ...
        POST /bookings/HTX-12345678/vehicles/bc9f89ab-285f-410e-913e-464d4adbaa53/location
        { "timestamp": "2019-08-17T13:10:50+00:00", "location": {"lat": 50.82106, "lng": -0.141369 }, "status": "AFTER_PICKUP" }
        ...
        POST /bookings/HTX-12345678/vehicles/bc9f89ab-285f-410e-913e-464d4adbaa53/location
        { "timestamp": "2019-08-17T13:57:25+00:00", "location": {"lat": 50.82105, "lng": -0.141370 }, "status": "COMPLETED" }
        ```
        
        ### Example flow: Separate status and location updates
        
        ```
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T12:30:00+00:00", "status": "BEFORE_PICKUP" }
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T12:30:00+00:00", "location": {"lat": 50.82109, "lng": -0.141366 } }
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T12:30:05+00:00", "location": {"lat": 50.82108, "lng": -0.141367 } }
        ...
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T12:55:15+00:00", "status": "WAITING_FOR_CUSTOMER" }
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T12:55:15+00:00", "location": {"lat": 50.82107, "lng": -0.141368 } }
        ...
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T13:10:50+00:00", "status": "AFTER_PICKUP" }
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T13:10:50+00:00", "location": {"lat": 50.82106, "lng": -0.141369 } }
        ...
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T13:57:25+00:00", "location": {"lat": 50.82105, "lng": -0.141370 } }
        POST /bookings/HTX-12345678/vehicles/j.smith/location
        { "timestamp": "2019-08-17T13:57:25+00:00", "status": "COMPLETED" }
        ```
        
        ### Example flow: Location requests for two vehicles fulfilling the same booking
        
        Note that requests can be sent in any order, as long as each vehicle is consistently identified.
        
        ```
        POST /bookings/HTX-12345678/vehicles/1/location
        { "timestamp": "2019-08-17T12:30:00+00:00", "location": {"lat": 50.82109, "lng": -0.141366 } }
        POST /bookings/HTX-12345678/vehicles/2/location
        { "timestamp": "2019-08-17T12:30:01+00:00", "location": {"lat": -77.850001, "lng": 166.715469 } }
        ...
        POST /bookings/HTX-12345678/vehicles/1/location
        { "timestamp": "2019-08-17T12:30:05+00:00", "location": {"lat": 50.82108, "lng": -0.141367 } }
        POST /bookings/HTX-12345678/vehicles/2/location
        { "timestamp": "2019-08-17T12:30:06+00:00", "location": {"lat": -77.850002, "lng": 166.715468 } }
        ...
        POST /bookings/HTX-12345678/vehicles/2/location
        { "timestamp": "2019-08-17T12:30:11+00:00", "location": {"lat": -77.850003, "lng": 166.715469 } }
        POST /bookings/HTX-12345678/vehicles/1/location
        { "timestamp": "2019-08-17T12:30:12+00:00", "location": {"lat": 50.82107, "lng": -0.141368 } }
        ```
        
        ### Example flow: Re-allocating a driver/vehicle in a two-vehicle booking
        
        ```
        POST /bookings/HTX-12345678/vehicles/jo_03/location
        { "timestamp": "2019-08-17T12:30:00+00:00", "location": {"lat": 50.82109, "lng": -0.141366 } }
        POST /bookings/HTX-12345678/vehicles/sa_07/location
        { "timestamp": "2019-08-17T12:30:01+00:00", "location": {"lat": -77.850001, "lng": 166.715469 } }
        ...
        POST /bookings/HTX-12345678/vehicles/jo_03/location
        { "timestamp": "2019-08-17T12:30:05+00:00", "location": {"lat": 50.82108, "lng": -0.141367 } }
        DELETE /bookings/HTX-12345678/vehicles/sa_07
        POST /bookings/HTX-12345678/vehicles/al_01/location
        { "timestamp": "2019-08-17T12:30:06+00:00", "location": {"lat": 35.815875, "lng": -85.363947 } }
        ```
        
        ### XML request example
        
        ```
        <?xml version="1.0" encoding="UTF-8"?>
        <request>
          <timestamp>2019-08-17T12:55:15+00:00</timestamp>
          <location><lat>-77.850001</lat><lng>166.715469</lng></location>
          <status>WAITING_FOR_CUSTOMER</status>
        </request>
        ```
      requestBody:
        content:
          application/json:
            schema:
              type: object
              xml:
                name: request
              additionalProperties: false
              required:
                - timestamp
              minProperties: 2
              properties:
                timestamp:
                  type: string
                  description: |-
                    The time at which the vehicle reported the given location, in UTC (+00:00).
                    
                    Times in the future, or more than 10 seconds in the past, will be rejected.
                  format: date-time
                  example: "2019-08-17T13:05:42+00:00"
                location:
                  type: object
                  description: Location of the vehicle. Must be provided if "status" is not.
                  additionalProperties: false
                  required:
                    - lat
                    - lng
                  properties:
                    lat:
                      type: number
                      description: |-
                        The decimal latitude of the vehicle's current location.
                        
                        Expected accuracy is between 4 and 6 decimal places.
                      minimum: -90
                      maximum: 90
                      example: 50.821090
                    lng:
                      type: number
                      description: |-
                        The decimal longitude of the vehicle's current location.
                        
                        Expected accuracy is between 4 and 6 decimal places.
                      minimum: -180
                      maximum: 180
                      example: -0.141366
                status:
                  type: string
                  description: |-
                    Describes the current status of the transfer relative to the customer pickup.
                    Must be provided if "location" is not.
                    
                    Values accepted:
                    
                    * BEFORE_PICKUP: initial status, while driving to the pickup location
                    * WAITING_FOR_CUSTOMER: the driver has reached the pickup location, but the customer is not yet on board
                    * AFTER_PICKUP: the customer has boarded the vehicle, and it is driving to the dropoff location
                    * COMPLETED: the vehicle has reached the dropoff location, and no more location information will be sent
                    * NO_SHOW: the customer has not shown up at the pickup point, and the vehicle will no longer wait for them
                  enum:
                    - BEFORE_PICKUP
                    - WAITING_FOR_CUSTOMER
                    - AFTER_PICKUP
                    - COMPLETED
                    - NO_SHOW
            example:
              {
                "timestamp": "2019-08-17T12:30:00+00:00",
                "location": {
                  "lat": 50.82109,
                  "lng": -0.141366
                },
                "status": "BEFORE_PICKUP"
              }
          application/xml:
            # This long reference allows us to re-use the JSON definition for XML ("~1" is the escape for "/" in JSON Pointer)
            $ref: "#/paths/~1bookings~1{bookingRef}~1vehicles~1{vehicleIdentifier}~1location/post/requestBody/content/application~1json"
            example: |-
              <?xml version="1.0" encoding="UTF-8"?>
              <request>
                <timestamp>2019-08-17T12:55:15+00:00</timestamp>
                <location><lat>-77.850001</lat><lng>166.715469</lng></location>
                <status>WAITING_FOR_CUSTOMER</status>
              </request>
      responses:
        '200':
          $ref: '#/components/responses/success-acknowledgement'
        '202':
          $ref: '#/components/responses/success-non-committal'
        '400':
          $ref: '#/components/responses/error-response'
        '401':
          $ref: '#/components/responses/error-response'
        '404':
          $ref: '#/components/responses/error-response'
  /products/resorts/areas:
    parameters:
      - $ref: '#/components/parameters/api-key-header'
      - $ref: '#/components/parameters/content-type-header'
      - $ref: '#/components/parameters/accept-header'
      - $ref: '#/components/parameters/version-header-any'
      - schema:
          type: integer
          default: 1
          example: 19928
          minimum: 1
        in: query
        name: startAt
        description: First ResortId to be returned in batch
    get:
      summary: List resorts with related geographical area data
      description: |-
        Describes the geographic areas which can be searched in the Holiday Taxis system.
        For each "resort" in the Holiday Taxis system, lists one or more shapes in WKT format which describe the geographic areas which are included in that resort.
        
        Results are returned in batches of 500 and ordered by ResortId (unique ID for a HolidayTaxis resort).
        
        If a `startAt` value is provided, results will be returned starting at this ResortId. Use the next and previous links in the response to navigate through batches.
      tags:
        - metadata
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  metadata:
                    type: object
                    properties:
                      links:
                        type: object
                        properties:
                          next:
                            type:
                              - string
                              - 'null'
                            pattern: '^\/products\/resorts\/areas\?startAt=[1-9]\d*$'
                            description: URI for next batch of 500 resorts
                          previous:
                            type:
                              - string
                              - 'null'
                            pattern: '^\/products\/resorts\/areas\?startAt=[1-9]\d*$'
                            description: URI for previous batch of 500 resorts
                  resorts:
                    type: object
                    minProperties: 0
                    patternProperties:
                      "resort_[0-9]+":
                        type: object
                        description: List of resorts, formatted as an object with sequential keys (resort_0, resort_1, etc)
                        properties:
                          resortid:
                            type: integer
                            minimum: 1
                            description: Unique ID for HolidayTaxis resort
                          areas:
                            type: object
                            description: List of areas which define the resort, formatted as an object with sequential keys (area_0, area_1, etc)
                            patternProperties:
                              "area_[0-9]+":
                                type: string
                                description: Shape description in WKT (well-known text) format, formatted as an object with sequential keys (area_0, area_1, etc). See https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry. Includes Polygon and MultiPolygon types.'
                  warnings:
                    $ref: '#/components/schemas/warnings'
              examples:
                JSON response for first page:
                  value:
                    {
                      "metadata": {
                        "links": {
                          "next": "/products/resorts/areas?startAt=964",
                          "previous": null
                        }
                      },
                      "resorts": {
                          "resort_0": {
                            "resortid": 1,
                            "areas": {
                              "area_0":"POLYGON ((1.0661400000000003 41.0701, 1.0690400000000002 41.0702, 1.07095 41.0706, 1.07345 41.0716, 1.0770100000000002 41.073, 1.0820100000000001 41.0725, 1.09343 41.0719, 1.10128 41.0719, 1.10112 41.071, 1.09974 41.0648, 1.08601 41.0636, 1.0711824172318287 41.064590028638861, 1.08772 41.0721, 1.0665400000000003 41.0649, 1.0711824172318287 41.064590028638861, 1.0665800000000003 41.0625, 1.0661400000000003 41.0701))",
                              "area_1":"POLYGON ((1.10874 41.0713, 1.10842 41.0731, 1.10838 41.0733, 1.10835 41.0734, 1.10803 41.0734, 1.10201 41.0721, 1.10132 41.0719, 1.10101 41.0705, 1.10068 41.069, 1.10874 41.0713))",
                              "area_2":"POLYGON ((1.1111 41.0717, 1.11314 41.0721, 1.11484 41.0726, 1.1179 41.0736, 1.11763 41.074, 1.11721 41.0744, 1.1167 41.0748, 1.11528 41.0755, 1.11357 41.0763, 1.11179 41.0751, 1.10836 41.0735, 1.10876 41.0713, 1.1111 41.0717))"
                            }
                          },
                          "resort_1": {
                            "resortid": 2,
                            "areas": {
                              "area_0":"POLYGON ((1.0661400000000003 41.0701, 1.0690400000000002 41.0702, 1.07095 41.0706, 1.07345 41.0716, 1.0770100000000002 41.073, 1.0820100000000001 41.0725, 1.09343 41.0719, 1.10128 41.0719, 1.10112 41.071, 1.09974 41.0648, 1.08601 41.0636, 1.0711824172318287 41.064590028638861, 1.08772 41.0721, 1.0665400000000003 41.0649, 1.0711824172318287 41.064590028638861, 1.0665800000000003 41.0625, 1.0661400000000003 41.0701))",
                              "area_1":"POLYGON ((1.10874 41.0713, 1.10842 41.0731, 1.10838 41.0733, 1.10835 41.0734, 1.10803 41.0734, 1.10201 41.0721, 1.10132 41.0719, 1.10101 41.0705, 1.10068 41.069, 1.10874 41.0713))",
                              "area_2":"POLYGON ((1.1111 41.0717, 1.11314 41.0721, 1.11484 41.0726, 1.1179 41.0736, 1.11763 41.074, 1.11721 41.0744, 1.1167 41.0748, 1.11528 41.0755, 1.11357 41.0763, 1.11179 41.0751, 1.10836 41.0735, 1.10876 41.0713, 1.1111 41.0717))"
                            }
                         },
                      },
                      "warnings": [
                        "Example Warning"
                      ]
                    }
            application/xml:
              schema:
                type: object
                xml:
                  name: response
                properties:
                  metadata:
                    type: object
                    properties:
                      links:
                        type: object
                        properties:
                          next:
                            type:
                              - string
                              - 'null'
                            pattern: '^\/products\/resorts\/areas\?startAt=[1-9]\d*$'
                            description: URI for next batch of 500 resorts
                          previous:
                            type:
                              - string
                              - 'null'
                            pattern: '^\/products\/resorts\/areas\?startAt=[1-9]\d*$'
                            description: URI for previous batch of 500 resorts
                  resorts:
                    type: array
                    xml:
                      wrapped: true
                    minItems: 0
                    items:
                      type: object
                      xml:
                        name: resort
                      properties:
                        resortid:
                          type: integer
                          minimum: 1
                          description: Unique ID for HolidayTaxis resort
                        areas:
                          type: array
                          xml:
                            wrapped: true
                          description: 'Array of strings in WKT (well-known text) format. See https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry. Includes Polygon and MultiPolygon types.'
                          items:
                            type: string
                            xml:
                              name: area
              examples:
                XML response for first page:
                  value: |-
                    <?xml version="1.0" encoding="UTF-8"?>
                    <response>
                      <metadata>
                        <links>
                          <next>/products/resorts/areas?startAt=964</ref>
                          <previous/>
                        </links>
                      </metadata>
                      <resorts>
                        <resort>
                          <resortid>1</resortid>
                          <areas>
                            <area>
                                POLYGON ((1.0661400000000003 41.0701, 1.0690400000000002 41.0702, 1.07095 41.0706, 1.07345 41.0716, 1.0770100000000002 41.073, 1.0820100000000001 41.0725, 1.09343 41.0719, 1.10128 41.0719, 1.10112 41.071, 1.09974 41.0648, 1.08601 41.0636, 1.0711824172318287 41.064590028638861, 1.08772 41.0721, 1.0665400000000003 41.0649, 1.0711824172318287 41.064590028638861, 1.0665800000000003 41.0625, 1.0661400000000003 41.0701))
                            </area>
                             <area>
                                POLYGON ((1.0661400000000003 41.0701, 1.0690400000000002 41.0702, 1.07095 41.0706, 1.07345 41.0716, 1.0770100000000002 41.073, 1.0820100000000001 41.0725, 1.09343 41.0719, 1.10128 41.0719, 1.10112 41.071, 1.09974 41.0648, 1.08601 41.0636, 1.0711824172318287 41.064590028638861, 1.08772 41.0721, 1.0665400000000003 41.0649, 1.0711824172318287 41.064590028638861, 1.0665800000000003 41.0625, 1.0661400000000003 41.0701))
                            </area>
                             <area>
                                POLYGON ((1.0661400000000003 41.0701, 1.0690400000000002 41.0702, 1.07095 41.0706, 1.07345 41.0716, 1.0770100000000002 41.073, 1.0820100000000001 41.0725, 1.09343 41.0719, 1.10128 41.0719, 1.10112 41.071, 1.09974 41.0648, 1.08601 41.0636, 1.0711824172318287 41.064590028638861, 1.08772 41.0721, 1.0665400000000003 41.0649, 1.0711824172318287 41.064590028638861, 1.0665800000000003 41.0625, 1.0661400000000003 41.0701))
                            </area>
                          </areas>
                      </resorts>
                    </response>
components:
  parameters:
    api-key-header:
      in: header
      name: API_KEY
      description: The API Key provided to you to by Holiday Taxis, which authenticates you to the system and authorises you to view and manage your bookings
      required: true
      schema:
        type: string
    version-header-any:
      in: header
      name: VERSION
      description: The version of the API you wish to use; as new features are released, you will need to send new values to access them
      required: false
      schema:
        type: string
        enum: ['2025-01', '2023-09', '2023-06', '2022-06', '2021-09']
    version-header-min-2025-01:
      in: header
      name: VERSION
      description: |-
        The version of the API you wish to use; as new features are released, you will need to send new values to access them.
        This operation requires at least version '2025-01'.
      required: true
      schema:
        type: string
        enum: ['2025-01']
    content-type-header:
      in: header
      name: Content-Type
      description: Selects the format of the provided request (JSON or XML); should match the Accept header
      required: true
      schema:
        type: string
        enum:
          - 'application/xml'
          - 'application/json'
    accept-header:
      in: header
      name: Accept
      description: Selects the preferred format for responses (JSON or XML); for PUT or POST requests, this should match the Content-Type header
      required: true
      schema:
        type: string
        enum:
          - 'application/xml'
          - 'application/json'
    bookingRef:
      in: path
      name: bookingRef
      description: The Holiday Taxis Booking Reference.
      required: true
      schema:
        type: string
        pattern: "^[a-zA-Z0-9]{2,5}-[0-9]{6,}$"
        example: HTX-12345678
    bookingRef-syntheticTesting:
      in: path
      name: bookingRef
      description: |+
        The Holiday Taxis Booking Reference.
  
        As part of your testing you can use the following reserved booking references to simulate error and success responses:
  
        TEST-111111 will return an OK response with status code 200
  
        TEST-222222 will return a NOT FOUND response with status code 404
  
        TEST-333333 will return a CANCELLED response with status code 400
  
        TEST-444444 will return a BOOKING_TRAVELLED_TOO_LONG_AGO response with status code 400
  
        TEST-555555 will return a BOOKING_TRAVELS_TOO_LONG_IN_THE_FUTURE response with status code 400
  
        TEST-666666 will return an INFORMATION_NOT_EXPECTED_FOR_THIS_BOOKING_TYPE response with status code 400
  
        TEST-777777 will return a TOO_MANY_DISTINCT_VEHICLE_IDENTIFIERS_FOR_THIS_BOOKING response with status code 400
  
        TEST-888888 will return an ATTEMPT_TO_DE_ALLOCATE_A_VEHICLE_IDENTIFIER_THAT_DOES_NOT_EXIST response with status code 400
        
        TEST-999999 will return an BOOKING_DATA_PROVIDED_TOO_EARLY response with status code 202
      required: true
      schema:
        type: string
        pattern: "^[a-zA-Z0-9]{2,5}-[0-9]{6,}$"
        example: HTX-12345678
    vehicleIdentifier:
      in: path
      name: vehicleIdentifier
      description: |-
        A free-form value to distinguish multiple vehicles fulfilling the same booking.
        This should be set consistently for a particular vehicle / in all requests for a particular booking.
      required: true
      schema:
        type: string
        pattern: "^[A-Za-z0-9._~-]{1,40}$"
        example: bc9f89ab-285f-410e-913e-464d4adbaa53
    dateFrom:
      in: path
      name: dateFrom
      description: Start date of your search
      required: false
      schema:
        type: string
        example: 2015-05-14T09:30:00
    dateTo:
      in: path
      name: dateTo
      description: End date of your search
      required: false
      schema:
        type: string
        example: 2015-05-14T09:30:00
    pageNumber:
      in: path
      name: pageNumber
      description: Page number
      required: false
      schema:
        type: int
        minimum: 1
        default: 1
  responses:
    success-acknowledgement:
      description: |-
        Acknowledgement of receipt of a valid request. 
      content:
        application/json:
          schema:
            type: object
            required:
              - status
            properties:
              status:
                type: string
                const: "OK"
              warnings:
                $ref: '#/components/schemas/warnings'
          examples:
            'Successful Response':
              value:
                status: OK
                warnings: ["Example Warning"]
        application/xml:
          schema:
            type: object
            xml:
              name: response
            required:
              - status
            properties:
              status:
                type: string
                const: "OK"
              warnings:
                $ref: '#/components/schemas/warnings'
          examples:
            'Successful Response':
              value: |-
                <?xml version="1.0" encoding="UTF-8"?>
                <response>
                  <status>OK</status>
                  <warnings>
                    <warning>Example Warning</warning>
                  </warnings>
                </response>
    success-non-committal:
      description: |-
        The request has been accepted for processing, but the processing has not been completed. 
        The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place.
      content:
        application/json:
          schema:
            type: object
            required:
              - status
            properties:
              status:
                type: string
                const: "OK"
              warnings:
                $ref: '#/components/schemas/warnings'
          examples:
            'Successful Response':
              value:
                status: OK
                warnings: ["Example Warning"]
        application/xml:
          schema:
            type: object
            xml:
              name: response
            required:
              - status
            properties:
              status:
                type: string
                const: "OK"
              warnings:
                $ref: '#/components/schemas/warnings'
          examples:
            'Successful Response':
              value: |-
                <?xml version="1.0" encoding="UTF-8"?>
                <response>
                  <status>OK</status>
                  <warnings>
                    <warning>Example Warning</warning>
                  </warnings>
                </response>
    error-response:
      description: Standard format for all errors and unsuccessful responses.
      content:
        application/json:
          schema:
            type: object
            description: One or more error messages
            required:
              - errors
            properties:
              errors:
                type: object
                description: Object containing one or more error messages, each with a distinct key indicating its category, or the field to which it applies
                minProperties: 1
                additionalProperties:
                  type: string
                  description: Details of an error. The key is a code indicating its category, or the field to which it applies; the value is a human-readable error message.
              warnings:
                $ref: '#/components/schemas/warnings'
          examples:
            'Incorrect authentication header':
              value:
                errors:
                  unauthorized: You have provided either an invalid API Key or you are out of IP range, please send valid credentials.
                warnings: []
        application/xml:
          schema:
            type: object
            xml:
              name: response
            description: One or more error messages
            required:
              - errors
            properties:
              errors:
                type: object
                description: Object containing one or more error messages, each with a distinct key indicating its category, or the field to which it applies
                minProperties: 1
                additionalProperties:
                  type: string
                  description: Details of an error. The key is a code indicating its category, or the field to which it applies; the value is a human-readable error message.
              warnings:
                type: array
                description: May contain messages about requests which, whilst they may not error, may produce unintended results or may be unsupported in the future
                items:
                  type: string
          examples:
            'Incorrect authentication header':
              value: |-
                <?xml version="1.0"?>
                <response>
                  <errors>
                    <unauthorised>You have provided either an invalid API Key or you are out of IP range, please send valid credentials.</unauthorised>
                  </errors>
                  <warnings>
                    <warning>Example Warning</warning>
                  </warnings>
                </response>
  schemas:
    contact-method:
      type: string
      description: |-
        Methods of contact which the driver can be contacted on:
        
        * 'VOICE' - Direct voice calls on the provided number
        * 'SMS' - SMS text message
        * 'VIBER' - Text messaging via Rakuten Viber
        * 'WHATSAPP' - Text messaging via WhatsApp
      enum:
        - VOICE
        - SMS
        - VIBER
        - WHATSAPP
    warnings:
      type: array
      xml:
        wrapped: true
      description: May contain messages about requests which, whilst they may not error, may produce unintended results or may be unsupported in the future
      items:
        type: string
        xml:
          name: warning
