Converting incoming emails into structured data is a classic integration challenge. Many developers try to extract data by hacking together regexes, but these brittle rules inevitably break when formatting changes. Instead, modern parsing uses a schema-first approach: you define the JSON shape you need, and the parser extracts into that contract before validation.
In this guide, we’ll look at how to build a robust JSON Schema email parser that validates raw MIME emails using MailFrame’s POST /v1/parse API. For a higher-level overview of our platform capabilities, see our Email to JSON API use case.
The Schema-First Approach
Instead of mapping rules to specific words or coordinates, MailFrame uses JSON Schema as the contract for extraction. The parser extracts into that contract, validates the result, and surfaces validation errors instead of handing your app an untyped blob. Read more about why we built MailFrame schema-first.
Here is an example JSON Schema for parsing an e-commerce receipt:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["merchant", "total_amount", "order_date"],
"properties": {
"merchant": { "type": "string" },
"total_amount": { "type": "number" },
"order_date": { "type": "string", "format": "date-time" },
"currency": { "type": "string", "enum": ["USD", "EUR", "GBP", "CAD"] },
"line_items": {
"type": "array",
"items": {
"type": "object",
"required": ["description", "price"],
"properties": {
"description": { "type": "string" },
"price": { "type": "number" }
}
}
}
}
}
We already have pre-built schemas for things like Stripe Receipts and Amazon Orders, but you can supply any valid JSON Schema.
Calling the API
With MailFrame, you pass the raw MIME or email-like input directly to the API alongside the schema. MailFrame processes the raw email and returns the extracted JSON.
Here is a curl example targeting our /v1/parse endpoint:
curl -X POST https://api.mailframe.ai/v1/parse \
-H "Authorization: Bearer $MAILFRAME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema": {
"type": "object",
"required": ["merchant", "total_amount"],
"properties": {
"merchant": { "type": "string" },
"total_amount": { "type": "number" }
}
},
"raw_mime": "From: receipts@example.com\r\nTo: ops@example.com\r\nSubject: Your Receipt\r\n\r\nThanks for shopping at Acme Corp. Your total was $42.50."
}'
Note: While you pass raw MIME or text today, PDF and image inputs are on our roadmap.
Implementation Steps
When setting up your email-to-JSON pipeline, consider these steps for a reliable architecture:
- Ingestion: Capture raw emails from your mail server or provider. (Note: Direct inbox forwarding is a roadmap feature; today you send the raw MIME directly to our API).
- Parsing Request: Make a request to the MailFrame API with your target schema.
- Response Handling: Receive the validated JSON response.
- Error & Review Routing: Branch your logic based on schema validation status or HTTP response success.
For a deeper dive, check out our email parsing pipeline design and choosing an email parsing API guides.
Handling Errors and Schema Validation
Because the parsing is schema-first, any result that violates your constraints (like an invalid enum or missing required fields) is treated as a parse error. Today, you should use strict JSON Schema rules as your primary routing signal. (Note: granular, per-field confidence scoring is on our product roadmap, but today we rely on binary schema validation).
You should design your system to route parsing failures to a human review queue. For example:
const response = await fetch("https://api.mailframe.ai/v1/parse", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MAILFRAME_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ schema, raw_mime: rawMimeText }),
});
if (!response.ok) {
// Preserve the raw email and API error for review/retry.
await queueForReview({ rawMimeText, error: await response.text() });
} else {
const result = await response.json();
if (result.status !== "completed" || result.validation_errors?.length) {
await queueForReview({ rawMimeText, result });
} else {
await processOrder(result.data);
}
}
Production Checklist
Before rolling this out, run through this quick checklist:
- Ensure your JSON Schema is strict. Use enums and required fields where possible.
- Implement a review queue for schema validation failures and parse errors.
- If using webhooks, ensure you’re validating the signed payload. (Signed async webhook delivery is available during early access; see webhooks that don’t break for best practices).
- Review our documentation for full API details.
By standardizing on a schema-first API, you can stop fighting fragile regex patterns and build a durable, scalable email ingestion system.