Edge Journeys overview
Edge Journeys provides configurable, branded booking experiences for cruise and group-touring products — from trip and departure selection through room choice, activities, payment, and confirmation. The entire journey is driven by a single YAML configuration file (journey.yaml) and a tenant-owned React UI, with no per-tenant application code deployed to the platform.
There is no custom backend per tenant. You configure; the platform renders, bundles, and serves.
The booking flow
A guest moves through a configurable sequence of steps. A cruise journey can use the full Meridian Voyages reference flow, while a group-touring journey can present departures and room configurations without a vessel or deck plan:
| Step | What happens |
|---|---|
| Trip select | Guest browses trips/packages from the catalog |
| Departure & travellers | Selects departure date, party size, solo vs sharing |
| Room category | Chooses a room or cabin tier (e.g. Twin, Single, Balcony, Suite) |
| Room pick | Selects a room configuration, or a specific cabin from a deck plan when the cruise model supports it |
| Activities & quote | Picks add-on activities; optionally receives an AI-generated quote letter |
| Review & pay | Reviews basket totals, deposit schedule, and completes payment |
| Confirmation | Receives booking reference and welcome content |
Steps are ordered in journey.yaml. The platform framework handles step gating. Cruise tenants can enable the immersive cabin-pick deck-plan experience; touring tenants normally render room options through tenant-owned step components.
How it works
Tenant config repo (journey.yaml + journeys/src/)
│
├─ journey.yaml → Journey definition (steps, channels, branding, provider, live IDs)
│
└─ journeys/src/ → Tenant React UI (main.jsx entry, step components, styles)
│
▼
Edge Journeys service (apps/journeys)
│
├─ Fetches config + UI source from GitLab (or local checkout)
├─ Bundles tenant UI with esbuild (React externalized via CDN import map)
├─ Serves bundled HTML at /:tenantId/ or custom domain
│
└─ API (/api/journeys/v1/*)
├─ Catalog: trips, categories, rooms, activities
├─ Baskets: create, update components/travellers, pricing
├─ Payments: schedules, payment requests
└─ Checkout: create booking → Salesforce itinerary
Booking experiences are built through the prompt-to-production pipeline: describe the flow you want, and the platform generates, reviews, tests, and deploys it — config and UI hosted on Edge in your tenant repository.
Journeys can also be extended with externally quoted ancillaries such as insurance or an eSIM. Those selections use Journeys-owned provider adapters and checkout orchestration rather than being stored as Basket Service components. See Extending journeys with third-party services.
The API underneath is fully documented: start with the Quickstart (curl from catalog to booking), then API architecture for the layers and authentication, the Journeys API reference for every endpoint (also available as an OpenAPI spec), the Data model for every object, Webhooks & events for real-time notifications, Performance for latency characteristics, MCP & SDK for AI-agent access, and Platform API surface for the underlying platform APIs a journey can be extended to use.
The Meridian Travel distribution API sample provides an interactive, fictional walkthrough of partner access, sandbox credentials, catalog-to-booking API calls, and the channels unlocked by one Journeys integration.
Cruise and touring catalog models
live.catalog_model selects how the live provider resolves inventory:
| Model | Catalog interpretation |
|---|---|
cruise | Packages become trips; cruise details supply vessels, cabin categories, physical cabins, deck locations, and cabin-level availability. |
touring | Packages become trips; active departures are listed and required PriceCategories package options supply room configurations such as Twin and Single. No vessel or physical cabin number is required. |
The neutral catalog routes are GET /catalog/trips and GET /catalog/rooms. They return product-neutral wire fields — tripCode, tripName, roomCode — with vessel and deck information present only for products that have them. Existing integrations can continue using the backward-compatible /catalog/voyages and /catalog/cabins routes, which keep the established voyageCode, voyageName, and cabinNumber wire fields.
Provider model
| Provider | When to use | What it does |
|---|---|---|
mock | Local development, UI iteration, demos | Returns fixture catalog data; basket operations are simulated in-memory |
live | Staging and production | Calls KTAPI for the catalog, Basket Service for commercial operations, Keycloak for auth |
Set provider: mock or provider: live in journey.yaml. The live provider requires additional commercial IDs in the live: block — see journey.yaml reference.
Entry points and channels
Journeys supports multiple booking channels, configured per tenant:
| Channel type | Example | Behaviour |
|---|---|---|
b2c | Book Direct | Guest books without intermediary |
b2b | Travel Advisor | Requires advisor identification (IATA number + email lookup) before the booking flow begins |
Deep links let product pages pre-select a trip and skip the browse step:
https://book.example.com/?trip=SOA-2627¤cy=AUD&adults=2
URL parameters are parsed by the tenant UI, not the platform — see Tenant UI source for the parameter contract.
Commercial pricing
For trade channels, the same basket account and mapped Salesforce channel drive reseller-agreement eligibility. KTAPI can return applicable_to: reseller_commission price lines; Journeys exposes their aggregate as optional BasketPricing.commission_amount while leaving the customer sales total unchanged.
Payment-method surcharges are a separate Edge Pay concern. They are configured per method in payment.yaml with surcharge_percent and applied authoritatively on the hosted payment surface. They are not interchangeable with itinerary-level KTAPI Fee lines.
Hosting
The platform serves tenant UIs at:
- Path-based:
https://journeys.edge.{env}.kaptioapis.com/{tenantId}/ - Custom domain: Customer CNAMEs their booking domain to the journeys ingress (e.g.
book.example.com)
Custom domains use GKE ManagedCertificates for TLS — the platform provisions certificates automatically once DNS is pointed.
What you configure
| Area | Where |
|---|---|
| Booking steps and order | journey.yaml → steps |
| Channels (B2C, B2B) | journey.yaml → channels |
| Branding (logo, color, font) | journey.yaml → branding |
| Behaviour (currency, deposit display, AI features) | journey.yaml → behavior |
| HTML shell (title, favicon, meta, CDN dependencies) | journey.yaml → ui |
| Catalog model and metadata (room tiers; optional vessels/deck plans) | journey.yaml → live.catalog_model and catalog |
| Commercial IDs (packages, tax profiles, channels) | journey.yaml → live |
| The booking UI itself | journeys/src/ (tenant-owned React/JSX) |
The full field-by-field reference is in journey.yaml reference.