-
Notifications
You must be signed in to change notification settings - Fork 8
Reference OTA
Dusan Milicevic edited this page Apr 24, 2026
·
2 revisions
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.
-
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
MockOtaAdapterso the site runs with no API keys -
Optional adapters: Duffel (via
@otaip/adapter-duffel) and aduffel-mockfor replaying recorded fixtures
The full customer journey is wired: search → results → offer detail → passenger details → payment → ticket → confirmation → manage/cancel.
pnpm --filter @otaip/ota-example dev # tsx watch, hot reload
pnpm --filter @otaip/ota-example start # plain runThe server listens on http://localhost:3000.
| 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 |
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.
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 |
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.
- Clone or copy
examples/ota/. - Replace
MockOtaAdapterwith aConnectAdapter(from@otaip/connect) orDuffelAdaptervia theADAPTERSenv var. - Swap
Pico CSSandpublic/*.htmlfor your own frontend — the API contract is stable. - Add auth (
@fastify/jwt, session cookies, etc.) insrc/server.tsahead of the/api/*routes. - Back the in-memory offer cache in
OfferServicewith Redis for multi-instance deployments.
PORT=3000 # default
ADAPTERS=mock # comma-separated adapter IDs
DUFFEL_API_KEY=duffel_test_... # optional- Getting Started — run the OTA as step 7
- Adapters — swap the default mock for a real adapter
- Offers and Orders — why bookings surface as either PNR or Order