Data Models
The field-by-field specification of every entity in the system. Each entity is defined here in pseudo-schema notation. The canonical JSON Schema files live in flighthelp/schema; this document is the human-readable summary.
For the philosophy behind these schemas, see SCHEMAS.md. For how the entities are served, see API.md. For how they map to repositories and files, see REPOSITORIES.md.
Every fact-carrying entity (Airline, Airport, BaggageRule, ContactMethod, Fee, Scenario, Regulation) includes a common provenance block:
last_verified_at ISO 8601 timestamp
verifier_count integer ≥ 0
sources array of source_id
confidence_score decimal 0–1 (derived from age, verifier count, source quality)
revisions array of revision_id
Provenance is enforced at the schema level. Data cannot be published without it.
Airline
The top-level entity. Roughly 400 active scheduled carriers worldwide; the schema also supports defunct carriers for historical reference.
id slug, e.g. "lufthansa" (lowercase, hyphen-separated)
iata_code string, exactly 2 alphanumeric chars, uppercase
icao_code string, exactly 3 alphabetic chars, uppercase
legal_name string, the legal entity name
common_name localizable string, the marketing name
country_of_origin ISO 3166-1 alpha-2 country code
alliance enum: star, oneworld, skyteam, none
hub_airports array of airport_id
secondary_hubs array of airport_id
fleet_size integer ≥ 0, optional
fare_classes array of fare_class_id
status enum: active, suspended, defunct, restructuring
operates_in array of ISO 3166-1 country codes
founded_year integer ≥ 1900
ceased_year integer, optional, for defunct carriers
parent_company string, optional
subsidiaries array of airline_id
website URL
support_website URL, optional
logo_url URL (low-resolution, stored under nominative fair use)
languages_supported array of ISO 639-1 codes (languages the airline operates in)
plus provenance block
The fare_classes array references separate FareClass entities (see below) because fare structures vary too much by airline to flatten into a simple enum.
FareClass
Fare classes are airline-specific. American's Basic Economy is not Lufthansa's Economy Light. The schema models them as first-class entities.
id composite: {airline_id}:{slug}, e.g. "lufthansa:economy-light"
airline_id airline_id
name localizable string, the airline's marketing name
internal_code string, optional (e.g. RBD codes)
cabin enum: economy, premium_economy, business, first
restrictions markdown, localizable (changes, cancellations, refundability)
included structured object: {
baggage: {personal_item, carry_on, checked}
seat_selection: enum(free, paid, paid_after_check_in)
meal: enum(none, snack, full)
lounge_access: bool
priority_boarding: bool
}
sortable_rank integer (1 = lowest in the cabin)
notes markdown
plus provenance block
The structured included object is the bridge between the fare class and the BaggageRule entity — it specifies which baggage rules apply by default to this fare.
Airport
Roughly 500 major airports get full pages; smaller airports get stub records. The schema supports both.
id slug, e.g. "lhr"
iata_code string, exactly 3 alphabetic chars, uppercase
icao_code string, exactly 4 alphabetic chars, uppercase
name localizable string
short_name localizable string, optional
city localizable string
country ISO 3166-1 alpha-2
region string, optional (state/province/county)
coordinates {latitude: decimal -90..90, longitude: decimal -180..180}
elevation_m integer, optional
timezone IANA timezone string
terminals array of Terminal objects
runway_count integer ≥ 1
size_class enum: small, medium, large, mega (passengers per year buckets)
status enum: active, closed, under_construction
amenities array of Amenity objects
ground_transport array of GroundTransport objects
lounges array of lounge_id
lost_and_found array of contact_id
notes markdown, localizable
plus provenance block
Terminal object:
id slug, scoped to airport
name localizable string
airlines array of airline_id
connected_terminals array of terminal_id (in same airport, for transit)
pre_security_amenities array of amenity_id
post_security_amenities array of amenity_id
Amenity object:
type enum: shower, sleep_pod, prayer_room, quiet_room,
baggage_storage, medical, family_room,
smoking_lounge, pet_relief, charging_station,
wifi, food_24h, bank, atm, currency_exchange
location_description localizable string
hours structured hours object
cost {amount, currency} or "free"
notes markdown
GroundTransport object:
type enum: metro, train, bus, taxi, rideshare, shuttle,
rental_car, walking
destination string (e.g. "city center", "main station")
duration_minutes integer range {min, max}
cost {amount, currency} range {min, max}
operating_hours structured hours object
url URL, optional
notes markdown
BaggageRule
The most-edited entity in the system. One rule per (airline × fare_class × bag_type) combination.
id uuid
airline_id airline_id
fare_class_id fare_class_id
bag_type enum: personal_item, carry_on, checked, oversized,
sports_equipment, musical_instrument,
pet_cabin, pet_cargo, mobility_aid,
stroller, car_seat, infant
max_dimensions_cm {length, width, height} (all decimals)
max_dimensions_in {length, width, height} (auto-converted, for display)
max_weight_kg decimal ≥ 0
max_weight_lb decimal (auto-converted)
max_count integer ≥ 0 (how many of this type allowed)
linear_dimensions_cm decimal, optional (total of l+w+h, some airlines use this)
fee_if_exceeded reference to Fee entity
fee_to_add reference to Fee entity, optional (for paid carry-on etc.)
sizer_photo_urls array of URL (Cloudflare R2, contributor-uploaded)
enforcement_strictness enum: lax, normal, strict, brutal (community-rated)
route_restrictions array of RouteRestriction objects
effective_from date (YYYY-MM-DD)
effective_to date, nullable
notes markdown, localizable
plus provenance block
RouteRestriction object:
applies_to enum: only_these, except_these
routes array of {
origin: airport_id or country code or "any"
destination: airport_id or country code or "any"
}
reason markdown
The route_restrictions field handles cases like "Ryanair 10kg cabin bag rule on UK domestic only" or "Air Canada different rules to/from US versus international." Without this, the model cannot represent the reality.
The enforcement_strictness field captures the gap between published policy and gate reality. A community rating of "brutal" means the airline actually weighs and measures; "lax" means they typically don't bother. This is what makes the data uniquely useful versus airline-published data.
ContactMethod
One record per (airline × purpose × channel × country_scope) combination. Designed so the API can return contact methods sorted by what works.
id uuid
airline_id airline_id
purpose enum: reservations, baggage, special_assistance,
refunds, corporate, media, accessibility,
loyalty_program, group_bookings,
compensation_claims, complaints
channel enum: phone, whatsapp, x_twitter, facebook,
instagram, email, live_chat, web_form,
physical_desk, postal_address
value string (phone number in E.164, handle, URL, email)
country_scope array of ISO 3166-1 codes (which country's callers
should use this); empty array means global
language array of ISO 639-1 codes
hours structured Hours object with timezone
typical_wait_minutes integer, crowdsourced rolling 30-day average
success_rate decimal 0–1, crowdsourced thumbs up/down ratio
sample_size integer (how many ratings the success_rate is based on)
notes markdown, localizable (e.g. "press 3 then 7 for human")
ivr_path ordered array of strings, optional (the menu sequence)
plus provenance block
Hours object:
monday..sunday array of {open: HH:MM, close: HH:MM} (multiple ranges OK)
timezone IANA timezone
exceptions array of {date_range, hours_override}
notes markdown
The success_rate field is the killer feature for travelers. Contact methods can be sorted by it. A number that reaches a human ranks above the published "official" number that rings forever.
Fee
Every fee an airline charges, structured.
id uuid
airline_id airline_id
fee_type enum: change, cancel, no_show, name_change,
seat_select_standard, seat_select_extra_legroom,
seat_select_exit_row, priority_boarding,
early_boarding, meal_economy, meal_premium,
alcoholic_beverage, lounge_access,
bag_overweight, bag_oversize,
extra_bag, carry_on, infant_in_lap,
child_unaccompanied, pet_cabin, pet_cargo,
sports_equipment, musical_instrument,
mobility_aid, oxygen, wifi, entertainment
amount decimal ≥ 0
currency ISO 4217 code
amount_range {min, max}, optional (when fee varies)
conditions structured Conditions object
charged_per enum: passenger, segment, direction, bag_unit, hour, mb
collected_by enum: airline, airport, ground_handler, third_party
refundable bool
refund_window_hours integer, optional
notes markdown, localizable
plus provenance block
Conditions object:
route_origins array of airport_id or country, optional
route_destinations array of airport_id or country, optional
fare_classes array of fare_class_id, optional
advance_purchase_days {min, max}, optional
member_only bool
online_only bool
payment_method array of enum (some fees vary by card type)
Scenario
A passenger-rights scenario. Roughly 80 core scenarios at launch, expanding as regulations and community input shape the list.
id slug, e.g. "eu-cancellation-less-than-14-days"
title localizable string
short_summary localizable string, one sentence
jurisdiction array of regulation_id
applies_when structured Eligibility object
your_rights markdown, localizable
step_by_step ordered array of Action objects
template_messages array of TemplateMessage objects
escalation_path ordered array of EscalationStep objects
typical_outcomes {
compensation_range: {min, max, currency}
success_rate_percent: integer 0–100
time_to_resolution_days: {median, p90}
}
case_examples array of CaseExample objects (anonymized)
common_pushback array of {
airline_claim: markdown
counter_response: markdown
legal_basis: regulation_id + article
}
related_scenarios array of scenario_id
plus provenance block
Eligibility object:
flight_type array of enum (commercial, charter, cargo, etc.)
origin_in array of country codes (where flight originated)
destination_in array of country codes
carrier_jurisdiction array of country codes
delay_min_hours integer, optional
cancellation_notice_max_days integer, optional
additional_conditions markdown
Action object:
step_number integer
title localizable string
description markdown, localizable
time_limit string, optional (e.g. "within 2 hours of disruption")
proof_to_collect array of strings (e.g. "boarding pass", "photo of board")
TemplateMessage object:
channel enum: email, postal, web_form, chat, in_person
language ISO 639-1
subject string, optional (for email)
body markdown with placeholders
placeholders array of {name, description, example}
EscalationStep object:
level integer (1 = first attempt, 2 = next, etc.)
target enum: airline_direct, national_regulator, eu_body,
court_small_claims, court_civil, court_aviation,
consumer_protection_agency, ombudsman, media
contact contact_id or markdown if not in dataset
expected_timeframe string
notes markdown
CaseExample object:
flight_route string (anonymized: e.g. "LHR-JFK")
carrier airline_id (if public)
disruption markdown
outcome markdown
compensation_received {amount, currency}, optional
time_to_resolution_days integer
contributor_id contributor_id, optional
Regulation
The legal frameworks that ground every compensation determination.
id slug, e.g. "eu-261-2004"
title localizable string, full title
short_name string, common usage (e.g. "EU 261")
jurisdiction array of ISO 3166-1 codes
effective_date date
amended_dates array of date
full_text_urls array of {language, url}
plain_language markdown, localizable
key_provisions array of Provision objects
enforcement_body array of contact_id
amendments array of Amendment objects
superseded_by regulation_id, optional
plus provenance block
Provision object:
article string (e.g. "Article 7", "§250.5")
title localizable string
summary markdown, localizable
applies_to markdown
triggers structured object (referenced by rules engine)
Amendment object:
date date
description markdown
source_url URL
changed_articles array of strings
The key_provisions[].triggers field is what the rules engine reads. See RULES-ENGINE.md for how triggers are structured.
Contributor
id uuid
display_name string (chosen, can be pseudonymous; profanity-filtered)
joined_at ISO 8601 timestamp
home_airport airport_id, optional
languages array of ISO 639-1 codes
country ISO 3166-1, optional (for moderator timezone routing)
reputation_score integer (computed nightly)
trust_tier enum: new, regular, trusted, moderator, core
edits_submitted integer ≥ 0
edits_approved integer ≥ 0
edits_rejected integer ≥ 0
verifications integer ≥ 0
photos_uploaded integer ≥ 0
airlines_flown array of airline_id (self-reported)
airports_visited array of airport_id (self-reported)
badges array of badge_id
public_profile bool
flight_credentials array of Credential objects (verified)
Credential object:
type enum: cabin_crew, gate_agent, pilot, dispatcher,
aviation_lawyer, frequent_flyer_status,
consumer_advocate, regulator_staff
airline_id airline_id, optional
verification_method enum: id_check, employer_verification, peer_vouch
verified_at timestamp
expires_at timestamp, optional
Edit / Revision
Every change to any entity creates a Revision. The full edit history is queryable; no data is ever destroyed, only superseded.
id uuid
entity_type enum (matches all entity types)
entity_id string (the id of the entity being edited)
field_path string (dot-notation, e.g. "baggage_rules.carry_on.max_weight_kg")
prior_value json
new_value json
contributor_id contributor_id
submitted_at ISO 8601 timestamp
source_urls array of URL
source_photos array of upload_id
source_notes markdown
moderator_id contributor_id, nullable
moderation_state enum: pending, approved, rejected, disputed, withdrawn
moderation_decided_at timestamp, nullable
moderation_note markdown, nullable
moderation_reason_code enum, nullable (when rejected; standard reason codes)
verification_votes {confirm: integer, dispute: integer, sample: integer}
parent_revision_id revision_id, nullable (for chained edits)
Source
The provenance record. Every claim traces to at least one Source.
id uuid
url URL
type enum: airline_official, regulator_official,
court_ruling, news_article, photo,
user_report, leaked_internal, academic_paper,
wikipedia_archived, scraper_snapshot
captured_at ISO 8601 timestamp
snapshot_url URL (archive.org, internal archive, or R2)
title string
publisher string
language ISO 639-1
reliability_tier enum: primary, secondary, tertiary
notes markdown
Reliability tiers:
- Primary: airline's own page, regulator's own page, court document, photo with timestamp/geotag.
- Secondary: reputable news article, contributor user report with evidence.
- Tertiary: Wikipedia, forum post, screenshot without verification.
Claims supported only by tertiary sources are flagged in the API response and visibly marked on the site.
Badge
id slug
name localizable string
description localizable string
criteria structured Rule (the engine that decides who has it)
rarity enum: common, uncommon, rare, legendary
icon_url URL (SVG, monochrome, on hairline background)
introduced_on date
retired_on date, nullable
Roughly 80 badges at launch. Examples: "First Edit," "Verified at 50 airports," "Translated a scenario into 3 languages," "Survived a Ryanair gate check," "Documented during a strike," "Found a broken scraper."