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
| Field | Type | Example | Notes |
|---|---|---|---|
booking_type | enum | flight | One of flight, hotel, car_rental |
confirmation_code | string | X7K9PQ | Record locator / PNR / reservation ID, as printed |
provider_name | string | Delta Air Lines | Airline, hotel brand, or rental company |
provider_domain | string | delta.com | Sending or booking domain |
traveler_name | string | Jordan Rivera | Lead passenger, guest, or driver |
total_price_cents | integer | 48200 | Total charged in minor units, currency-agnostic |
currency | string | usd | ISO 4217, lower-cased |
booking_status | enum | confirmed | One of confirmed, changed, cancelled, pending |
manage_url | string | https://www.delta.com/mytrips/X7K9PQ | ”Manage trip” link when present |
segments | array | see below | One 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:
| Field | Type | Example | Notes |
|---|---|---|---|
start_datetime | string | 2026-07-14T08:05:00-04:00 | Departure, check-in, or pickup — ISO 8601 with offset |
end_datetime | string | 2026-07-14T10:55:00-07:00 | Arrival, check-out, or drop-off — ISO 8601 with offset |
start_location | string | JFK | Origin airport, hotel city, or pickup branch |
end_location | string | LAX | Destination, or same as start for a stay |
detail | string | DL415 · Main Cabin | Flight 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
segmentsentry 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 tocancelledorchangedagainst the sameconfirmation_code. - Body-only today. MailFrame reads the fields printed in the email body. PDF,
image, and
.icscalendar-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/parseas 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.