# WebView

Zamna WebView is a hosted React SPA that implements the full Ready To Fly passenger UI on top of the Ready To Fly API. It handles consent, travel document verification, questions, checklist item resolution, and completion — so airlines do not need to build this UI themselves.

# 1. Overview

Two integration modes are supported:

Mode Use case
Browser Airline web check-in links the passenger to WebView in the browser
Embedded Airline native iOS/Android app hosts WebView in-process

The airline deploys the full Zamna stack. The WebView is served from a separate frontend host; the backend API runs on its own host. All API calls are made inside the WebView using the JWT issued by /start2 — the client app does not call any RTF API endpoints directly.

For the passenger flow inside WebView (wizard steps, API calls per step), see Ready To Fly — Flow.

# 2. Browser integration

# Booking ID encryption

The airline backend encrypts booking data using a shared AES/RSA key, then encodes the result as:

url_encode(base64_encode(encrypted_booking_data))

The final value is passed as the encrypted_booking_id query parameter. URL-encoding is required because base64 output contains +, /, and = characters that are not safe in query strings.

The encrypted value is passed to the web or mobile app, which uses it to call /start or /start2 — no raw booking data is exposed to the client.

High-level API authentication model

See also Ready To Fly — Authentication model.

# /start2 — browser redirect initiation

Entry point for both browser and embedded flows. The backend creates or resumes a MultiPax session and responds with 302 redirect to the WebView.

All URL-valued parameters (redirect_url, return_url) must be URL-encoded when constructing the /start2 query string, since they contain ://, /, ?, and & characters.

Param Required Description
encrypted_booking_id Yes url_encode(base64_encode(encrypted_booking_data))
redirect_url Yes URL-encoded base URL of the WebView frontend (trailing slash recommended). Backend appends session path and JWT
return_url No (recommended for browser) URL-encoded URL where the passenger is sent after completion. Appended with ?ready_to_fly=true on success; shown on error/ineligible screens
pax_ids No Comma-separated DCS passenger keys. Omit for all passengers; provide one key for single-pax embedded flows
consented No true/false — pre-set consent at session creation, skips consent step in WebView
locale No BCP 47 language tag (eg en-US, es-MX). Falls back to client-configured default. Alias: language
mode No Pass embedded for native app integration (see §3). Omit for browser
departure_station No IATA code to select journey leg when multiple future journeys exist. Alias: departureCity
encryption_mode No Encryption mode for booking id decryption (eg AES_CBC)

On success:

302 → {redirect_url}/session/{sessionId}/?pax_check_token={jwt}&locale=...&return_url=...&chosen_pax_sessions=...

On error:

302 → {redirect_url}/not-found/
302 → {redirect_url}/ineligible/

(with return_url appended if provided)

redirect_url vs return_url:

  • redirect_url — base URL of the WebView SPA. The backend builds the session URL by appending the session path and token to this base. Required on every /start2 call.
  • return_url — where the passenger goes after completing (or exiting) the RTF flow. The WebView navigates the browser to return_url?ready_to_fly=true on success, or shows a button back to return_url on ineligible/not-found screens. In embedded mode this URL is unused — completion is signalled via the native bridge closeFlow event.

Links: swagger (opens new window), redoc (opens new window)

# /start — programmatic session creation

JSON API alternative — returns session data directly, no redirect. Used when the airline backend creates the session server-side and passes the token to a frontend or mobile app (alternative auth model — see Ready To Fly — Authentication model).

Param Required Description
encrypted_booking_id Yes url_encode(base64_encode(encrypted_booking_data))
consented No true/false
pax_ids No Comma-separated DCS passenger keys
encryption_mode No Encryption mode (eg AES_CBC)

Response:

{
  "data": {
    "session_id": "...",
    "pax_check_token": "...",
    "session": { ... }
  }
}

Links: swagger (opens new window), redoc (opens new window)

# 3. Embedded WebView integration (iOS / Android)

# Overview

The native app embeds Zamna WebView as an in-app WebView component (iOS WKWebView / Android WebView).

The app loads a single URL — the /start2 endpoint with mode=embedded — and does nothing else to initialise the session. The backend 302 redirect is followed automatically inside the WebView component. The app does not need to:

  • Intercept the Location header
  • Parse pax_check_token, sessionId, or chosen_pax_sessions from the redirect
  • Build or load the session URL itself

The WebView communicates progress and completion back to the native shell via a JSON message bridge.

# Loading the WebView

Construct the /start2 URL with mode=embedded, pax_ids (single passenger DCS key for per-passenger flows), URL-encoded redirect_url (WebView frontend host), and optionally consented=true and locale:

https://{zamna-backend-host}/start2
  ?encrypted_booking_id={url_encoded_base64_encrypted_data}
  &redirect_url={url_encoded_webview_host}
  &mode=embedded
  &pax_ids={dcsPassengerKey}
  &locale=en-US
  &consented=true

Requirements:

Requirement Detail
Camera Grant getUserMedia video to the WebView origin (no microphone)
JavaScript Required
Redirects Must follow HTTP 302 from /start2 to WebView frontend — do not intercept
Cookies Not required — auth is JWT in query → Bearer header
External links Handle openExternalLink — open in SFSafariViewController / Chrome Custom Tab

After the 302, the WebView lands on the session URL automatically. The app does not need to interact with that URL.

# Web → Native bridge events

All messages use the envelope:

{ "type": "<event>", "payload": { ... }, "version": "1" }

Delivery:

  • iOS: window.webkit.messageHandlers.zamna.postMessage(message) — pass the object directly (not stringified)
  • Android: window.ZamnaBridge.postMessage(JSON.stringify(message)) — pass as JSON string
Event When Payload
flowReady Session loaded, first interactive screen shown { sessionId: string }
documentSaved A checklist item transitions to RESOLVED { paxSessionId: string, itemType: string }
paxReadyToFly One passenger reaches READY_TO_FLY { paxSessionId: string, checklist: [{ itemType, status }] }
allPaxReadyToFly All passengers in the session are READY_TO_FLY { sessionId: string }
closeFlow Terminal state — app must dismiss WebView { reason: string }
openExternalLink User taps an external link (eg ESTA website) { url: string }
error Unrecoverable client error { code: string, message: string }

paxReadyToFly.checklist entries:

Field Source
itemType Checklist item type, plus /{item_territory} when non-null (eg VISA/USA). Travel docs may appear as TRAVEL_DOC
status NOT_YET_RESOLVED, VERIFICATION_REQUIRED, or RESOLVED

closeFlow reasons:

Reason When
user_closed Passenger backed out with no more in-app navigation history
ready_to_fly Passenger(s) completed the full RTF flow
ineligible Booking/passenger not eligible for online verification
not_found Invalid or expired session, booking not found
outage Platform outage detected

# Native → Web (back button)

Send via webView.evaluateJavaScript:

window.postMessage({"type":"backButton"}, "<webview-origin>")

The WebView handles in-app back navigation first. If there is no prior screen, it emits closeFlow { reason: "user_closed" }.

# What the app should persist

App state Bridge signal
Per-document progress documentSaved (itemType + status)
Passenger RTF status paxReadyToFly (checklist snapshot)
Booking fully complete allPaxReadyToFly

On closeFlow, dismiss the WebView regardless of reason.

# Embedded vs browser

Scenario Browser (default) Embedded (mode=embedded)
Completion Redirect return_url?ready_to_fly=true closeFlow { reason: "ready_to_fly" }
Ineligible Show return button → return_url closeFlow { reason: "ineligible" }
Not found Show return button → return_url closeFlow { reason: "not_found" }
Outage Show outage page closeFlow { reason: "outage" }
External links Normal <a target="_blank"> openExternalLink { url } → app opens system browser
Back navigation Browser back button Native sends backButton message

Embedded WebView sequence diagram

# 4. Analytics

WebView registers events and submits them to the abstract Events Layer, from which the relevant adapters fire them to respective analytics platforms (eg Google/Adobe Analytics).

Please refer to the detailed reference for event parameters, page paths, and custom dimensions.