Skip to content
Tier 2 Schema

Parse Travel Booking Confirmation Emails

Turn flight, hotel, and rental-car confirmation emails into typed JSON — confirmation code, provider, traveler, dates, locations, price, and per-segment legs.

Airlines, hotels, and rental-car companies all send a confirmation email the moment a booking is made — and every one of them lays it out differently. Delta, Marriott, and Hertz share nothing in their formatting, yet the fields a trip dashboard, expense tool, or itinerary builder needs are the same every time: what was booked, by whom, when, where, and for how much. MailFrame extracts those fields from the confirmation email into typed, schema-validated JSON you can route straight into a calendar, an expense report, or a travel-management workflow.

It reads the details written in the body of the confirmation email today. Many itineraries also arrive as a PDF or a calendar .ics attachment — PDF, image, and calendar-attachment input are on the roadmap, so for now MailFrame parses the flight numbers, dates, and totals printed in the email body itself.

Fields MailFrame extracts

FieldTypeExampleNotes
booking_typeenumflightOne of flight, hotel, car_rental
confirmation_codestringX7K9PQRecord locator / PNR / reservation ID, as printed
provider_namestringDelta Air LinesAirline, hotel brand, or rental company
provider_domainstringdelta.comSending or booking domain
traveler_namestringJordan RiveraLead passenger, guest, or driver
total_price_centsinteger48200Total charged in minor units, currency-agnostic
currencystringusdISO 4217, lower-cased
booking_statusenumconfirmedOne of confirmed, changed, cancelled, pending
manage_urlstringhttps://www.delta.com/mytrips/X7K9PQ”Manage trip” link when present
segmentsarraysee belowOne entry per leg, stay, or rental period

Each entry in segments carries the same shape regardless of booking_type, so a multi-leg flight, a hotel stay, and a car rental all parse into one consistent structure:

FieldTypeExampleNotes
start_datetimestring2026-07-14T08:05:00-04:00Departure, check-in, or pickup — ISO 8601 with offset
end_datetimestring2026-07-14T10:55:00-07:00Arrival, check-out, or drop-off — ISO 8601 with offset
start_locationstringJFKOrigin airport, hotel city, or pickup branch
end_locationstringLAXDestination, or same as start for a stay
detailstringDL415 · Main CabinFlight number + cabin, room type + nights, or vehicle class

Sample input

A typical flight confirmation email looks like this:

From: confirmations@delta.com
Subject: Your trip to Los Angeles is confirmed — Confirmation X7K9PQ
Date: Tue, 23 Jun 2026 14:12:00 -0400
To: jordan.rivera@example.com

Hi Jordan,

Your booking is confirmed. Confirmation code: X7K9PQ

OUTBOUND — Tue, Jul 14, 2026
DL 415   New York (JFK)   8:05 AM  →  Los Angeles (LAX)  10:55 AM
Cabin: Main Cabin (Economy)

RETURN — Sun, Jul 19, 2026
DL 1180  Los Angeles (LAX) 6:40 PM  →  New York (JFK)    2:59 AM (+1)
Cabin: Main Cabin (Economy)

Passenger:      Jordan Rivera
Total charged:  $482.00 USD

Manage your trip: https://www.delta.com/mytrips/X7K9PQ

Structured JSON output

{
  "booking_type": "flight",
  "confirmation_code": "X7K9PQ",
  "provider_name": "Delta Air Lines",
  "provider_domain": "delta.com",
  "traveler_name": "Jordan Rivera",
  "total_price_cents": 48200,
  "currency": "usd",
  "booking_status": "confirmed",
  "manage_url": "https://www.delta.com/mytrips/X7K9PQ",
  "segments": [
    {
      "start_datetime": "2026-07-14T08:05:00-04:00",
      "end_datetime": "2026-07-14T10:55:00-07:00",
      "start_location": "JFK",
      "end_location": "LAX",
      "detail": "DL415 · Main Cabin"
    },
    {
      "start_datetime": "2026-07-19T18:40:00-07:00",
      "end_datetime": "2026-07-20T02:59:00-05:00",
      "start_location": "LAX",
      "end_location": "JFK",
      "detail": "DL1180 · Main Cabin"
    }
  ]
}

A hotel or rental-car confirmation maps onto the same shape: start_datetime / end_datetime become check-in / check-out (or pickup / drop-off), start_location and end_location carry the property or branch, and detail holds the room type and nights or the vehicle class.

JSON Schema definition

Every field is validated against the schema before delivery. Copy this as a starting point and tighten it for your own use case:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "travel_booking",
  "type": "object",
  "required": ["booking_type", "confirmation_code", "provider_name", "booking_status", "segments"],
  "properties": {
    "booking_type": { "type": "string", "enum": ["flight", "hotel", "car_rental"] },
    "confirmation_code": { "type": "string", "minLength": 1 },
    "provider_name": { "type": "string", "minLength": 1 },
    "provider_domain": { "type": "string", "format": "hostname" },
    "traveler_name": { "type": "string" },
    "total_price_cents": { "type": "integer", "minimum": 0 },
    "currency": { "type": "string", "minLength": 3, "maxLength": 3 },
    "booking_status": { "type": "string", "enum": ["confirmed", "changed", "cancelled", "pending"] },
    "manage_url": { "type": "string", "format": "uri" },
    "segments": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": ["start_datetime", "start_location"],
        "properties": {
          "start_datetime": { "type": "string", "format": "date-time" },
          "end_datetime": { "type": "string", "format": "date-time" },
          "start_location": { "type": "string", "minLength": 1 },
          "end_location": { "type": "string" },
          "detail": { "type": "string" }
        }
      }
    }
  }
}

Parse via the API

POST the raw email (MIME or plain text) to /v1/parse with the schema you want to extract against:

The example below sends this page’s Sample input as raw_mime.

curl https://api.mailframe.ai/v1/parse \
  -H "Authorization: Bearer $MAILFRAME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "schema_id": "travel_booking",
    "raw_mime": "From: confirmations@delta.com\r\nTo: jordan.rivera@example.com\r\nSubject: Your trip to Los Angeles is confirmed — Confirmation X7K9PQ\r\n\r\nHi Jordan,"
  }'

MailFrame returns the typed JSON in the same HTTP response. Prefer asynchronous delivery? Signed webhook delivery — where MailFrame POSTs the extraction result to your endpoint with an HMAC-SHA256 signature in the MailFrame-Signature header and exponential-backoff retries — is available during early access.

Operational notes

  • Timezones are preserved. Departure and arrival times are normalized to ISO 8601 with the original UTC offset, so a red-eye that lands the next morning keeps its (+1) day rollover instead of silently shifting.
  • Round trips and multi-city itineraries produce one segments entry per leg, in travel order. A one-way trip or a single hotel stay is simply a one-element array.
  • Changes and cancellations are reflected in booking_status — a “your trip has been cancelled” or “schedule change” email re-parses to cancelled or changed against the same confirmation_code.
  • Body-only today. MailFrame reads the fields printed in the email body. PDF, image, and .ics calendar-attachment input are on the roadmap; inbox forwarding — pointing your trips inbox at a unique address MailFrame assigns you — is planned as well. Until those ship, POST the raw email to /v1/parse as shown above.

Parsing other transactional mail? See the invoice & payment-due schema and the Stripe receipt schema, browse the full schema library, or read the API docs and pricing for the free-tier limits.

Other schemas

Ship this schema in production

Define your fields once, then POST raw email to /v1/parse. MailFrame returns typed JSON in the HTTP response or via signed webhook delivery with retries, attempt history, dead-letter, and replay. (Inbox forwarding is on the roadmap.)

Request early access