Introduced new QuestionPurpose.CUSTOMER_DOB enum value to indicate questions related to customer's date of birth.
Added new field SelectOption.code.
This new property will initially only appear on single- or multi-select type, country- or language-related Questions, e.g. QuestionPurpose.PAX_COUNTRY, to inform the ISO country or language code associated with each SelectOption.
Introduced new QuestionPurpose.CUSTOMER_* enum values.
Our intention is to attribute these to questions collected at the group/booking-level from the customer, i.e. the person making the booking and acting as the main contact.
This customer does not necessarily have to be a participant in the tour or activity. Our main aim is to preserve this separation where it exists in the underlying reservation system and to distinguish such questions from those using the existing QuestionPurpose.PAX_* flags, which can then be associated with the actual participants.
Please refer to the Question type in the Schema section at the bottom of our API documentation page for a full list of the new QuestionPurpose.CUSTOMER_* values.
This release adds a new pair of properties to a set of types that make up the Step.fareDetails and Step.questions models used during checkout:
The new properties introduced in all of the above types are called fingerprintHash and dnaHash and take the form of SHA-256 hash strings.
A fingerprintHash is a hash of the combination of primary identifiers used by the supplier's reservation system that distinguishes a record, such as a BaseVariant, Fare or Question, from its siblings. Related records at the same level but with different parents, e.g. the Adult Fare types sitting under various different BaseVariant-TimeSlot branches, will commonly have the same fingerprintHash but each will have a distinct dnaHash.
A dnaHash is the unique hash of a record's fingerprint, so the same combined properties used to identify it in the supplier's subsystem forming the basis of its fingerprintHash, but in conjunction with the fingerprints of its entire line of parents/ancestors. Effectively, this results in a signature that identifies a single specific node in an entire Step.fareDetails or Step.questions tree that is unique within the entire scope of the relevant top-level Product.
We are excited to release this new feature as it is a prerequisite for a host of useful applications that require the ability to identify, and thus recognise at a later time, instances of the above model types. Unlike Products, which are imported, edited and enriched by Livn in a process we call Content Curation, the BaseVariant, TimeSlot, Fare etc objects appearing during checkout are all generated on-the-fly from data received directly from the relevant upstream reservation system.
The existing uuid primary identifiers, which are used to refer to some of these types in the scope of the Livn API, namely to define Step.fareSelections, Step.addOnSelections and Step.answers, were never intended to be used as lasting identifiers beyond the scope or lifetime of the Flow they appear in. These uuid strings are either true, randomly generated UUIDs or are sequentially generated "pseudo-UUIDs" that merely borrow the 8-4-4-4-12 character UUID format. Either way, there is no guarantee that a particular Fare or Question with a specific uuid value from one Flow will appear with the same uuid in another Flow, be it for the same Flow.date or another date.
Clients of our API who wish to keep track of the available variants, sessions and fare types of products as they appear over time, currently have to resort to using the various human-readable properties like name, description, title etc to try and identify these by. However, just like the uuid properties, which also don't exist at all levels of the FareDetails and Questions model, these text fields are ill-suited to serve as lasting identifiers. These fields are prone to change, be it due to code changes made by Livn to fix or improve the way data coming from a supplier is presented downstream or simply by the supplier making a change on their end. The new fingerprintHash and dnaHash values, on the other hand, are based on values that are supposed to be static for the lifetime of these records in their originating system, so ideally values like database primary keys published by the reservation system API and used there to refer to a product session, fare type or question. The expectation is that a record with the same fingerprint and DNA (and thus the derived hashes) represents the same entity in the connected reservation system while a changed fingerprintHash and dnaHash indicate a different or new entity upstream. The exact combination of properties or the nature of these fingerprints is specific to the different reservation systems we have connected, but the hashes we produce for each all have the same format.
If your implementation depends on the ability to identify and keep track of data objects from our checkout-time API model, you'll want to work with the fingerprintHash and dnaHash properties. We already have a few upcoming features for our API in the development pipeline that weren't feasible, or technically possible, without this important step of adding reliable fingerprinting at every relevant level of the checkout-time data model. The first such extension we have planned requires the new ability to track sub-Product-level information about product variants, time slots and fares in a perpetual cache record and we hope to be sharing this data with our clients soon.
We currently only populate the flow.clientId property if this is defined in a JSON Web Token used to authenticate the initial POST /api/flows request.
For calls using Basic HTTP authentication, we currently ignore this field and it always remains null.
It might be useful even to Livn API clients that don't use JWT, but make all requests from a secure backend using their API credentials and Basic authentication, to still set a specific ID for their individual clients in every flow record.
For this reason, we now accept and persist any non-blank flow.clientId received in the payload of the initial POST so long as it isn’t explicitly locked in by a JWT Bearer token.
Added booking.clientId to hold the flow.clientId of the flow from which a booking originates.
Added request parameter clientId to the booking search route (GET /api/bookings) to allow filtering searches to bookings resulting from flows with a specific flow.clientId.
Note: this parameter can only be used when the clientId isn't explicitly locked in by a JWT authentication token, e.g. in conjunction with Basic HTTP authentication.
Added parameter bookingSupplierReference to ticket search API GET /api/tickets which allows searching for tickets based on the Booking.supplierReference.
Implemented new Cancellation.status field and CancellationStatus enum to more easily identify the status or outcome of a cancellation request.
Added endpoint GET /api/products/operatingDates, which returns the operating dates for all products in the user's accessible inventory as a single data dump using CSV formatting.
Please see chapter 3.2 Product Search & Discovery of the Developer Guide for more details.
We have decided to deprecate the QuestionScope enum and Question.scope field. To date there has not been any use case for scopes other than PER_GROUP, meaning the questions we publish need to be asked and answered only once. Depending on the Question.fareUuids property a question can still only be relevant to the user and need to be answered if any fare or add-on with one of the specified uuid values has been selected.
Implemented new Booking.productName field for display on booking tickets for improved user experience.
Added endpoint GET /api/suppliers/productMinDetails. This returns only the ids of suppliers and their products you have access to.
Added optional request parameters supplierIds and productIds to the booking search endpoint (GET /api/bookings).
Similar to the filter properties ProductSearch.supplierIds and ProductSearch.productIds of the product search call, you can use a comma-separated list of supplier or product IDs to narrow the search down to bookings of specific suppliers or products.
Added boolean flag minimalDetails default value False When set to True, the response will contain minimal product details.
Added boolean flag Question.mustShow used to indicate that a question should be displayed to the customer even if it is technically not required to be answered.
The most common use case are pick-up and drop-off-related questions that are quite frequently optional, meaning participants have the option not to make use of the courtesy pick-up, but most customers will want to have the option.
We decided to provide this new property in response to requests we received from suppliers who noticed an increase in bookings that lacked optional details (pickup selections, booking notes/comments etc) that they simply know from experience would often be included if only customers were presented with certain non-required questions.
Added fields Fare.paxMinand Fare.paxMax to inform the number of participants included in each unit of a fare. This is applicable mostly for Group fares that admit a number of participants on a single unit of that fare, e.g. Family 2 Adults + 2 Children.
Please note that this information can only be presented when it is, in turn, provided by the respective upstream reservation system.
Added QuestionPurpose.PAX_COUNT_TOTAL used to indicate a question that requires the user to specify the total number of participants in the group.
Updated default value optional parameter orderDescending to TRUE for endpoint GET /api/bookings
Livn is happy to introduce our new Mocker connector and Mock-Supplier (Supplier id 1). This supplier offers a small number of products (Product ids 1-4) that between them cover every facet of the Livn API's extensive range of fields and functionality: non-linear group pricing, follow-up questions, optional steps, all the various question answer types etc.
We recommend that developers working on their integration to the Livn API focus primarily on these four products and build their client around their requirements. The mock-up products also form the basis of our final pre-production certification process, which will ensure that your application is ready to handle anything our API will throw at you once you go live.
Added fields Booking.channel and Booking.distributor containing the details of the the Channel through which the booking was made and the Distributor from which the product was sourced.
Added optional parameters includeChannel and includeDistributor to endpoint GET /api/bookings. Both default to false, maintaining the existing behavior, and when enabled cause the respective field to be included in the Bookings returned by the search.
Added Cancellation.userInfo, which contains the API user's id and loginName used when making the cancellation.
Added Cancellation.origin, which indicates where the cancellation request originated from. Currently, this can contain any of the ff values:
Added Cancellation.cancelledBySupplier, which indicates whether the cancellation has been made on the supplier's end and not through the upstream reservation system.
Added search parameters travelFrom and travelTo to endpoint GET /api/bookings which filters results to bookings with travel dates falling within the specified period.
Parameter confirmedTo on endpoint GET /api/bookings can now be used independently without parameter confirmedFrom.
Added ProductSearch.searchLimit, the search will be limited by the provided value. Any value <=0 will result in an unlimited search. default value is 1000
Added includeAllSteps to /api/flows/{flowId} If true, the response will contain all the steps. If false, the response will contain only the active step. default value true
Added Quote.contractCommTotal and Quote.resSuppliedCommTotal, the sum of all contracted commissions and the sum of all commissions returned by the supplier's reservation system in monetary form, respectively.
Added Invoice.contractCommTotal and Invoice.resSuppliedCommTotal, the sum of all contracted commissions and the sum of all commissions returned by the supplier's reservation system in monetary form, respectively.
Added Quote.generalTerms, where we return the supplier's general terms and conditions at the time of booking.
Marked Supplier.tnc and SupplierBasic.tnc as deprecated in favor of Quote.generalTerms.
Added endpoint GET /api/bookings/pdf/{bookingId} and GET /api/tickets/pdf/{ticketId} which generates a PDF voucher on a per booking and per ticket level, respectively.
Added Location.district, the name of the suburb or district within a municipality (Location.city) where applicable.
Added Supplier.phoneRes, the best phone number to contact the supplier with booking-related inquiries.
Added Ticket.supplierEmailRes and Ticket.supplierPhoneRes.
These values are essentially just copied from Supplier.emailRes (falling back on Supplier.email if that is null) and Supplier.phoneRes and represent the best email address and phone number to contact the supplier with booking-related inquiries.
Added Product.operatingDaysStr to complement the numeric bitmask-encoded field Product.operatingDays.
It contains the product's known operating weekdays as a comma-separated list of the abbreviated English week day names, e.g. Product.operatingDays=21 translates to Mon,Wed,Fri.
Added search parameter countriesOfOperation to endpoint POST /api/suppliers/search which filters results to suppliers who operate products in specific countries.
The countries parameter remains unchanged and filters suppliers by the country where they are headquartered.
Added endpoint POST /api/products/cities which returns the list of cities that appear as a product search reference start location, i.e. Product.locationsStart.
Added endpoint GET /api/permissions which lists the permissions of the authenticating API user.
These are the currently defined permissions:
Added optional field permissions to the Login type used to request JSON Web Tokens with the POST /api/login call.
The property is an array of Permission enum values and can be used to explicitly restrict the permissions of the generated token. By default, i.e. by omitting the permissions property, the returned token will have the same permissions as the API user. This matches the POST /api/login call's previous behaviour.
Added enum type QuestionPurpose and field Question.purpose.
The field is used to describe the purpose or nature of a Question.
The intention is to enable clients who capture pax details as part of their greater application,
to map this data onto questions asked during checkout and pre-populate form fields,
suggest or auto-complete input values.
Important: Please note that this enumeration is explicitly to be treated as evolving and expendable.
We plan to add new values in the future for question types we encounter in newly connected supplier reservation system
, or even questions that may emerge as new quasi-standards (COVID vaccination status?)
, which present as dedicated single-purpose fields on the upstream and for which it makes sense to map these to data
our API clients might capture in their application.
Please make sure that your implementation is designed to ignore (and perhaps log) newly introduced QuestionPurpose values.
Added enum value AnswerType.PHONE.
Questions known to be collecting a phone number are commonly found in many, if not most, reservation systems we are communicating with on the upstream. While the input for these questions is commonly freely typed, we have already connected two systems so far, that require numbers in a specific format. Instead of imposing different phone number formats on you we have adopted libphonenumber, Google's common Java, C++ and JavaScript library for parsing, formatting, and validating international phone numbers. We require that the answer.value in response to a question with answerType=PHONE has to be an valid PSTN phone number that includes the country dial code and which can be parsed using libphonenumber. The easiest way to do this is to simply stick to a standard notation such as the ITU's E.164, e.g. +61292644411. We will parse and validate your input and are subsequently able to convert it to whatever specific format may be required on a particular upstream API.
Added field Booking.cancellations in the GET /api/flows/{flowId} and GET /api/bookings calls, which contains details of any failed, in-progress or confirmed cancellations.
Add new endpoint GET /api/exchangeRates which retrieves a map of current exchange rates for all known product currencies.
Add Step.addOnSelections as a stand-alone field, replacing the old approach of embedding the addOnSelections as a second-tier child-node of individual Step.fareSelections.
This simplifies the fare and add-on selection process and generally makes more sense with addOns that are not fare-specific, but are offered at the timeSlot or baseVariant level.
"steps": [{
"id": 47,
"status": "ACTIVE",
"milestone": "FARE_SELECTION",
"fareSelections": [{
"uuid": "00000550-0002-0010-0001-000000000007",
"quantity": 2
}
],
"addOnSelections": [{
"uuid": "00000550-0002-0010-0001-000000000002",
"quantity": 1
}, {
"uuid": "00000550-0002-0010-0001-000000000003",
"quantity": 1
}
]
}
]
Please check the Developer Guide for a more complete example of the new step structure for fareSelections and addOnSelections.
Add Ticket.created, Ticket.bookingDetails, Ticket.passengerDetails, Ticket.productDetails, Ticket.travelDate, Ticket.supplierName, Ticket.localOperatorName, Ticket.barCodeDetails, Ticket.pickupDetails, Ticket.localFees, and Ticket.billingNotes to enhance details shown in tickets.
Deleted Ticket.barcodeData and Ticket.barcodeRequired since this is now part of the newly added Ticket.barCodeDetails.
Add Flow.livnReference, Flow.billingInfo, Booking.livnReference, Booking.clientReference, Booking.passThroughReference, Booking.partyName, Booking.partyEmailAddress, Booking.billingInfo, Cancellation.supplierReference to give additional references and help in generating sales reports.
Add Question.scope to know if a question should be answered per selected unit, per selected fare, or just once for the whole group.
Updated Question.fareUuid to Question.fareUuids to associate a question with more than one Fare.uuid.
Add ProductSearch.productIds to limit search results to specific Product.id values.
Add ProductSearchOrder.SUPPLIER_ID to order search results first by Product.supplier.id then Product.id.
First soft-launch release of the Livn API version 2.