Apple sends a “Your receipt from Apple” email for every App Store, subscription, and in-app purchase, but the itemized breakdown lives inside a styled HTML table that varies by region and purchase type. MailFrame normalizes every Apple receipt into typed JSON you can feed directly into your subscription management or expense tracking system.
It works on App Store purchase receipts, in-app purchase confirmations, and subscription renewal emails from Apple.
Fields MailFrame extracts
| Field | Type | Example | Notes |
|---|---|---|---|
order_id | string | ML8X9R2KTP | Apple order number |
document_no | string | MJDQ4LL/A | Internal document number when present |
apple_id | string | taylor@icloud.com | Apple ID (email) associated with the purchase |
items | array | see output | Each item: title, type, price_cents |
subtotal_cents | integer | 999 | Pre-tax subtotal in minor units |
tax_cents | integer | 82 | Tax charged in minor units |
total_cents | integer | 1081 | Grand total in minor units |
currency | string | usd | ISO 4217, lower-cased |
date | string | 2026-05-21 | Purchase date normalized to ISO 8601 |
renewal | boolean | true | true if this is a subscription auto-renewal |
Sample input
A typical Apple App Store receipt email looks like this:
From: no_reply@email.apple.com
Subject: Your receipt from Apple.
Date: Thu, 21 May 2026 08:02:00 -0700
To: taylor@icloud.com
Dear Taylor,
Thank you for your purchase.
Apple ID: taylor@icloud.com
Order ID: ML8X9R2KTP
Document No.: MJDQ4LL/A
Billed to: Visa ending in 1234
May 21, 2026
Fantastical — Calendar & Tasks
Annual Subscription (auto-renewal) $39.99
Subtotal: $39.99
Tax: $3.28
Total: $43.27 USD
This subscription renews automatically. Manage subscriptions in Settings.
Structured JSON output
{
"order_id": "ML8X9R2KTP",
"document_no": "MJDQ4LL/A",
"apple_id": "taylor@icloud.com",
"items": [
{
"title": "Fantastical — Calendar & Tasks Annual Subscription",
"type": "subscription",
"price_cents": 3999
}
],
"subtotal_cents": 3999,
"tax_cents": 328,
"total_cents": 4327,
"currency": "usd",
"date": "2026-05-21",
"renewal": true
}
JSON Schema definition
Every field is validated against the schema before delivery. You can copy this as a starting point and tighten it for your own use case:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "apple_app_store_receipt",
"type": "object",
"required": ["order_id", "apple_id", "items", "total_cents", "currency", "date"],
"properties": {
"order_id": { "type": "string" },
"document_no": { "type": "string" },
"apple_id": { "type": "string", "format": "email" },
"items": {
"type": "array",
"items": {
"type": "object",
"required": ["title", "type", "price_cents"],
"properties": {
"title": { "type": "string" },
"type": { "type": "string", "enum": ["app", "subscription", "in_app"] },
"price_cents": { "type": "integer", "minimum": 0 }
}
}
},
"subtotal_cents": { "type": "integer", "minimum": 0 },
"tax_cents": { "type": "integer", "minimum": 0 },
"total_cents": { "type": "integer", "minimum": 0 },
"currency": { "type": "string", "minLength": 3, "maxLength": 3 },
"date": { "type": "string", "format": "date" },
"renewal": { "type": "boolean" }
}
}
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": "apple_app_store_receipt",
"raw_mime": "From: no_reply@email.apple.com\r\nTo: taylor@icloud.com\r\nSubject: Your receipt from Apple.\r\n\r\nDear Taylor,"
}'
Prefer a fully automated pipeline? Inbox forwarding — sending your Apple receipts to a
unique inbox address MailFrame assigns you — is on the roadmap. Until it ships, POST the
raw email to /v1/parse as shown above.
Signed webhook delivery
Signed webhook delivery — where MailFrame POSTs the extraction result to your endpoint —
is available during early access. Each delivery carries an HMAC-SHA256 signature in
the MailFrame-Signature header for verification, with exponential-backoff retries on
failure. The delivery envelope looks like this:
{
"event": "parse.completed",
"parse_id": "parse_f5a8b3",
"schema": "apple_app_store_receipt",
"data": {
"order_id": "ML8X9R2KTP",
"apple_id": "taylor@icloud.com",
"items": [
{
"title": "Fantastical — Calendar & Tasks Annual Subscription",
"type": "subscription",
"price_cents": 3999
}
],
"subtotal_cents": 3999,
"tax_cents": 328,
"total_cents": 4327,
"currency": "usd",
"date": "2026-05-21",
"renewal": true
},
"confidence": { "order_id": 0.99, "total_cents": 0.98, "renewal": 0.95 },
"received_at": "2026-05-21T15:02:14Z"
}
For synchronous delivery, use POST /v1/parse as shown above — the response returns
typed JSON for every successful extraction.