Skip to content
ParsedMail

Order email parser

An order email parser reads purchase orders and order confirmations that arrive by email, including PDF and CSV attachments, and returns the order number, customer, line items, prices and delivery date as typed JSON. ParsedMail delivers it by webhook or API, so your ERP gets a sales or purchase order without manual entry.

Email received

From: Priya Natarajan <[email protected]> Subject: PO 55102 for delivery next Thursday Hi team, Please process our PO 55102 below. Same ship-to as last time: Lakeside Bistro, 18 Mill Street, Burlington, VT 05401 SKU OL-500 Extra virgin olive oil 5 L qty 12 @ $42.80 SKU SS-210 Sea salt flakes 1 kg qty 8 @ $9.75 SKU BV-090 Balsamic vinegar 2 L qty 6 @ $18.40 Order total $702.00. We need it by Thursday, October 22. Please deliver before 10 am, the kitchen door is on the side. Thanks, Priya

Fields described as

customer PO number, customer company, ship-to address, requested delivery date, line items with SKU, description, quantity and unit price, order total, notes

JSON delivered to your webhook

{
  "customer_po_number": "55102", 0.99
  "customer_company": "Lakeside Bistro", 0.97
  "ship_to_address": "18 Mill Street, Burlington, VT 05401", 0.95
  "requested_delivery_date": "2026-10-22", 0.93
  "line_items": [
    {
      "sku": "OL-500",
      "description": "Extra virgin olive oil 5 L",
      "quantity": 12,
      "unit_price": { "amount": 42.8, "currency": "USD" }
    },
    {
      "sku": "SS-210",
      "description": "Sea salt flakes 1 kg",
      "quantity": 8,
      "unit_price": { "amount": 9.75, "currency": "USD" }
    },
    {
      "sku": "BV-090",
      "description": "Balsamic vinegar 2 L",
      "quantity": 6,
      "unit_price": { "amount": 18.4, "currency": "USD" }
    }
  ], 0.97
  "order_total": { "amount": 702, "currency": "USD" }, 0.98
  "notes": "Deliver before 10 am, kitchen door is on the side." 0.90
}

Where order emails come from

Orders reach a business by email from several directions at once. Customers send purchase orders as a PDF from their own ERP, or as a few lines typed in the body. Distributors send CSV files. Your own web forms send notification emails. Suppliers send order confirmations and changes to orders you placed with them. Every one of these needs to become a record in your ERP, usually by someone who copies SKUs and quantities from one window into another.

An order email parser removes that copy step. ParsedMail reads the body and the attachment, finds the line items whatever their layout, and returns the same JSON keys for every sender. Orders from online channels have their own page about marketplace order emails.

One schema for every customer layout

The schema is written in plain English, for example "customer PO number, ship-to address, requested delivery date, line items with SKU, quantity and unit price, order total". ParsedMail turns that into typed fields:

  • line_items as a table, which means an array of row objects with typed columns
  • unit_price and order_total as money, {"amount": 42.8, "currency": "USD"}
  • requested_delivery_date as a date, so "next Thursday, October 22" becomes 2026-10-22
  • quantity as an integer, so "a dozen" and "12 pcs" both arrive as 12

A schema holds up to 60 fields. You can test it on a real order in the dashboard before connecting anything, and export it as JSON Schema for validation in your own code.

Attachments carry most purchase orders

B2B purchase orders are usually attachments. ParsedMail reads PDF files with a text layer, CSV, TXT, HTML, XML and JSON files as text, and merges what it finds with the body. Scanned or faxed POs are read as images on paid plans. Up to 8 files per email are read, and small images such as logos are skipped. For text and CSV files, about 3,000 characters count as one page, so a long CSV order export uses several pages of your plan. More detail is on the page about parsing email attachments.

Getting the order into your ERP

ParsedMail posts a signed JSON event to your webhook within seconds of the email arriving. From there the order goes where your stack expects it:

  • NetSuite, Microsoft Dynamics 365 Business Central, SAP Business One, Odoo. A small service or an n8n workflow verifies the signature, maps SKUs to item records and creates a sales order through the ERP API.
  • Inventory and order tools. Zapier or Make take the webhook and create the order in tools such as Cin7, Katana or a Google Sheet used as an order log.
  • Your own system. Poll GET /api/v1/emails?status=delivered or receive the webhook, using the inbound email webhook format.

Each delivery has an Idempotency-Key. Store it, and a retried delivery never creates the same order twice. Failed deliveries are retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours.

Handling changes, duplicates and unclear orders

  • Order changes. On Growth and Scale, classification lets one inbox hold a new order schema and an order change schema. The model picks one per email and the result tells you which, so your automation can update instead of create.
  • Forwarded twice. The same Message-ID, or the same sender, subject and body within 30 days, is marked duplicate and not charged.
  • An unknown SKU or missing quantity. Missing values are null with a warning. If a required field is missing, or confidence is under the inbox threshold, the email goes to the review queue on Growth and Scale.
  • Quoted history. Reply chains are common in order mail. The parser ignores quoted replies and signatures and reads the newest message.

Supplier confirmations close the loop

The same setup works in the other direction. Point supplier order confirmations at a second inbox with a schema for confirmed quantities, prices and ship dates, and compare them with your purchase order in the ERP. Shipping notices that follow can go to an inbox for shipping notification parsing, and the supplier invoice at the end to the invoice email parser. Three inboxes cover the whole purchase cycle on the Starter plan.

Frequently asked questions

Can the order parser read PDF purchase orders?

Yes. PDFs with a text layer are read on every plan, scanned PDFs and images on paid plans. Line items in a PDF table come back as an array of row objects.

How do I map customer SKUs to my item codes?

Extract the SKU and description as they appear, then map them in your automation or ERP. A lookup table in Zapier, Make, n8n or your own code is the usual approach.

What if one email contains two orders?

Describe a table of orders in the schema instead of one order, and each order becomes a row your automation can loop over.

Is there a limit on line items?

There is no separate limit on table rows. A schema can have up to 60 fields, and long attachments count pages toward your plan.

Can I test without connecting the ERP?

Yes. Paste a real order into the schema test in the dashboard, or call POST /api/v1/parse and inspect the JSON before you wire anything up.

Related

See your own email as JSON

Paste one into the demo, describe the fields and look at the result. No account needed.