Stripe sends a receipt email for every successful charge, but the data you actually need — the amount, the customer, the payment intent ID — is locked inside HTML. MailFrame extracts those fields into a typed, schema-validated JSON object you can write straight to your database or forward to your billing system.
It works on the emailed receipt today; PDF invoice and screenshot input are on the roadmap.
Fields MailFrame extracts
| Field | Type | Example | Notes |
|---|---|---|---|
reference_id | string | pi_3PqL2xK9 | Payment intent (pi_), charge (ch_), or invoice (in_) token |
amount_cents | integer | 2999 | Minor units, currency-agnostic |
currency | string | usd | ISO 4217, lower-cased |
card_brand | string | visa | Normalized: visa, mastercard, amex, discover |
card_last4 | string | 4242 | Last four digits only — never the full PAN |
customer_email | string | jordan@example.com | The recipient on the receipt |
merchant_domain | string | stripe.com | Sending domain of the receipt |
date | string | 2026-05-21 | Normalized to ISO 8601 |
payment_status | enum | paid | One of paid, refunded, failed |
Sample input
A typical Stripe receipt email looks like this:
From: receipts@stripe.com
Subject: Receipt from Acme SaaS Inc. - pi_3PqL2x
Date: Thu, 21 May 2026 10:30:00 -0700
To: jordan@example.com
Thanks for your payment of $29.99 to Acme SaaS Inc.
Receipt ID: pi_3PqL2xK9
Amount paid: $29.99 USD
Card: Visa ending in 4242
Date paid: May 21, 2026
Structured JSON output
{
"reference_id": "pi_3PqL2xK9",
"amount_cents": 2999,
"currency": "usd",
"card_brand": "visa",
"card_last4": "4242",
"customer_email": "jordan@example.com",
"merchant_domain": "stripe.com",
"date": "2026-05-21",
"payment_status": "paid"
}
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": "stripe_receipt",
"type": "object",
"required": ["reference_id", "amount_cents", "currency", "payment_status"],
"properties": {
"reference_id": { "type": "string", "pattern": "^(pi|ch|in)_[A-Za-z0-9]+$" },
"amount_cents": { "type": "integer", "minimum": 0 },
"currency": { "type": "string", "minLength": 3, "maxLength": 3 },
"card_brand": { "type": "string", "enum": ["visa", "mastercard", "amex", "discover"] },
"card_last4": { "type": "string", "pattern": "^[0-9]{4}$" },
"customer_email": { "type": "string", "format": "email" },
"date": { "type": "string", "format": "date" },
"payment_status": { "type": "string", "enum": ["paid", "refunded", "failed"] }
}
}
Parse via the API
POST the raw email (MIME or plain text) to /v1/parse with the schema you want to
extract against:
curl https://api.mailframe.ai/v1/parse \
-H "Authorization: Bearer $MAILFRAME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema": "stripe_receipt",
"input": { "type": "email", "raw": "<base64-encoded MIME>" }
}'
Prefer not to handle the email yourself? Inbox forwarding — pointing Stripe’s receipt
forwarding at a unique inbox address MailFrame assigns you — is on the roadmap. Until
it ships, POST the raw email to /v1/parse as shown above.
Webhook delivery
When extraction completes, MailFrame POSTs a signed envelope to your endpoint. The
signature is an HMAC-SHA256 of the raw body using your webhook secret, sent in the
MailFrame-Signature header, with exponential-backoff retries on failure.
{
"event": "parse.completed",
"parse_id": "parse_8f2a1c",
"schema": "stripe_receipt",
"data": {
"reference_id": "pi_3PqL2xK9",
"amount_cents": 2999,
"currency": "usd",
"card_brand": "visa",
"card_last4": "4242",
"payment_status": "paid"
},
"confidence": { "reference_id": 0.99, "amount_cents": 0.98 },
"received_at": "2026-05-21T17:30:04Z"
}
Want to see extraction run live? The free Stripe receipt parser runs a pattern-matching preview entirely in your browser — no signup, no API call.