Skip to content
Tier 2 Schema

Parse Calendar Meeting Invite Emails

Turn Google Calendar, Outlook, and iCloud meeting invite emails into typed JSON — event title, organizer, attendees, start and end times, location, and response.

Google Calendar, Outlook, and iCloud send a fresh meeting-invite email the moment someone books time with you — and every one of them lays the event out differently. The fields a calendar sync, a CRM activity log, or a meeting-prep assistant needs are always the same: what’s the event, who’s running it, who’s attending, when (and in what time zone), and where. MailFrame extracts those fields from the invite email into a typed, schema-validated JSON object you can route straight into a calendar backend, a meeting-prep workflow, or a customer-engagement timeline.

It works on the body of meeting-invite, update, and cancellation emails from Google Calendar (typically calendar-notification@google.com), Microsoft Outlook (often outlook@office365.com for cloud tenants or an Exchange on-prem address for self-hosted), and Apple iCloud (noreply@caldav.icloud.com). Match on the invite body and the embedded iCalendar parts (Outlook BEGIN:VCALENDAR, Google text/calendar invite attachment) rather than the From address alone — providers can relay invites through tenant-specific addresses. Subject lines, start/end times with the original time zone, organizer, attendees, location (including conferencing links), and response status are normalized into one consistent shape regardless of which provider sent the message.

Fields MailFrame extracts

FieldTypeExampleNotes
event_titlestringQ3 roadmap reviewThe meeting subject, as written on the invite
event_uidstring040000008200E00074C5B7101A82E00800000000B0...@google.comProvider’s event UID when present — stable join key for updates and cancellations
invitation_typeenuminvitationOne of invitation, update, cancellation
organizer_emailstringamelia.chen@example.comThe organizer’s address
organizer_namestringAmelia ChenThe organizer’s display name when present
attendeesarraysee belowOne entry per invitee, with name, email, and response status
start_datetimestring2026-07-08T14:00:00-04:00Event start in ISO 8601 with offset
end_datetimestring2026-07-08T15:00:00-04:00Event end in ISO 8601 with offset
timezonestringAmerica/New_YorkIANA time zone when present; otherwise the offset is preserved on the datetime fields
locationstringConference Room 4BPhysical location or conferencing room name
location_urlstringhttps://meet.google.com/abc-defg-hijVideo-conferencing link when present (Google Meet, Zoom, Teams, Webex)
descriptionstringReview the Q3 OKR draft before the 1:1 with the exec team.The invite body, lightly trimmed
is_recurringbooleanfalsetrue when the invite is part of a recurring series
response_statusenumneeds_actionOne of accepted, declined, tentative, needs_action
datestring2026-07-07Date the invite was sent, normalized to ISO 8601

Each entry in attendees carries the same shape regardless of provider:

FieldTypeExampleNotes
emailstringjordan.rivera@example.comInvitee address
namestringJordan RiveraInvitee display name when present
requiredbooleantruefalse for optional/CC’d attendees
response_statusenumacceptedOne of accepted, declined, tentative, needs_action

Sample input

A typical Google Calendar invitation email looks like this:

From: amelia.chen@example.com
Subject: Invitation: Q3 roadmap review @ Wed Jul 8, 2026 2pm - 3pm (EDT)
Date: Tue, 07 Jul 2026 16:42:00 -0400
To: jordan.rivera@example.com

Amelia Chen has invited you to the following event:

Title:        Q3 roadmap review
When:         Wed Jul 8, 2026 14:00 - 15:00 (EDT)
Where:        https://meet.google.com/abc-defg-hij
Organizer:    Amelia Chen <amelia.chen@example.com>
Attendees:    Amelia Chen (organizer), Jordan Rivera, Priya Shah

Description:
Review the Q3 OKR draft before the 1:1 with the exec team.

Do you want to accept?
https://www.google.com/calendar/event?eid=...

The same shape is produced for Outlook meeting-request messages (outlook@office365.com, Exchange BEGIN:VCALENDAR parts) and iCloud noreply@caldav.icloud.com invitations — invitation_type distinguishes invitation from update and cancellation, and the rest of the fields normalize to the same JSON keys.

Structured JSON output

{
  "event_title": "Q3 roadmap review",
  "event_uid": "040000008200E00074C5B7101A82E00800000000B0CAFED@example.com",
  "invitation_type": "invitation",
  "organizer_email": "amelia.chen@example.com",
  "organizer_name": "Amelia Chen",
  "attendees": [
    {
      "email": "amelia.chen@example.com",
      "name": "Amelia Chen",
      "required": true,
      "response_status": "accepted"
    },
    {
      "email": "jordan.rivera@example.com",
      "name": "Jordan Rivera",
      "required": true,
      "response_status": "needs_action"
    },
    {
      "email": "priya.shah@example.com",
      "name": "Priya Shah",
      "required": false,
      "response_status": "needs_action"
    }
  ],
  "start_datetime": "2026-07-08T14:00:00-04:00",
  "end_datetime": "2026-07-08T15:00:00-04:00",
  "timezone": "America/New_York",
  "location": "",
  "location_url": "https://meet.google.com/abc-defg-hij",
  "description": "Review the Q3 OKR draft before the 1:1 with the exec team.",
  "is_recurring": false,
  "response_status": "needs_action",
  "date": "2026-07-07"
}

JSON Schema definition

Every field is validated against the schema before MailFrame returns it. You can copy this as a starting point and tighten it for your own use case — for example, require attendees if every event in your workflow should carry at least one invitee, or restrict response_status to {"accepted", "declined"} if you only care about confirmed outcomes:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "calendar_invite",
  "type": "object",
  "required": [
    "event_title",
    "invitation_type",
    "start_datetime",
    "end_datetime",
    "organizer_email"
  ],
  "properties": {
    "event_title":     { "type": "string", "minLength": 1 },
    "event_uid":       { "type": "string" },
    "invitation_type": {
      "type": "string",
      "enum": ["invitation", "update", "cancellation"]
    },
    "organizer_email": { "type": "string", "format": "email" },
    "organizer_name":  { "type": "string" },
    "attendees": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["email"],
        "properties": {
          "email":           { "type": "string", "format": "email" },
          "name":            { "type": "string" },
          "required":        { "type": "boolean" },
          "response_status": {
            "type": "string",
            "enum": ["accepted", "declined", "tentative", "needs_action"]
          }
        }
      }
    },
    "start_datetime": { "type": "string", "format": "date-time" },
    "end_datetime":   { "type": "string", "format": "date-time" },
    "timezone":       { "type": "string" },
    "location":       { "type": "string" },
    "location_url":   { "type": "string", "format": "uri" },
    "description":    { "type": "string" },
    "is_recurring":   { "type": "boolean" },
    "response_status": {
      "type": "string",
      "enum": ["accepted", "declined", "tentative", "needs_action"]
    },
    "date": { "type": "string", "format": "date" }
  }
}

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 $MAILF...KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "schema_id": "calendar_invite",
    "raw_mime": "From: amelia.chen@example.com\r\nTo: jordan.rivera@example.com\r\nSubject: Invitation: Q3 roadmap review @ Wed Jul 8, 2026 2pm - 3pm (EDT)\r\n\r\nAmelia Chen has invited you to the following event:"
  }'

The call is synchronous: /v1/parse validates the extraction against your schema and returns the typed JSON in the HTTP response, so you can act on it inline — push the event into your calendar backend, surface a meeting-prep briefing, or trigger a follow-up workflow on cancellation.

Routing on the result

The most useful split is by invitation_type: any value of {"invitation", "update"} should refresh the local calendar entry keyed on event_uid (carrying forward start_datetime, end_datetime, location_url, and the per-attendee response_status), while cancellation should soft-delete the local entry keyed on the same event_uid rather than removing it from history. Use event_uid as the deduplication key — providers send one message per change, so a single event in your calendar will produce several messages over its lifetime (invitation, update, cancellation), and the same event_uid is the right join across all of them.

Signed webhook delivery

Signed async webhook delivery — where MailFrame POSTs a signed envelope to your endpoint when a parse completes — is available during early access alongside the synchronous API. Each delivery carries an HMAC-SHA256 signature in the MailFrame-Signature header for verification, with exponential-backoff retries on failure. Inbox forwarding — pointing a Gmail or Outlook filter at a unique inbox address MailFrame assigns you — is on the roadmap.

Working with related email types? See the shipping notification schema for carrier tracking, the travel booking schema for flight/hotel/car confirmations, and the email-to-JSON API guide for a full walkthrough of POST /v1/parse.

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