Skip to content
ti2travelPublic

About

Tourism Industry Interchange

Resources

Stars

2 stars

Watchers

3 watching

Forks

Repository files navigation

Ti2

Ti2 (Tourism Information Interchange) is an open source integration framework, built by and for the tourism community. Ti2's goal is to make integrations in our industry faster and easier to build, while providing a framework for innovation on top of these integrations.

Core functions of Ti2 are currently focused on content, rates, and bookings.

Why use it ?

Ti2 gives a free, open source solution to building integrations across our industry. In addition, tools can be built on top of Ti2, that add additional value to these integrations - whether for the good of our industry or for profit.

Become part of the community, start building on Ti2 today!

About this Project

How it Works

Ti2 has a core codebase of standardized industry functions (new, update, cancel, etc.) for bookings, content, and rates - with more to come. Plugins are used to connect to the Ti2 to perform a task (like create a booking). There are two types of plugins: Integration and App.

Integration Plugins are used to connect core systems, like booking/reservation or content management systems, to Ti2. For example, you would use a Integration Plugin to connect Ventrata to Ti2. You would do this to be able to accept bookings from another system (like an OTA) connected to Ti2. Ti2 allows any Integration Plugin to communicate with each other; therefore, once a Integration Plugin is live, no one ever needs to write a custom integration for that system again.

App Plugins are value added tools that only speak to Ti2 and other plugins. For example, you might create an App Plugin that sends email notifications every morning with a list of all active bookings for the day. You would retrieve the list of bookings for the day by using a System Plugin.

Ti2 can be deployed on your own servers, or you can connect to a Ti2 instance that another company is hosting.

Getting Started

You can write your [own plugin]{@tutorial plugin-development} that hooks up to a Ti2 instance or you can run a server that that hosts your [own Ti2 instance]{@tutorial setup-your-instance} with any plugins (your own or from the plugin library).

Plugins

Plugins connect Ti2 to other systems and features. By default, the API listens on port 10010 and serves Swagger documentation at /api-docs. Set startServer: false to disable the HTTP server or apiDocs: false to disable the Swagger route.

Plugin Library

Methods FareHarbor PeekPro Zaui Xola Ventrata TravelGateX Didgigo TourConnect TourPlan
Base
validateToken ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
tokenTemplate ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
Content
copyMedia ✓
getProfile ✓ ✓
updateProfile ✓
getLocations ✓ ✓
getLocation ✓ ✓
createLocation ✓ ✓
updateLocation ✓ ✓
getProducts ✓ ✓
getProduct ✓ ✓
createProduct ✓ ✓
updateProduct ✓ ✓
Bookings
searchProducts ✓ ✓ ✓ ✓ ✓ ✓
searchBooking ✓ ✓ ✓ ✓ ✓ ✓
searchAvailability ✓ ✓ ✓ ✓ ✓ ✓
searchQuote ✓ ✓ ✓ ✓ ✓ ✓
createBooking ✓ ✓ ✓ ✓ ✓ ✓
confirmBooking ✓ ✓ ✓ ✓ ✓ ✓
cancelBooking ✓ ✓ ✓ ✓ ✓ ✓
searchProductsForItinerary ✓
searchAvailabilityForItinerary ✓
addServiceToItinerary ✓
getCreateItineraryFields ✓
searchItineraries ✓
queryAllotment ✓

Product catalog refresh contract

POST /{app}/{userId}/{hint}/product-files-archive generates four product JSON files from the existing TourPlan NX cache. It accepts an explicit all selection or a nonempty usage map, with an optional 64-character lowercase hexadecimal usageHash, and streams a temporary tar.gz archive to pyfilematch. A usage selection with no matching options returns no_matching_options JSON instead. The endpoint requires an admin or matching user token. TI2 does not upload files to S3 or create another raw catalog cache.

GET /{app}/{userId}/{hint}/product-files-archive returns { "projectionVersion": number } for the TourPlan NX exporter. Pyfilematch uses this version to republish product files when their projection changes, even if the source catalog and usage are unchanged. It uses the same admin or matching user authentication as the POST endpoint.

For TourPlan NX, request a manual or scheduled full refresh with backgroundJob: true when the sync marker is required. After a successful catalog cache save, the worker calls the loaded events2url plugin's recordProductCacheSave API (ti2-events2url >= 1.3.0, configured with ti2_events2url_eventsURL and ti2_events2url_authorization) so Filematch can record product and option counts, cache fingerprint, cache save time, and cache revision in a small S3 marker. TI2 suppresses the in-process bookingsProductSearch:cache:save emit for those NX full refreshes so the plugin's fire-and-forget bus listener does not also forward them. A successful handoff returns syncMetadataGenerationId; a handoff failure returns syncMetadataError while the saved product cache remains a successful refresh. A synchronous full refresh and the internal plugin job do not record a marker. Without ti2-events2url >= 1.3.0 loaded in the worker, the handoff fails with syncMetadataError and the catalog cache save still succeeds.

POST /products/{appKey}/{userId}/{hint}/search returns a canonical object with a products array. Use cacheOnly: true to read Ti2's current catalog without calling the integration; cacheFound distinguishes a cache miss from a cached empty catalog. productId and optionId accept arrays and can be combined to limit the returned products and options when an option ID is shared.

A forced request is a full-catalog refresh by default. fullSyncTrigger may be scheduled, manual, or organic; an omitted trigger on a forced request is treated as manual. Manual refreshes require a non-blank admissionOverrideReason. Scheduled and manual refreshes reject searchInput, optionId, productId, productName, or lastUpdatedFrom selectors. An empty searchInput or searchInput: "*", or an empty optionId array, represents the full catalog. Scheduler-owned requests may also carry fullSyncStartedAt and fullSyncAdmissionToken. TourPlan NX forceRefresh rebuilds the aggregate catalog but may reuse supplier entries fetched within the last 18 hours.

Background NX force-refresh requests for the same company and integration hint share one Bull job while it is queued or active, including manual and scheduled requests. Each worker uses an exclusive temporary HTTP server. API jobs have a 45-minute deadline (API_JOB_TIMEOUT_MS); individual NX HTTP requests during a forced refresh default to two minutes (TOURPLAN_REQUEST_TIMEOUT_MS). A worker request timeout aborts the internal request and cancels outstanding NX requests, then returns a failed result with HTTP code 504.

The NX plugin saves successful supplier entries individually. It saves _all separately after a complete, nonempty fetch. A later supplier failure preserves successful supplier writes and the prior aggregate and translated product cache. There is no catalog-wide saveMany transaction. Product files are generated on demand during downstream aggregation, not by Force Refresh itself.

Unscoped forced responses include catalogRefreshOutcome, cacheUpdated, cachePreserved, cachedProductCount, cacheSavedAt, and cacheVersion. TourPlan NX also returns catalogOptionCount and catalogFingerprint for a complete catalog refresh; the worker needs both to record the Filematch marker. Consumers that update a downstream catalog should use these fields instead of assuming that HTTP 200 or the returned products.length means Ti2 replaced its cache. Empty or partial plugin results can preserve an existing catalog. If a concurrent refresh remains in progress past the lock wait, Ti2 serves the retained catalog with catalogRefreshOutcome: "refresh_in_progress_cache_served". This outcome is non-terminal: background-job success means the HTTP call completed, not that the catalog was written.

The product cache refresh interval defaults to seven days when no TTR is set. Any explicit ttlForProducts or plugin cacheSettings.bookingsProductSearch.ttr value is honored, including 86400 for a one-day interval.

Shared itinerary product query

controllers/graphql-schemas/itinerary-product exports the type definitions and query used for itinerary product searches. The option selection includes city, country, and currency, which Tourplan plugins already populated, as well as optionClass and chargeUnit. Room restrictions and room unit restrictions include maxPaxWithInfants; option restrictions also include Other. These fields are nullable. When a plugin omits one, the query returns null for that field, as it does for other optional fields such as description and maxAdults. Adult, Child, and Infant restrictions continue to select only allowed, minAge, and maxAge.

The query selects fields from the product objects supplied by the plugin. A previously cached product does not gain new fields until its catalog entry is refreshed. Use the forced full-catalog refresh contract above when the latest plugin fields must appear immediately (forceRefresh: true, with a non-blank admissionOverrideReason for a manual refresh), and check cacheUpdated before treating the result as a refreshed catalog.

Optional catalog lifecycle service

Ti2 synchronously asks Filematch to update catalog lifecycle state when an integration is removed or reactivated. The call reuses ti2_events2url_eventsURL and ti2_events2url_authorization; Filematch then forwards the request to Pyfilematch. Without the events URL, Ti2 cleans its own credentials and schedules without making an external catalog request. INTEGRATION_LIFECYCLE_TIMEOUT_MS controls the request timeout and defaults to 30 seconds. A save left in provisioning blocks deletion until it is older than INTEGRATION_PROVISIONING_TIMEOUT_MS (five minutes by default); deletion then advances the generation before removing local and catalog state. Catalog lifecycle consumers must accept newer generations so a failed activation followed by deletion can move from generation N to N+1. The timeout is a provisioning lease: saves refresh it before catalog activation and must still own their generation when marking activation complete.

Contributing

Contributions are welcome and ecouraged.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  • Fork the Project
  • Create your Feature Branch (git checkout -b feature/AmazingFeature)
  • Commit your Changes (git commit -m 'Add some AmazingFeature')
  • Push to the Branch (git push origin feature/AmazingFeature)
  • Open a Pull Request

Feel free to check the Issues Page.

License

Distributed under the GPL-3 License. See LICENSE file for more information.

TL;DR Here's what the license entails:

  1. Anyone can copy, modify and distribute this software.
  2. You have to include the license and copyright notice with each and every distribution.
  3. You can use this software privately.
  4. You can use this software for commercial purposes.
  5. If you dare build your business solely from this code, you risk open-sourcing the whole code base.
  6. If you modify it, you have to indicate changes made to the code.
  7. Any modifications of this code base MUST be distributed with the same license, GPLv3.
  8. This software is provided without warranty.
  9. The software author or license can not be held liable for any damages inflicted by the software.

About

Tourism Industry Interchange

Resources

Stars

2 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages