travel.book_flight — Full Intent Specification
INTENT NAMESPACE: travel
INTENT NAME: book_flight
FULL ID: travel.book_flight
VERSION: v1.0.0
STATUS: draft
LAST UPDATED: 2026-05-10
TTBS WEIGHTS: time 0.40 · taste 0.10 · budget 0.30 · safety 0.20
Flight booking is fundamentally different from hotel: time-critical (cannot miss departure), seat-based pricing, multi-leg/round-trip/one-way, fare class hierarchy, baggage rules, ancillary upgrades. Distinct from mobility.book_intercity_ride because it crosses cities/countries via airline, with airport check-in protocol and airline-specific schedules. Locked structural fields: (a) journey_kind (one_way / round_trip / multi_city); (b) legs[] with origin/destination/scheduled_departure_iso; (c) fare_class enum (economy/premium_economy/business/first); (d) baggage_allowance block (cabin/checkin); (e) ancillaries (seat selection, meal, priority boarding); (f) pnr for held-bookings.
1. NATURAL LANGUAGE COVERAGE
Classifies IN
- "flight from Hyderabad to Bangalore tomorrow"
- "Indigo flight to Mumbai next Friday"
- "round-trip flight Delhi-Goa June 15-22"
- "cheapest flight to Singapore"
- "business class to London"
- "morning flight Hyderabad to Chennai"
- "Air India flight to NYC"
- "non-stop flight Bangalore Mumbai"
- "multi-city: Hyderabad-Delhi-Mumbai"
Classifies OUT — borderline NO
- "Hyderabad to Bangalore cab" →
mobility.book_intercity_ride - "train to Vijayawada" →
travel.book_train - "bus to Tirupati" →
travel.book_bus - "tour package to Bali" →
travel.book_package - "hotel near Bangalore airport" →
travel.book_hotel
MULTI-INTENT TRIGGERS
- "flight to Goa and hotel" →
travel.book_flight+travel.book_hotel - "flight to Bangalore and airport pickup" →
travel.book_flight+mobility.book_airport_transfer - "flight + visa for Singapore" →
travel.book_flight+travel.book_visa_assistance
2. INPUT — TOMO → PROVIDER
{
"intent": "travel.book_flight",
"intent_version": "v1.0.0",
"request_id": "req_flt_8h2k_2026-05-10T08:00:00Z",
"user_session_id": "anon_user_token_or_uid",
"journey_kind": "round_trip",
"legs": [
{
"leg_index": 1,
"origin_iata": "HYD",
"origin_city": "Hyderabad",
"origin_country_code": "IN",
"destination_iata": "BLR",
"destination_city": "Bangalore",
"destination_country_code": "IN",
"scheduled_departure_iso": "2026-06-15T07:00:00+05:30",
"scheduled_arrival_iso": "2026-06-15T08:30:00+05:30",
"preferred_departure_window_minutes": 120
},
{
"leg_index": 2,
"origin_iata": "BLR",
"origin_city": "Bangalore",
"origin_country_code": "IN",
"destination_iata": "HYD",
"destination_city": "Hyderabad",
"destination_country_code": "IN",
"scheduled_departure_iso": "2026-06-18T19:00:00+05:30",
"scheduled_arrival_iso": "2026-06-18T20:30:00+05:30",
"preferred_departure_window_minutes": 180
}
],
"passengers": {
"adult_count": 2,
"child_count_2_to_11": 1,
"infant_count_under_2": 0,
"passenger_kyc_kind": "indian_aadhaar"
},
"preferences": {
"fare_class_acceptable": ["economy", "premium_economy"],
"fare_class_preferred": "economy",
"max_stops_per_leg": 0,
"max_layover_minutes": 180,
"airline_preferred": ["6E", "AI"],
"airline_avoid": [],
"alliance_preferred": "any",
"departure_time_window_kind": "morning",
"arrival_time_window_kind": "any",
"non_stop_required": true,
"checked_baggage_count": 2,
"checked_baggage_weight_kg": 23,
"cabin_baggage_count": 2,
"meal_preference": "veg",
"seat_kind_preferred": "aisle",
"wheelchair_assistance": false,
"unaccompanied_minor_assist": false,
"priority_boarding_required": false,
"free_cancellation_required": false,
"free_change_required": false,
"budget_band": "good",
"budget_max_inr_total": 14000,
"online_payment_required": true,
"loyalty_program_card_kind": ["6e_rewards", "indigo_blue"],
"loyalty_member_id": ""
},
"context": {
"user_locale": "en-IN",
"user_currency_pref": "INR",
"trip_purpose": "leisure",
"is_business_corporate": false,
"trust_signals": {
"is_repeat_customer": true,
"prior_flight_bookings": 8,
"user_account_age_days": 312,
"verified_phone": true,
"passport_verified": true,
"pan_verified": true
}
}
}
| Field | Type | Constraint | Notes |
|---|---|---|---|
intent |
string | REQUIRED, equals "travel.book_flight" |
|
journey_kind |
enum | REQUIRED, STRICT one_way | round_trip | multi_city |
|
legs |
array | REQUIRED, ≥1 | one_way=1, round_trip=2, multi_city=≥2 |
legs[].leg_index |
int | REQUIRED, ≥1, contiguous | |
legs[].origin_iata |
string | REQUIRED, 3 chars | IATA code |
legs[].origin_country_code |
string | REQUIRED, ISO_3166_2 | |
legs[].destination_iata |
string | REQUIRED, 3 chars | |
legs[].destination_country_code |
string | REQUIRED, ISO_3166_2 | |
legs[].scheduled_departure_iso |
ISO_DATETIME | REQUIRED | |
legs[].scheduled_arrival_iso |
ISO_DATETIME | REQUIRED | |
legs[].preferred_departure_window_minutes |
int | REQUIRED, ≥0 | tolerance |
passengers.adult_count |
int | REQUIRED, ≥1 | |
passengers.child_count_2_to_11 |
int | REQUIRED, ≥0 | |
passengers.infant_count_under_2 |
int | REQUIRED, ≥0 | typically lap-infant |
passengers.passenger_kyc_kind |
enum | REQUIRED, see §5 | drives ID flow |
preferences.fare_class_acceptable |
array |
REQUIRED, ≥1 | see §5 |
preferences.max_stops_per_leg |
int | REQUIRED, ≥0 | 0 = non-stop only |
preferences.max_layover_minutes |
int | REQUIRED, ≥0 | for connecting flights |
preferences.airline_preferred |
array |
REQUIRED, may be empty | IATA airline codes |
preferences.airline_avoid |
array |
REQUIRED, may be empty | |
preferences.alliance_preferred |
enum | REQUIRED, see §5 | star_alliance | skyteam | oneworld | any |
preferences.departure_time_window_kind |
enum | REQUIRED, see §5 | |
preferences.non_stop_required |
bool | REQUIRED | hard filter when true |
preferences.checked_baggage_count |
int | REQUIRED, ≥0 | |
preferences.checked_baggage_weight_kg |
int | REQUIRED, ≥0 | |
preferences.cabin_baggage_count |
int | REQUIRED, ≥0 | |
preferences.meal_preference |
enum | REQUIRED, see §5 | |
preferences.seat_kind_preferred |
enum | REQUIRED, STRICT aisle | window | middle | any |
|
preferences.wheelchair_assistance |
bool | REQUIRED | |
preferences.unaccompanied_minor_assist |
bool | REQUIRED | |
preferences.priority_boarding_required |
bool | REQUIRED | |
preferences.free_cancellation_required |
bool | REQUIRED | |
preferences.free_change_required |
bool | REQUIRED | |
preferences.loyalty_program_card_kind |
array |
REQUIRED, may be empty | see §5 |
context.is_business_corporate |
bool | REQUIRED | drives corporate-fare visibility |
Anti-fabrication preamble (universal): no paid placement, no urgency text, no commission-influenced fields.
3. PROVIDER TOOLS
Tool 1: search_flights
PURPOSE: return ranked flight options across airlines + fare classes
INPUT: §2 request body
OUTPUT: { results: FlightOption[], result_token, expires_at }
SLA: p50 < 800ms, p95 < 2000ms
RATE LIMIT: ≤ 1/sec per user
Tool 2: get_fare_rules_and_breakdown
PURPOSE: full fare rules for a specific option (cancellation, change, baggage, etc.)
INPUT: { option_id, request_id }
OUTPUT: FareRulesAndBreakdown (§4)
SLA: p95 < 800ms
Tool 3: lock_seat_or_ancillaries
PURPOSE: select specific seat + add meals/priority boarding before booking
INPUT: { option_id, seat_choices[], ancillaries[], request_id }
OUTPUT: { ancillary_total_inr, locked_until_iso }
SLA: p95 < 1500ms
Tool 4: book_flight
PURPOSE: commit booking
INPUT: { option_id, passenger_details, payment_token, request_id, idempotency_key, user_phone }
OUTPUT: { pnr, booking_ref, status, total_inr, ticket_url, e_tickets_per_passenger[] }
SLA: p95 < 8000ms
IDEMPOTENCY: REQUIRED
Tool 5: track_pnr_status
PURPOSE: live PNR status (cancellations, schedule changes, gate updates)
INPUT: { pnr, request_id }
OUTPUT: FlightTrack (§4)
SLA: p95 < 600ms
RATE LIMIT: ≤ 1 every 5min
Tool 6: cancel_flight
INPUT: { booking_ref, reason, request_id }
OUTPUT: { status, cancellation_charge_inr, refund_amount_inr, refund_processing_days }
SLA: p95 < 4000ms
Tool 7: change_flight
PURPOSE: modify dates / passenger / etc.
INPUT: { booking_ref, modifications, request_id }
OUTPUT: { revised_total_inr, change_fee_inr, fare_difference_inr, new_legs }
SLA: p95 < 4000ms
Tool 8: web_check_in
PURPOSE: partner-mediated web check-in
INPUT: { booking_ref, passenger_pax_index, seat_choice_optional, request_id }
OUTPUT: { boarding_pass_url, gate, seat_confirmed }
SLA: p95 < 3000ms
All eight REQUIRED.
4. RESPONSE SHAPE
FlightOption
id: string, REQUIRED
option_token: string, REQUIRED
expires_at: ISO_DATETIME, REQUIRED
journey_kind: STRICT ENUM, REQUIRED
total_legs: int, REQUIRED, ≥1
legs: array, REQUIRED, ≥1
- leg_index: int, REQUIRED
leg_kind: STRICT ENUM, REQUIRED # outbound | inbound | segment_n
flight_segments: array, REQUIRED, ≥1 # if non-stop, length 1
- segment_index: int, REQUIRED
airline_iata: string, REQUIRED
airline_name: string, REQUIRED
flight_number: string, REQUIRED # "6E-432"
operating_carrier_iata: string, REQUIRED # if codeshare
aircraft_kind: STRICT ENUM, REQUIRED # see §5
origin_iata: string, REQUIRED
origin_terminal: string, REQUIRED
destination_iata: string, REQUIRED
destination_terminal: string, REQUIRED
scheduled_departure_iso: ISO_DATETIME, REQUIRED
scheduled_arrival_iso: ISO_DATETIME, REQUIRED
duration_minutes: int, REQUIRED, ≥1
layover_minutes: int, REQUIRED # 0 if first segment
leg_total_duration_minutes: int, REQUIRED
leg_layover_count: int, REQUIRED, ≥0
leg_stops_count: int, REQUIRED, ≥0
leg_changes_required: array<string>, REQUIRED, may be empty # ["change in DEL"]
is_overnight_leg: boolean, REQUIRED
fare:
base_fare_inr: INR_INTEGER, REQUIRED
taxes_and_surcharges_inr: INR_INTEGER, REQUIRED
airport_dev_fee_inr: INR_INTEGER, REQUIRED
fuel_surcharge_inr: INR_INTEGER, REQUIRED
user_dev_fee_inr: INR_INTEGER, REQUIRED
meal_charge_inr: INR_INTEGER, REQUIRED # 0 if not selected
seat_charge_inr: INR_INTEGER, REQUIRED # 0 if random
baggage_charge_inr: INR_INTEGER, REQUIRED # 0 if standard
priority_boarding_charge_inr: INR_INTEGER, REQUIRED # 0 if not selected
insurance_inr: INR_INTEGER, REQUIRED # 0 if not added
convenience_fee_inr: INR_INTEGER, REQUIRED
gst_inr: INR_INTEGER, REQUIRED
total_inr: INR_INTEGER, REQUIRED
fare_breakdown_text: string, REQUIRED
is_upfront_fare: boolean, REQUIRED
fare_locked_until_iso: ISO_DATETIME, REQUIRED
fare_class: STRICT ENUM, REQUIRED # see §5
fare_brand_kind: STRICT ENUM, REQUIRED # see §5; saver | flex | etc.
baggage_allowance:
cabin_count_per_pax: int, REQUIRED
cabin_weight_kg_per_pax: int, REQUIRED
cabin_size_inches: string, REQUIRED # "55x35x25"
checkin_count_per_pax: int, REQUIRED
checkin_weight_kg_per_pax: int, REQUIRED
checkin_size_inches: string, REQUIRED
excess_baggage_inr_per_kg: INR_INTEGER, REQUIRED
free_baggage_at_pre_book: boolean, REQUIRED
charged_baggage_at_pre_book: boolean, REQUIRED
amenities_per_segment: array, REQUIRED, ≥1
- segment_index: int, REQUIRED
seat_pitch_inches: int, REQUIRED
seat_recline_degrees: int, REQUIRED # 0 if no recline
in_seat_power: boolean, REQUIRED
usb_charger: boolean, REQUIRED
wifi_available: boolean, REQUIRED
wifi_kind: STRICT ENUM, REQUIRED # see §5
in_flight_entertainment: STRICT ENUM, REQUIRED # none | seat_screen | personal_device
in_flight_meal_kind: STRICT ENUM, REQUIRED # see §5
leg_room_kind: STRICT ENUM, REQUIRED # standard | extra | premium
cancellation:
free_cancel_until_iso: ISO_DATETIME, REQUIRED # may equal "never_free"
free_cancel_kind: STRICT ENUM, REQUIRED # see §5
cancellation_fee_24h_inr: INR_INTEGER, REQUIRED
cancellation_fee_2h_inr: INR_INTEGER, REQUIRED
no_show_loss_pct: float, REQUIRED, 0-1
refund_processing_days: int, REQUIRED, ≥0
partial_refund_supported: boolean, REQUIRED
change:
free_change_supported: boolean, REQUIRED
change_fee_inr: INR_INTEGER, REQUIRED
fare_difference_charged: boolean, REQUIRED
changes_allowed_count: int, REQUIRED # -1 = unlimited
ancillaries_offered:
meal_options: array<STRICT ENUM>, REQUIRED # see §5
meal_inr_per_segment: INR_INTEGER, REQUIRED
seat_selection_inr_per_segment: INR_INTEGER, REQUIRED # 0 if free
priority_boarding_inr: INR_INTEGER, REQUIRED
insurance_kinds_offered: array<STRICT ENUM>, REQUIRED
insurance_inr_per_pax: INR_INTEGER, REQUIRED
lounge_access_inr_per_pax: INR_INTEGER, REQUIRED # 0 if not offered
fast_track_security_inr: INR_INTEGER, REQUIRED
frequent_flyer:
loyalty_eligible: boolean, REQUIRED
loyalty_program_kinds: array<STRICT ENUM>, REQUIRED # if eligible
miles_earned_estimate: int, REQUIRED
miles_redeemed_estimate: int, REQUIRED # if user opted
route_quality:
on_time_arrival_30day_pct: float, REQUIRED, 0-1 # for the airline+route pair
cancellation_30day_pct: float, REQUIRED, 0-1
delay_minutes_30day_avg: int, REQUIRED # average delay if delayed
baggage_delivery_30day_avg_minutes: int, REQUIRED # baggage carousel time
pet_baggage_handling_record: STRICT ENUM, REQUIRED # excellent | good | fair | poor
trust:
airline_iata_registered: boolean, REQUIRED
airline_iata_number: string, REQUIRED
airline_dgca_registered: boolean, REQUIRED # for India operations
iosa_certified: boolean, REQUIRED # IATA Operational Safety Audit
faa_part_121_or_equivalent: boolean, REQUIRED # operational standards
insurance_coverage_inr: INR_INTEGER, REQUIRED
partner_account_age_days: int, REQUIRED, ≥0
partner_flight_bookings_30d: int, REQUIRED, ≥0
partner_completion_rate_30d: float, REQUIRED, 0-1
freshness:
data_last_synced_iso: ISO_DATETIME, REQUIRED
_provider:
name: string, REQUIRED
tomo_partner_id: string, REQUIRED
partner_tier: STRICT ENUM, REQUIRED
deep_link: URL, REQUIRED
customer_support_phone: string, REQUIRED
customer_support_email: string, REQUIRED
customer_support_24x7: boolean, REQUIRED
in_app_chat_supported: boolean, REQUIRED
FareRulesAndBreakdown
(Detailed fare rules, baggage rules, change conditions per leg per segment. All fields REQUIRED.)
FlightTrack
pnr: string, REQUIRED
status: STRICT ENUM, REQUIRED # see §5
status_updated_iso: ISO_DATETIME, REQUIRED
status_history: array, REQUIRED, ≥1
current_legs: array, REQUIRED, ≥1
- leg_index: int, REQUIRED
current_status: STRICT ENUM, REQUIRED # see §5
delay_minutes_observed: int, REQUIRED # 0 if on-time
cancelled: boolean, REQUIRED
rebooked_to_pnr: string, REQUIRED # may be empty
gate: string, REQUIRED # may be empty until announced
boarding_iso: ISO_DATETIME, REQUIRED # may equal future
actual_departure_iso: ISO_DATETIME, REQUIRED # may equal future
actual_arrival_iso: ISO_DATETIME, REQUIRED
web_check_in_state:
open: boolean, REQUIRED
open_iso: ISO_DATETIME, REQUIRED
close_iso: ISO_DATETIME, REQUIRED
available_seats_count: int, REQUIRED, ≥0
baggage_state:
pre_paid: boolean, REQUIRED
excess_alert: boolean, REQUIRED # if user's baggage exceeds limit
excess_charge_estimated_inr: INR_INTEGER, REQUIRED
support_phone: string, REQUIRED
support_email: string, REQUIRED
Forbidden fields
paid_placement_score | sponsored_rank | promotion_priority |
fake_on_time_arrival_30day_pct | auto_inflate_loyalty_miles |
fake_cancellation_30day_pct | hidden_baggage_charge |
fake_iosa_certified | fake_dgca_registered | hidden_convenience_fee
5. CONTROLLED VOCABULARIES
journey_kind
one_way | round_trip | multi_city
passengers.passenger_kyc_kind
indian_aadhaar | indian_pan | indian_passport | foreign_passport |
voter_id | driving_license | other
preferences.fare_class_acceptable[] and FlightOption.fare_class
economy | premium_economy | business | first
FlightOption.fare_brand_kind
saver_no_meal_no_seat | standard | flex_changeable_no_change_fee |
flex_full_refund_with_fee | corporate | luxury_first |
ultra_low_cost | full_service
legs[].leg_kind
outbound | inbound | segment_1 | segment_2 | segment_n
flight_segments[].aircraft_kind
boeing_737 | boeing_777 | boeing_787 | boeing_747 |
airbus_a320 | airbus_a321 | airbus_a330 | airbus_a350 | airbus_a380 |
embraer_175 | bombardier_q400 | atr_72 | private_jet | other
preferences.alliance_preferred
star_alliance | skyteam | oneworld | none | any
preferences.departure_time_window_kind
early_morning_5_to_8 | morning_8_to_12 | afternoon_12_to_4 |
evening_4_to_8 | night_8_to_12 | red_eye_12_to_5 | any
preferences.meal_preference
veg | non_veg | jain | vegan | halal | kosher | gluten_free |
diabetic | low_sodium | seafood | none | any
preferences.seat_kind_preferred
aisle | window | middle | any
preferences.loyalty_program_card_kind[]
6e_rewards | indigo_blue | club_vistara | flying_returns_air_india |
spice_club | go_first_max | krisflyer | mileage_plus | privilege_club |
none
amenities_per_segment[].wifi_kind
none | free_basic | paid_premium | gate_to_gate_paid
amenities_per_segment[].in_flight_entertainment
none | seat_screen | personal_device | streaming_to_phone | sky_lounge_only
amenities_per_segment[].in_flight_meal_kind
none | snack_only | hot_meal | premium_meal | a_la_carte_paid | first_class_dining
amenities_per_segment[].leg_room_kind
standard | extra | premium | exit_row | bulkhead
cancellation.free_cancel_kind
never_free | within_24h_of_booking | within_grace_window_at_purchase |
within_72h_of_departure | within_24h_of_departure | always_partial
ancillaries_offered.meal_options[]
veg_indian | non_veg_indian | continental | jain_meal | vegan |
hindu_non_veg | muslim_meal | kosher | low_calorie | child_meal |
infant_meal | none
ancillaries_offered.insurance_kinds_offered[]
trip_protect | medical_emergency | flight_cancellation_protection |
baggage_loss_protection | none
frequent_flyer.loyalty_program_kinds[]
Same enum as preferences.loyalty_program_card_kind.
route_quality.pet_baggage_handling_record
excellent | good | fair | poor | not_supported
FlightTrack.status
booked_pending_payment | confirmed | rebooked | cancelled_by_user |
cancelled_by_airline | partially_completed | completed | refund_processing |
refund_completed | failed
FlightTrack.current_legs[].current_status
scheduled | on_time | delayed_minor | delayed_major | rerouted | cancelled |
boarding | departed | in_air | landed | arrived
cancel_flight.reason
user_changed_plans | medical_emergency | family_emergency |
schedule_change_too_disruptive | weather_block | found_alternative | other
merchant_id resolution order
1. Airline IATA + flight_number + scheduled_departure
2. Partner_id + ":" + booking_ref
3. PNR (post-booking)
6. TTBS DIMENSIONS
Per-domain weights (locked; flight)
travel (book_flight): { time: 0.40, taste: 0.10, budget: 0.30, safety: 0.20 }
TIME
SIGNALS USED:
- legs[].scheduled_departure_iso match request HARD FILTER (within ±preferred_window)
- leg_total_duration_minutes (lower=better) weight 0.30
- leg_stops_count (lower=better) weight 0.20
- max_stops_per_leg constraint HARD FILTER
- max_layover_minutes constraint HARD FILTER
- route_quality.on_time_arrival_30day_pct weight 0.30
- cancellation.refund_processing_days weight 0.10
USER BAND HANDLING:
- "earliest possible" → tighten arrival_iso
- "flexible by ±2h" → relax window
TASTE
SIGNALS USED:
- amenities match preferences (in_seat_power, wifi, IFE) weight 0.30
- airline_preferred match weight 0.30
- airline_avoid avoidance HARD FILTER
- amenities_per_segment.leg_room_kind weight 0.20
- amenities_per_segment.in_flight_meal_kind weight 0.10
- alliance_preferred match weight 0.10
HARD FILTERS:
- meal_preference NOT in meal_options
- non_stop_required AND leg_stops_count > 0
BUDGET
SIGNALS USED:
- fare.total_inr vs band:
ok → ultra_low_cost / saver
good → standard / flex
great → business / first / luxury_first
- fare.is_upfront_fare=true weight 0.20
- free_cancellation when requested HARD FILTER
- free_change when requested HARD FILTER
- included baggage match user's baggage_count weight 0.20
- convenience_fee_inr (lower=better) weight 0.10
HARD FILTERS:
- fare.total_inr > preferences.budget_max_inr_total → drop
SAFETY
SIGNALS USED:
- airline_iata_registered AND dgca_registered (for IN routes) HARD FILTER
- iosa_certified weight 0.30
- faa_part_121_or_equivalent weight 0.20
- aircraft_kind (modern wide-body for long-haul preferred) weight 0.15
- cancellation_30day_pct (lower=better) weight 0.15
- route_quality.delay_minutes_30day_avg weight 0.20
- airline insurance_coverage_inr ≥ 10M weight 0.10
- is_overnight_leg → safety scales 1.2x
- wheelchair_assistance → drop airlines without service
HARD FILTERS:
- dgca_registered=false for India domestic → drop
- iosa_certified=false for international → drop
Hidden ranking factor
information_completeness_score weight 0.10.
7. COMPLETION CONTRACT
POST /api/v1/cpc/mcp_provider/{tomo_partner_id}
{
"intent": "travel.book_flight",
"intent_version": "v1.0.0",
"external_id": "FLT-XYZ",
"amount_inr": 13800,
"closed_at": "2026-06-18T20:30:00+05:30",
"request_id": "req_flt_8h2k_...",
"status": "completed",
"pnr": "ABC123",
"booking_ref": "FLT-XYZ",
"legs_completed": 2,
"legs_total": 2,
"actual_departure_iso_outbound": "2026-06-15T07:08:00+05:30",
"actual_arrival_iso_outbound": "2026-06-15T08:38:00+05:30",
"actual_departure_iso_inbound": "2026-06-18T19:08:00+05:30",
"actual_arrival_iso_inbound": "2026-06-18T20:38:00+05:30",
"any_delay_event_minutes": 16,
"any_cancellation_event": false,
"ancillaries_consumed": ["meal_veg_indian", "seat_aisle"],
"miles_earned": 2400,
"currency": "INR",
"fare_breakdown_total_inr": 13800,
"ratings_pending": true,
"notes": ""
}
Status enum: completed | cancelled_by_user | cancelled_by_airline_full_refund | rebooked_with_credit | partial_completion_one_leg_only | failed | refunded
8. WIDGET, 9. CACHING, 10. ERROR CODES, 11. CHECKLIST
(Standard pattern. Widget type: flight_options.)
| Call | TTL |
|---|---|
search_flights |
60s — fares + seats shift fast |
get_fare_rules_and_breakdown |
5min |
lock_seat_or_ancillaries |
0s |
book_flight / cancel_flight / change_flight |
0s |
track_pnr_status |
30s |
web_check_in |
0s |
Universal codes + NO_FLIGHTS_AVAILABLE, OPTION_EXPIRED, PNR_NOT_FOUND, WEB_CHECK_IN_NOT_OPEN, BAGGAGE_OVER_LIMIT, SEAT_TAKEN, WEATHER_DELAY.
12. ANTI-FABRICATION RULES
RULE 1 — No paid placement.
RULE 2 — IOSA / DGCA claims real and current.
RULE 3 — On-time-arrival rate must come from carrier's actual operations data.
RULE 4 — Hidden baggage charge forbidden.
baggage_charge_inr declared at search. Charging at airport beyond stated
excess rates = breach.
RULE 5 — No phantom seat selection charges.
seat_selection_inr_per_segment must reflect actual. Bait-and-switch =
consumer-protection breach.
RULE 6 — Loyalty miles earned honest.
Inflating miles_earned_estimate = breach.
RULE 7 — Cancellation refund processing within stated days.
RULE 8 — Free cancellation honored as stated.
RULE 9 — Schedule changes communicated honestly.
Material schedule change >2h must trigger user notification + free rebook
or refund per regulator (DGCA Aviation Customer Charter).
RULE 10 — No commission-based response shaping.
RULE 11 — Insurance coverage real and pays out.
RULE 12 — Aircraft fitness real.
aircraft_kind claimed must match dispatched plane. Substituting with older
plane silently = breach.
VERSION HISTORY
v1.0.0 — 2026-05-10 — Initial spec