Skip to content
Tier 2 Schema

Parse Invoice & Payment-Due Emails

Turn invoice and payment-due emails into typed JSON — invoice number, vendor, amount due, currency, issue and due dates, PO number, and payment status.

Vendors email invoices and payment reminders in every layout imaginable — QuickBooks, FreshBooks, Xero, Bill.com, or a one-off message typed by hand — yet the fields your accounts-payable workflow needs are always the same: who’s billing you, how much, and by when. MailFrame extracts those fields from the invoice email into a typed, schema-validated JSON object you can route straight into your ledger, AP queue, or reconciliation job.

It works on the text of the invoice or payment-reminder email today. Many invoices also arrive as a PDF attachment — PDF and image input are on the roadmap, so for now MailFrame reads the fields written in the email body itself.

Fields MailFrame extracts

FieldTypeExampleNotes
invoice_numberstringINV-2026-0481Vendor’s invoice identifier, as printed
po_numberstringPO-5567Purchase-order reference when present
vendor_namestringAcme SuppliesBilling party’s display name
vendor_domainstringacmesupplies.comSending domain of the invoice
amount_due_centsinteger125000Balance due in minor units, currency-agnostic
currencystringusdISO 4217, lower-cased
issue_datestring2026-06-15Invoice date, normalized to ISO 8601
due_datestring2026-06-30Payment due date, normalized to ISO 8601
customer_emailstringap@buyerco.comThe billed recipient on the invoice
payment_urlstringhttps://pay.acmesupplies.com/inv/INV-2026-0481”Pay now” link when present
payment_statusenumdueOne of due, paid, overdue, partial

Sample input

A typical invoice / payment-due email looks like this:

From: billing@acmesupplies.com
Subject: Invoice INV-2026-0481 from Acme Supplies — due June 30
Date: Mon, 15 Jun 2026 09:00:00 -0400
To: ap@buyerco.com

Hi Buyer Co.,

Please find invoice INV-2026-0481 below.

Invoice number: INV-2026-0481
PO number:      PO-5567
Issue date:     June 15, 2026
Due date:       June 30, 2026
Amount due:     $1,250.00 USD

Pay online: https://pay.acmesupplies.com/inv/INV-2026-0481

Thank you for your business.

Structured JSON output

{
  "invoice_number": "INV-2026-0481",
  "po_number": "PO-5567",
  "vendor_name": "Acme Supplies",
  "vendor_domain": "acmesupplies.com",
  "amount_due_cents": 125000,
  "currency": "usd",
  "issue_date": "2026-06-15",
  "due_date": "2026-06-30",
  "customer_email": "ap@buyerco.com",
  "payment_url": "https://pay.acmesupplies.com/inv/INV-2026-0481",
  "payment_status": "due"
}

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": "invoice",
  "type": "object",
  "required": ["invoice_number", "vendor_name", "amount_due_cents", "currency", "payment_status"],
  "properties": {
    "invoice_number": { "type": "string", "minLength": 1 },
    "po_number": { "type": "string" },
    "vendor_name": { "type": "string", "minLength": 1 },
    "vendor_domain": { "type": "string", "format": "hostname" },
    "amount_due_cents": { "type": "integer", "minimum": 0 },
    "currency": { "type": "string", "minLength": 3, "maxLength": 3 },
    "issue_date": { "type": "string", "format": "date" },
    "due_date": { "type": "string", "format": "date" },
    "customer_email": { "type": "string", "format": "email" },
    "payment_url": { "type": "string", "format": "uri" },
    "payment_status": { "type": "string", "enum": ["due", "paid", "overdue", "partial"] }
  }
}

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": "invoice",
    "raw_mime": "From: billing@acmesupplies.com\r\nTo: ap@buyerco.com\r\nSubject: Invoice INV-2026-0481 from Acme Supplies — due June 30\r\n\r\nHi Buyer Co.,"
  }'

Prefer not to handle the email yourself? Inbox forwarding — pointing your AP inbox or a vendor’s billing notifications at a unique address MailFrame assigns you — is on the roadmap, alongside PDF and image input for invoices that arrive as attachments. Until those ship, 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_b41f7e",
  "schema": "invoice",
  "data": {
    "invoice_number": "INV-2026-0481",
    "vendor_name": "Acme Supplies",
    "amount_due_cents": 125000,
    "currency": "usd",
    "due_date": "2026-06-30",
    "payment_status": "due"
  },
  "confidence": { "invoice_number": 0.99, "amount_due_cents": 0.98, "due_date": 0.97 },
  "received_at": "2026-06-15T13:00:11Z"
}

For synchronous delivery, use POST /v1/parse as shown above — the response returns typed JSON for every successful extraction.

Working with payment data from a specific provider? See the Stripe receipt schema and PayPal receipt schema, or the email-to-JSON API guide for a full walkthrough.

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