journey.yaml reference
This page documents every field in journey.yaml — the configuration file that defines your booking experience. The Meridian Voyages examples preserve the cruise reference implementation; a separate group-touring example shows the same contract without a vessel or deck plan.
The file lives at journeys/journey.yaml in your tenant config repo (or tenants/{tenantId}/journeys/journey.yaml for internal tenants in edge-configs).
tenant_id / journey_id
tenant_id: meridian
journey_id: meridian-cruise
| Field | Required | Description |
|---|---|---|
tenant_id | Yes | Must match the tenant identifier used in API calls and the config stub in edge-configs. |
journey_id | Yes | A unique identifier for this journey definition. Used in logging and diagnostics. |
channels
Defines the available booking channels. At least one channel is required.
channels:
- id: b2c-direct
label: "Book Direct"
type: b2c
requires_advisor_id: false
- id: b2b-advisor
label: "Travel Advisor"
type: b2b
requires_advisor_id: true
| Field | Type | Default | Description |
|---|---|---|---|
id | string | — | Unique channel identifier. Referenced in live.channel_map. |
label | string | — | Display name shown in the channel picker UI. |
type | b2c | b2b | — | Channel type. B2B channels show advisor identification before the booking flow. |
requires_advisor_id | boolean | false | When true, the guest must identify their travel advisor (IATA lookup) before proceeding. |
When only one channel is defined, the channel picker is skipped and the flow starts immediately.
steps
An ordered list of step identifiers that defines the booking flow sequence.
steps:
- trip-select
- departure-travellers
- cabin-category
- cabin-pick
- activities-quote
- review-pay
- confirmation
Canonical step IDs
| Step ID | Purpose | Framework behaviour |
|---|---|---|
trip-select | Browse and select a trip/package | — |
departure-travellers | Choose departure date, adults, children, solo | Sets basket occupancy context |
cabin-category | Select a room/cabin category tier | Advances to cabin-pick if present |
cabin-pick | Pick a room option, or a specific cruise cabin from a deck plan | The shared immersive renderer is cruise-specific; touring UIs normally render their own room-option step |
room-select | Choose a touring room option | First-class neutral alias that advances through the same selection boundary without a cruise deck plan |
activities-quote | Choose add-on activities | Optionally triggers AI quote letter |
review-pay | Review basket totals and complete payment | Deposit vs full payment based on schedule |
confirmation | Show booking reference and welcome content | — |
Step ordering rules
- Immersive cruise cabin selection (deck plan with live availability overlays) renders only when
cabin-pickappears in the steps list AND comes afterdeparture-travellers. - Steps after
cabin-pickare gated — the guest cannot advance without choosing the required room or cabin option. - Touring room selection uses
room-select; it is also gated and advances when the room option has been selected. - Custom step IDs are allowed for tenant-specific screens; the framework passes unrecognised IDs to the tenant's step renderer.
branding
Visual identity metadata available to the tenant UI.
branding:
logo_url: https://assets.example.com/meridian-voyages/logo.svg
primary_color: "#1B365D"
font_family: "Inter, system-ui, sans-serif"
| Field | Type | Description |
|---|---|---|
logo_url | string | URL of the tenant logo, displayed in the journey chrome. |
primary_color | string | Hex color code for the primary brand accent. |
font_family | string | CSS font-family stack. |
These values are available to tenant code via the /api/journeys/v1/config endpoint. Framework components use CSS custom properties for theming — see Tenant UI source.
behavior
Controls journey-wide behavioural switches.
behavior:
deposit_display: true
currency: USD
ai_quote_letter: true
default_occupancy: 2
| Field | Type | Default | Description |
|---|---|---|---|
deposit_display | boolean | true | Whether deposit amounts and balance-due dates are shown in the review step. |
currency | string | USD | Default display currency (ISO 4217). The tenant UI may allow guests to switch currencies. |
ai_quote_letter | boolean | false | Enables the AI-generated quote/welcome letter feature (Anthropic integration). |
default_occupancy | integer | 2 | Default number of adults when occupancy is not specified. Minimum 1. |
ui
Controls the HTML shell that wraps the tenant's bundled UI. These fields are injected at bundle time by the platform's esbuild pipeline.
ui:
title: "Meridian Voyages — Book Your Cruise"
favicon_url: "https://assets.example.com/meridian-voyages/favicon.ico"
meta:
description: "Book your expedition cruise with Meridian Voyages"
og:title: "Meridian Voyages Booking"
og:image: "https://assets.example.com/meridian-voyages/og-image.jpg"
dependencies:
framer-motion: "https://esm.sh/framer-motion@11"
zustand: "https://esm.sh/zustand@4"
| Field | Type | Default | Description |
|---|---|---|---|
title | string | "{tenantId} — Journey" | The HTML <title> tag. |
favicon_url | string | none | URL for the page favicon (<link rel="icon">). |
meta | Record<string, string> | none | Key-value pairs rendered as <meta> tags. Keys starting with og: use property attribute; others use name. |
dependencies | Record<string, string> | none | Additional entries added to the ESM import map beyond React. Keys are bare module specifiers; values are CDN URLs. |
Import map
The platform provides React 18 in the import map by default:
{
"imports": {
"react": "https://esm.sh/react@18.3.1",
"react-dom": "https://esm.sh/react-dom@18.3.1",
"react-dom/client": "https://esm.sh/react-dom@18.3.1/client",
"react/jsx-runtime": "https://esm.sh/react@18.3.1/jsx-runtime"
}
}
Entries from ui.dependencies are merged into this map. Your tenant UI can then import those packages by bare specifier without bundling them — they load from CDN at runtime.
catalog
Optional metadata that groups room/cabin options and, for cruise journeys, supplies vessel deck plans.
catalog:
category_tiers:
- name: Balcony Staterooms
codes: [balcony-sup, balcony-a, balcony-b, balcony-c]
sort_order: 1
- name: Horizon Staterooms
codes: [horizon-sup, horizon-sup-s, horizon-s, horizon-tw, horizon-tr]
sort_order: 2
- name: Suites
codes: [captain, junior]
sort_order: 3
vessels:
- code: meridian-explorer
name: Meridian Explorer
deck_plan: "https://assets.example.com/deck-plans/meridian-explorer.svg"
- code: meridian-voyager
name: Meridian Voyager
category_tiers
Groups room or cabin categories into display tiers for the category selection step.
| Field | Type | Default | Description |
|---|---|---|---|
name | string | — | Display name for the tier group (e.g. "Balcony Staterooms"). |
codes | string[] | — | List of category slugs or names belonging to this tier. Mapped to room/cabin categories from the catalog API. |
sort_order | number | 0 | Display order of the tier (ascending). |
vessels
Optional cruise vessel reference data for deck plan rendering. Omit this block for group touring.
| Field | Type | Description |
|---|---|---|
code | string | Vessel identifier (matched against catalog trip shipName or code). |
name | string | Display name. |
deck_plan | string | Optional URL to a deck plan asset (SVG or image). Used by the framework's DeckPlan component. |
provider
provider: live
| Value | Description |
|---|---|
mock | Uses fixture data for the catalog and simulated basket operations. No external dependencies. Ideal for local development and UI iteration. |
live | Connects to KTAPI (catalog), Basket Service (commercial operations), and Keycloak (auth). Requires the live: block. |
Default: mock.
live
Required when provider: live. Contains the per-tenant commercial identifiers the live provider needs to create baskets and read the catalog from your Salesforce org.
live:
catalog_model: cruise
package_filter:
package_ids:
- a299j000002M59ZAAS
tax_profile_id: a477F0000000YtgQAE
default_account_id: 001On00000fUpVLIA0
service_level_id: null
channel_map:
b2c-direct: a1K7F000001lZ6WUAU
from_price_currencies:
- USD
- AUD
sf_environment: null
Catalog model
catalog_model controls how live catalog inventory is interpreted:
| Value | Default | Behaviour |
|---|---|---|
cruise | Yes | Uses cruise details, cabin types, physical cabin inventory, and optional vessel/deck-plan metadata. |
touring | No | Uses active package departures and required PriceCategories package options as room configurations. From-prices and room availability come from package option pricing; no vessel or physical cabin is required. |
The neutral routes /catalog/trips and /catalog/rooms work for both values. The original /catalog/voyages and /catalog/cabins paths remain aliases, and their established response field names remain unchanged.
Package filter
Determines which packages from your org appear in the journey catalog.
| Field | Type | Description |
|---|---|---|
package_filter.package_ids | string[] | Explicit allow-list of KTAPI package Salesforce IDs. Environment-specific — prefer package_codes for cross-environment configs. |
package_filter.package_codes | string[] | Cross-environment package external codes. Resolved to IDs at runtime. |
package_filter.active_only | true | Include every active package returned by KTAPI for the tenant. |
You must provide either package_ids / package_codes or active_only — not both. The deprecated top-level live.package_ids field is accepted for backward compatibility but package_filter is preferred.
Commercial IDs
Each field has an _id variant (Salesforce record ID, environment-specific) and a _code variant (cross-environment external code, resolved at runtime). You must provide at least one variant for required fields.
| Field | Required | Description |
|---|---|---|
tax_profile_id / tax_profile_code | Yes (one) | The Salesforce tax profile applied to basket pricing. |
default_account_id / default_account_code | Yes (one) | Fallback Salesforce account for B2C guest bookings (when no account is identified). |
service_level_id / service_level_code | No | Package service level. null uses the package default. |
Channel map
Maps journey channel IDs (from channels[].id) to Salesforce channel record IDs or codes.
channel_map:
b2c-direct: a1K7F000001lZ6WUAU
b2b-advisor: a1K7F000001lZ6XIAU
Values that look like Salesforce IDs (15 or 18 characters starting with a known prefix) are used directly. Other values are treated as external codes and resolved at runtime.
Catalog pricing
| Field | Type | Default | Description |
|---|---|---|---|
from_price_currencies | string[] | ["USD"] | ISO currency codes for which catalog "from prices" are computed. Each currency costs a KTAPI call per departure — keep the list to currencies your guests actually use. |
Salesforce environment
| Field | Type | Default | Description |
|---|---|---|---|
sf_environment | string | null | null | The salesforce_environments key from blueprint.yaml where live bookings land. Used by enrichment lookups to skip per-environment itinerary searches. Set to null when not configured. |
external_ancillaries
Optional configuration for tenant-owned third-party service providers. The UI only exposes this feature when the block is present.
external_ancillaries:
providers:
- id: insurance
quote_url: https://insurance.example.com/v1/quotes
timeout_ms: 10000
auth:
credential_env: INSURANCE_API_TOKEN
header: Authorization
scheme: Bearer
persistence:
type: edge_composite
sf_environment: uat
apex_path: /services/apexrest/journeys/external-ancillaries
| Field | Required | Description |
|---|---|---|
providers[].id | Yes | Lowercase provider identifier used in the Journeys API path. |
providers[].quote_url | Yes | HTTPS endpoint called server-to-server for quotes. |
providers[].timeout_ms | No | Provider timeout from 500 to 30,000 ms. Default: 10,000 ms. |
providers[].auth.credential_env | No | Name of the runtime environment variable containing the credential. Never store the credential in YAML. |
providers[].auth.header | No | Authentication header. Default: Authorization. |
providers[].auth.scheme | No | Prefix applied to the credential. Default: Bearer. |
persistence.type | For checkout write-through | Must be edge_composite. |
persistence.sf_environment | No | Salesforce environment; falls back to live.sf_environment. |
persistence.apex_path | For checkout write-through | Existing Apex REST endpoint that accepts the verified selection contract. |
Production write-through also requires JOURNEYS_EDGE_COMPOSITE_URL and COMPOSITE_API_KEY in the Journeys runtime. When persistence is not fully configured, booking fails explicitly before KTAPI booking creation rather than dropping the external service.
See Third-party services for the complete trust and persistence flow.
Environment overrides
For per-environment configuration (e.g. different package IDs in staging vs production), create an overlay file:
journeys/
journey.yaml # Base configuration
journey.staging.yaml # Overrides for EDGE_ENVIRONMENT=staging
journey.production.yaml # Overrides for EDGE_ENVIRONMENT=production
The platform deep-merges the environment file into the base configuration. Arrays and primitives in the override replace base values; objects are recursively merged.
# journey.staging.yaml — only override what differs
live:
package_filter:
package_ids:
- a299j000002STAGING_ID
tax_profile_id: a477F000STAGING_TAX
default_account_id: 001On000STAGING_ACC
channel_map:
b2c-direct: a1K7F000STAGING_CH
The active environment is determined by the EDGE_ENVIRONMENT variable on the platform service.
Complete examples
Group touring (live provider)
This fictional example models a dated escorted tour with Twin and Single room choices. It contains no customer-specific identifiers:
tenant_id: example-touring
journey_id: example-group-tour
channels:
- id: b2c-direct
label: Book Direct
type: b2c
requires_advisor_id: false
- id: b2b-advisor
label: Travel Advisor
type: b2b
requires_advisor_id: true
steps:
- trip-select
- departure-travellers
- cabin-category
- cabin-pick
- activities-quote
- review-pay
- confirmation
branding:
logo_url: https://assets.example.com/example-touring/logo.svg
primary_color: "#174B45"
font_family: "Inter, system-ui, sans-serif"
behavior:
deposit_display: true
currency: AUD
ai_quote_letter: false
default_occupancy: 2
ui:
title: "Example Touring — Book Your Trip"
meta:
description: "Choose a departure and room configuration"
catalog:
category_tiers:
- name: Shared rooms
codes: [twin room]
sort_order: 1
- name: Single rooms
codes: [single room]
sort_order: 2
provider: live
live:
catalog_model: touring
package_filter:
package_codes:
- SOUTHERN-HIGHLANDS-12D
tax_profile_id: a47000000000001AAA
default_account_id: 001000000000001AAA
channel_map:
b2c-direct: a1K000000000001AAA
b2b-advisor: a1K000000000002AAA
from_price_currencies:
- AUD
The corresponding catalog exposes dated trips such as “Southern Highlands Explorer” and room rows such as “Twin Room” and “Single Room”. The room rows are required package options with live price and inventory context, not physical hotel-room assignments.
Mock provider (local development)
tenant_id: meridian
journey_id: meridian-cruise
channels:
- id: b2c-direct
label: "Book Direct"
type: b2c
requires_advisor_id: false
- id: b2b-advisor
label: "Travel Advisor"
type: b2b
requires_advisor_id: true
steps:
- trip-select
- departure-travellers
- cabin-category
- cabin-pick
- activities-quote
- review-pay
- confirmation
branding:
logo_url: https://assets.example.com/meridian-voyages/logo.svg
primary_color: "#1B365D"
font_family: "Inter, system-ui, sans-serif"
behavior:
deposit_display: true
currency: USD
ai_quote_letter: true
provider: mock
Live provider (staging/production)
tenant_id: meridian
journey_id: meridian-cruise
channels:
- id: b2c-direct
label: Book Direct
type: b2c
requires_advisor_id: false
steps:
- trip-select
- departure-travellers
- cabin-category
- cabin-pick
- activities-quote
- review-pay
- confirmation
branding:
logo_url: https://assets.example.com/meridian-voyages/logo.svg
primary_color: "#1B365D"
font_family: "Inter, system-ui, sans-serif"
behavior:
deposit_display: true
currency: USD
ai_quote_letter: true
default_occupancy: 2
ui:
title: "Meridian Voyages — Book Your Cruise"
favicon_url: "https://assets.example.com/meridian-voyages/favicon.ico"
meta:
description: "Book your expedition cruise with Meridian Voyages"
catalog:
category_tiers:
- name: Balcony Staterooms
codes: [balcony-sup, balcony-a, balcony-b, balcony-c]
sort_order: 1
- name: Horizon Staterooms
codes: [horizon-sup, horizon-sup-s, horizon-s, horizon-tw, horizon-tr]
sort_order: 2
- name: Suites
codes: [captain, junior]
sort_order: 3
vessels:
- code: meridian-explorer
name: Meridian Explorer
- code: meridian-voyager
name: Meridian Voyager
provider: live
live:
catalog_model: cruise
package_filter:
package_ids:
- a299j000002M59ZAAS
tax_profile_id: a477F0000000YtgQAE
default_account_id: 001On00000fUpVLIA0
service_level_id: null
channel_map:
b2c-direct: a1K7F000001lZ6WUAU
from_price_currencies:
- USD
- AUD
sf_environment: null