Skip to content

Inbound email API · n8n node

An email address in. Structured JSON out.

MailMint turns an incoming email into the fields you asked for — each one with a confidence we compute, the layer it came from, and the exact text of the message it was read out of. Delivered by webhook, by polling, or into n8n.

  • 300 parsed emails a month free
  • No card to sign up
  • POST /v1/parse stores nothing

The emailtext/plain

From
example-shop.com <auto-confirm@example-shop.com>
Subject
Your Example-Shop.com order of Anker 737 Power Bank...
Date
Tue, 19 Aug 2026 21:14:52 +0000
Hello Florian,

Thank you for your order. We'll send a
confirmation when your item ships.

Order # 114-7729183-4462618
Order Date: August 19, 2026

Arriving: Friday, August 22, 2026

Anker 737 Power Bank (PowerCore 24K)   $109.99
Qty: 1
Sold by: AnkerDirect

Item Subtotal: $109.99
Shipping & Handling: $0.00
Total Before Tax: $109.99
Estimated Tax: $9.35
Order Total: $119.34

What MailMint returnsapplication/json

{
  "fields": {
    "order_number": { "value": "114-7729183-4462618",
      "confidence": 0.97, "source": "rule+llm",
      "evidence": "Order # 114-7729183-4462618" },
    "order_date": { "value": "2026-08-19",
      "confidence": 0.97, "source": "rule+llm",
      "evidence": "Order Date: August 19, 2026" },
    "arriving": { "value": "2026-08-22",
      "confidence": 0.97, "source": "rule+llm",
      "evidence": "Arriving: Friday, August 22, 2026" },
    "total": { "value": { "amount": 119.34, "currency": "USD" },
      "confidence": 0.97, "source": "rule+llm",
      "evidence": "Total: $119.34" },
    "line_items": { "value": [
        { "description": "Anker 737 Power Bank (PowerCore 24K)",
          "qty": 1, "amount": 109.99 } ],
      "confidence": 0.97, "source": "rule+llm",
      "evidence": "anker 737 power bank (powercore 24k) $109.99" }
  },
  "flags": [],
  "needs_review": false
}
Real output, not a mock-up: MailMint’s own parser (packages/parser, the code behind POST /v1/parse) run on 25 September 2026 against fx-02-order-confirmation.eml from its test corpus, with a five-field schema. The model that answered was deepseek-ai/DeepSeek-V4-Flash-0731-TEE. The full response also carries the decoded headers, the body, attachments, tables, sender authentication and timings; it is trimmed here to the schema’s answers. Highlighted: the evidence each value was read from.

88 % / 95 %

Precision and recall on a hold-out set the parser had never seen: 36 adversarial messages, 163 labelled field slots.

91.6 %

Of field slots resolved by deterministic rules before any model runs. Those values are byte-identical run to run.

69 / 69

Genuine third-party DKIM signatures that verify against live DNS, from gmail.com, Fastmail, Pobox, GMX and others.

0

Competitors that return a per-field confidence or evidence span — checked across 363 vendor help articles and two API schemas.

Hold-out figures measured 31 August 2026, three runs (87.1–87.8 % and 91.5–93.6 %). On our own labelled corpus the pipeline scores 100 %, and we do not quote that, because a number measured on the cases you tuned against is not a number. 36 unseen messages is a small sample, not a general accuracy guarantee. The harness and every case it gets wrong are in packages/parser/.

How it works

Three steps, and no template to click together

You describe the fields in words. There is no sample to upload, no region to draw and no positional rule that breaks when a sender changes their layout.

  1. Describe the fields

    A name, one of 13 types and a sentence of description per field — string, date, currency, enum, typed arrays of objects and more. Change it over the API at any time.

    { "name": "total", "type": "currency",
      "description": "grand total incl. tax" }
  2. Send the mail

    Forward it to your mailbox’s own address on @smooth-operator.online, post raw MIME to /v1/parse, or drop the MailMint node after n8n’s IMAP or Gmail trigger.

    k7m2xq4h9bwz@smooth-operator.online
    invoices.k7m2xq4h9bwz@…   # slug alias
    k7m2xq4h9bwz+acme@…       # +tag survives
  3. Get JSON you can check

    A signed webhook, a polling feed or the n8n trigger. Route on one boolean: needs_review is true whenever any field is doubtful, missing or unsupported by the text.

    x-mailmint-signature: t=1787648043,v1=6a1f…
    { "id": "msg_01JQ8Z…", "needs_review": false,
      "fields": { … } }

Confidence & evidence

When it gets something wrong, it says so

“How do I find out that it went wrong?” is the question the n8n, Make and Zapier threads keep asking. Every value MailMint returns carries four keys — value, confidence, source and evidence — so the answer is in the payload.

  • Computed, never taken from the model. A model will report 0.95 on a value it invented, so its self-report may only ever lower a score. The ceiling comes from signals that can be checked.
  • The evidence check runs. If the quoted span is not really in the message, the score is capped at 0.3 and the field is flagged hallucinated_evidence:<field>.
  • Two extractors, independently. Deterministic rules and the model both run. Agreement earns "source": "rule+llm"; disagreement keeps the rule’s value, lowers the score and raises rule_llm_disagreement:<field>.
  • The arithmetic has to reconcile. Line items against the subtotal, subtotal + tax + shipping − discount against the total. Failing sets arithmetic_mismatch.
  • Missing is null. Never invented, never “N/A”, never a default you chose. A required field that is absent raises missing_required:<field>. The full rule.
fx-01-stripe-receipt.emlneeds_review: true
receipt_number"2451-8827"rule+llm
0.97

evidence Your receipt from Northwind Analytics #2451-8827

paid_on"2026-08-21"llm
0.93

evidence Paid August 21, 2026

total82.08 USDrule+llm
0.776

evidence Total $82.08

line_items3 rows — the third is “Sales tax”, 6.08rule
0.422

A summary row was read as a product, so the rows sum to 82.08 instead of the 76.00 subtotal.

flags arithmetic_mismatch suspect_row:line_items low_confidence:line_items

Also real output, run the same day on another corpus receipt — picked because it went wrong. The parser took the “Sales tax” line for a line item. It did not hide that: the arithmetic failed, the row was named as suspect, the field fell to 0.42 and the message came back with needs_review: true. That is the behaviour you are paying for.

What else is in the box

The unglamorous half, done properly

“We have an LLM” is not a product. The value is the part nobody wants to write: real MIME turned into clean text, tables that keep every row, and an honest answer about who sent it.

Forty rows in, forty rows out

Declare "type": "array" of objects and get a real nested array. Rows are found three ways — HTML grid, repeating DOM blocks, aligned text — and reconciled. row_count and truncated ride on every table; 1, 40 and 520-row tables come out complete.

Re-parse mail you already received

The original RFC822 bytes are kept, so a schema fix can be dry-run over last month’s real mail ("dry_run": true) and then applied. Re-delivery is a separate switch, so tuning never fires a month of webhooks at you. Every result carries parse.schema_version.

Attachments you can address

Each file is its own object with inline and content_id — the pair that separates the invoice PDF from the signature logo. GET /v1/attachments/:id serves the bytes. 25 MB inbound, 10 MB per stored attachment.

SPF, DKIM and DMARC, for real

Evaluated against live DNS, not copied from someone else’s header. A forward that broke the body hash is dkim: "body_altered", not fail. Where a result genuinely cannot be computed it says none instead of a pass we did not earn.

Clean text, reply chain removed

Quoted-printable decoded, legacy charsets normalised to UTF-8, RFC 2047 and 2231 resolved. You get the raw text, the HTML, text rendered from HTML, and body.stripped_text with the quoted thread and signature taken off.

Signed webhooks that retry

hmac_sha256(secret, t + "." + rawBody) with the timestamp inside the signature. Six attempts at 0 s, 30 s, 2 m, 10 m, 1 h and 6 h, a stable delivery id for idempotency, and several endpoints per mailbox, each with its own secret.

Built, not yet wired up — said plainly

MailMint does not read text out of a PDF attachment yet. The extractor exists (packages/docs: PDF text and tables, spreadsheets, DOCX, OCR fallback) and the response has the slot for it, attachments[].extracted, but nothing populates that slot today. A message whose data lives only inside the PDF gives you the file, its metadata and its checksum, not its contents.

The API

One request to try it. No address, no DNS.

POST /v1/parse takes raw MIME — or just a subject and a body — plus your schema, and returns the same object a mailbox would deliver. Nothing is stored.

  • Bearer key, JSON in, JSON out. Machine-readable reference at /openapi.json (OpenAPI 3.1).
  • Mailboxes when you are ready. Create one, get an address, set a webhook_url or read the /v1/events feed.
  • Filter on doubt. GET /v1/messages?needs_review=true is a review queue with no extra code.
# Stateless. No address, no DNS, nothing stored.
curl -X POST $MAILMINT_URL/v1/parse \
  -H "Authorization: Bearer $MAILMINT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "subject": "Invoice INV-2291 from Acme Ltd",
  "text": "Invoice INV-2291\n\nTotal: $31.50\nDue: Sep 8, 2026\n",
  "schema": [
    { "name": "invoice_number", "type": "string",
      "description": "the invoice or reference number" },
    { "name": "total", "type": "number",
      "description": "grand total including tax" },
    { "name": "due_date", "type": "date",
      "description": "when payment is due" }
  ]
}'

Integrations

The schema editor lives inside n8n

Other email parsers make you leave your automation tool to build a template. The n8n-nodes-mailmint community node does it on the canvas: name a field, give it a type and a sentence, hit Execute step, see the value.

  • No MailMint address needed. Put the node after n8n’s Email Trigger (IMAP) or a Gmail node and it parses what arrives.
  • A second output for anything doubtful. Route Messages Needing Review Separately adds a Needs Review branch. No IF node.
  • A trigger that registers its own webhook and verifies every HMAC before the workflow runs; polling mode for an n8n the internet cannot reach.
  • Eleven actions, zero runtime dependencies, MIT. Marked usableAsTool, so an n8n AI Agent can call it. Version 0.1.2 is in n8n’s verified registry since 1 September 2026, so it installs on n8n Cloud too.
The MailMint node in n8n, showing the Fields editor with fields such as total (Number, grand total including tax) and due_date (Date, when payment is due).
Defining the schema on the canvas: Name, Type, Description and Hint per field.
The same node after Execute step: an output table with invoice_number INV-2292, total 132, due_date 2026-09-15, _needs_review false and a _meta column.
One item out, _needs_review at the top level, everything else under _meta.

How it compares

Against the four products people actually use

Every cell comes from the vendor’s own pricing page, help centre or published API schema, fetched on 25 August 2026. Where a vendor publishes no figure the cell is empty rather than guessed.

Feature MailMint Mailparser Parseur Docparser Zapier Parser
Per-field confidenceYes — computed, with the evidence spanNoneNone — outcome is PARSEDOK / PARSEDKONone, bar one arithmetic presetNone
Where a value came fromsource + verbatim evidence————
Variable-row line itemsTyped array, with row_count and truncatedOne parsing rule per column, then “explode”; output is a flat cross-productTable Field — the best of the four; AI caps at 25 pagesSmart Tables: page 1 only, columns frozen at design timeCannot. Staff answer is {{shotnumberOne}}…
Reads the email bodyYesYesYesNo — stated in their own help centreYes
Reads PDF attachment contentsNot yet — extractor built, not yet wired inNo — points you at DocparserYesYesNo — attachments arrive zipped together
Re-parse mail already receivedAny stored message, any schema, from the original bytesLast 300 only; original bytes not keptYes, within the retention windowYes, bulk APINo — “there is no way to replay them”
Change the schema over the APIPATCH /v1/mailboxes/:id—No — templates are not programmableYes—
Entry priceFree for 300/mo, then $9 for 5,000 — $0.0018 each$29.95/mo for 250 emails — $0.1198 each, their own figure€49/mo for 100 emails — €0.49 each$39/mo for 100 documents — $0.39 eachFree
n8n nodeYes — 11 actions + a trigger, on npmNoneOfficial, published 21 Aug 2026 — upload + webhook onlyNoneNative to Zapier

Scroll the table sideways to see every column.

Sources: mailparser.io/pricing and 183 Mailparser help-centre articles; docparser.com/pricing, docparser.com/api and 180 Docparser help-centre articles; parseur.com’s own pricing endpoint and its published OpenAPI 3.1 schema; Zapier’s community forum, including staff replies. Parseur’s figures came back in EUR because their pricing endpoint geolocates. These are good products. If your mail is single-sender plain text with no attachments and you already pay for an LLM, n8n’s own Information Extractor node is genuinely sufficient and free.

Pricing

Per parsed email, not per seat

A parsed email is one message MailMint accepted and returned JSON for. A message that arrives flagged still counts; a message that never reached us does not. Free needs no card, and every plan can be cancelled from the dashboard in two clicks.

Free

$0 /month

300 parsed emails a month

  • Inbound address and POST /v1/parse
  • Webhooks, polling and the n8n node
  • Raw message kept 30 days
  • Attachment bytes kept 7 days
  • No card
  • Over the line: still delivered, flagged

Enough to run a real low-volume workflow rather than only to look at one.

Create an account

Starter

$9 /month

5,000 parsed emails a month

  • Everything in Free
  • Raw message kept 90 days
  • Attachment bytes kept 30 days
  • Re-parse anything still inside the window

Mailparser’s entry plan is $29.95 for 250 emails. This is twenty times the volume for less than a third of the price.

Start on Starter

Pro

$29 /month

25,000 parsed emails a month

  • Everything in Starter
  • Raw message kept 180 days
  • Attachment bytes kept 60 days

When several senders feed several mailboxes and a layout change has to be replayable months later.

Start on Pro

Scale

$99 /month

150,000 parsed emails a month

  • Everything in Pro
  • Raw message kept 365 days
  • Attachment bytes kept 90 days

Production volume, and a retention window that outlives an audit.

Start on Scale
What happens if you go over? Nothing is dropped and nothing bounces. A message past your monthly allowance is still received, parsed by the deterministic layer, stored and delivered — with the flag quota_exceeded and without the model pass, so fields the rules could not read come back null rather than guessed.
Every plan, including Free: per-field confidence with the evidence span, SPF, DKIM and DMARC verdicts, signed webhooks with retries, re-parse of stored mail, the n8n node, and the same parser. Paid plans buy volume and retention, never a better answer. The card is only asked for when you pick a plan in the dashboard.

Prices in US dollars, billed monthly by Stripe. VAT is added where it applies.

Questions

Before you wire anything up

Do I need an inbound address to try it?

No. POST /v1/parse takes raw MIME, or just a subject, text and html, plus your schema — and stores nothing at all. It is the same parser, the same response shape, and the same confidence numbers. The quickstart starts there.

Where does the confidence number come from?

Not from the model. It is computed from signals we can verify: whether the quoted evidence is really a verbatim substring of the message; whether the deterministic rules layer and the model independently agreed; whether the invoice arithmetic reconciles; and whether the value coerced cleanly to its declared type. The model’s own self-report is one input with the smallest weight, and it may only lower a score. The full rule is in the docs.

What happens to a message that fails to parse?

It is still delivered. A message with any flag on it arrives at your webhook with needs_review: true and the flags naming what went wrong and in which field. Nothing is ever silently dropped, and a field that could not be found is null — never invented, never a placeholder string.

Can I verify that a webhook really came from MailMint?

Yes. Every delivery carries x-mailmint-signature: t=<unix>,v1=<hex>, where the hex is hmac_sha256(secret, t + "." + rawBody). The timestamp is inside the signed string, so a captured request cannot be replayed. There are worked verification examples in Node and Python — copy one, do not guess.

Is any of this live?

Yes. The API is live at mailmint.app.mintapis.com; the hosted inbound address works — mail sent to your @smooth-operator.online address is received, authenticated and parsed; the n8n node is on npm and in n8n’s verified registry; and paid plans are live through Stripe. What does not exist yet: a published uptime history, an SLA, a SOC 2 report, or a customer logo or testimonial we have permission to quote. See the status page.

What about prompt injection from a hostile email?

It is a real risk in any product that pipes attacker-controlled email into a model, and we will not pretend it is solved. What exists is a structural mitigation, not a control: a value is only accepted with a high confidence when its evidence is a verbatim substring of the message, when the deterministic layer independently agrees, or when the arithmetic reconciles — none of which an instruction embedded in a body can manufacture. Treat parsed output as data, and check needs_review before acting on it.

Send one email and see what comes back

The shortest true path from nothing to structured JSON is one curl against /v1/parse. No address, no DNS, nothing stored.

Who runs this. MailMint is built and run by Florian Standhartinger in Passau, Germany. It is new, so there are no customer logos, testimonials or uptime history on this page, and there will not be invented ones. Every number here is either measured and dated, or taken from a competitor’s own page and attributed. Not true yet: attachment contents are not extracted, and there is no SLA or SOC 2 report.