Skip to content

Reference OTA

Dusan Milicevic edited this page Apr 24, 2026 · 2 revisions

Reference OTA

examples/ota/ — a deployable flight search and booking site that runs end-to-end on top of OTAIP. Fork it to build your own OTA.

What it is

  • Package: @otaip/ota-example
  • Server: Fastify 5 on Node.js >= 24
  • Frontend: plain HTML + vanilla JS, Pico CSS for styling — no build step, no framework
  • Default adapter: an in-process MockOtaAdapter so the site runs with no API keys
  • Optional adapters: Duffel (via @otaip/adapter-duffel) and a duffel-mock for replaying recorded fixtures

The full customer journey is wired: search → results → offer detail → passenger details → payment → ticket → confirmation → manage/cancel.

Run it

pnpm --filter @otaip/ota-example dev     # tsx watch, hot reload
pnpm --filter @otaip/ota-example start   # plain run

The server listens on http://localhost:3000.

Routes

Route Method Purpose
/api/search POST Flight search across configured adapters
/api/offers/:id GET Fetch a single offer by ID
/api/book POST Create a booking (PNR or Order, depending on adapter)
/api/pay POST Record a payment against a booking
/api/ticket POST Issue ticket for a booking
/api/booking/:ref GET Retrieve a booking by reference
/api/cancel POST Cancel a booking
/health GET Server and adapter health probe

Frontend pages

Served from public/ as static assets:

Page Purpose
index.html Search form (origin, destination, dates, pax)
results.html Offer list with sort/filter
offer.html Full offer detail (segments, fare rules summary, price)
book.html Passenger details form
payment.html Card / FOP capture (demo-only)
confirmation.html Success screen with PNR/Order reference
manage.html Retrieve & cancel by reference

All pages share app.js for fetch helpers and route handling.

Services

Under src/services/, each service wraps one or more OTAIP agents/adapters:

Service Wraps
SearchService AvailabilitySearch (1.1) across configured adapters
MultiSearchService Fan-out search over multiple DistributionAdapter instances, merges with source attribution, sorts by price
OfferService Fetch + cache individual offers
BookingService Creates a PNR or Order depending on the adapter's supportsOrders flag
PaymentService Records a payment against the booking (no real PSP)
TicketingService Issues the ticket; for order-native adapters maps to AIDM OrderChange
ManageService Retrieve + cancel flows

Adapter selection

Controlled by the ADAPTERS env var (comma-separated):

ADAPTERS=mock                     # default — in-process MockOtaAdapter
ADAPTERS=mock,duffel-mock         # multi-source with Duffel fixtures
ADAPTERS=duffel                   # live Duffel (requires DUFFEL_API_KEY)

Per-request you can also force multi-source search:

POST /api/search?multi=true

When multi=true, MultiSearchService fans out in parallel to every configured adapter, tags each offer with its source, and returns a merged list sorted by price.

Fork pattern

  1. Clone or copy examples/ota/.
  2. Replace MockOtaAdapter with a ConnectAdapter (from @otaip/connect) or DuffelAdapter via the ADAPTERS env var.
  3. Swap Pico CSS and public/*.html for your own frontend — the API contract is stable.
  4. Add auth (@fastify/jwt, session cookies, etc.) in src/server.ts ahead of the /api/* routes.
  5. Back the in-memory offer cache in OfferService with Redis for multi-instance deployments.

Environment

PORT=3000                         # default
ADAPTERS=mock                     # comma-separated adapter IDs
DUFFEL_API_KEY=duffel_test_...    # optional

See also

Clone this wiki locally