Example

Invoice Parsing

Invoice fields from documents.

← All examples

Specification

$imports: [ 'types/money', 'types/date', 'types/payment-terms' ]
 
$flags: [ 'CASE_INSENSITIVE', 'MULTILINE', 'FLEXIBLE_WHITESPACE' ]

Header:

  Number:
    $types: { InvoiceNumber: '[A-Z]{2,5}-${Integer}' }
    $fields: { number: InvoiceNumber }
    $patterns: 'Invoice (No\.?|#):\s*#{number}'

Section:

  Date: 
    $fields: { date: Date }
    $patterns: 'Invoice Date:\s*#{date}'
  
  BillTo: 
    $types: { ClientName: '.*?' }
    $fields: { billTo: ClientName }
    $patterns: 'Bill To:\s*#{billTo}$'
  
  Subtotal:
    $fields: { subtotal: Money }
    $patterns: 'Subtotal:\s*#{subtotal}'
  
  Tax:
    $fields: { tax: Money }
    $patterns: 'Tax:\s*#{tax}'
  
  Amount: 
    $fields: { total: Money }
    $patterns: 'Total( Amount)?:\s*#{total}'
  
  Terms:
    $fields: { terms: PaymentTerms }
    $patterns: 'Payment Terms:\s*#{terms}'

Invoice: '${Header}( ${Section})+'

 

Imported types

types/number.yml
Number:
  Integer: '\d+(,\d{3})*'
  Decimal: '${Integer}\.${Integer}'
types/currency.yml
Currency:
  USD: '(USD|US\$|\$)'
  EUR: '(EUR|€)'
  GBP: '(GBP|£)'
types/money.yml
$imports: [ 'number', 'currency' ]

Money:
  $fields:
    currency: Currency
    amount: Number
  $patterns:
    - '#{currency}\s*#{amount}'
    - '#{amount}\s*#{currency}'
types/date.yml
$imports: 'number'

Date:
  ISO:
    $fields:
      year: { $type: Integer, $patterns: '\d{4}' }
      month: { $type: Integer, $patterns: '\d{2}' }
      day: { $type: Integer, $patterns: '\d{2}' }
    $patterns: '#{year}-#{month}-#{day}'
types/payment-terms.yml
$imports: 'number'

PaymentTerms:
  
  NetDays: 
    $fields:
      days: Integer
    $patterns: 'Net #{days}'
  
  DueOnReceipt: 'Due on Receipt'

Sample input

Invoice No: INV-1042
Invoice Date: 2026-05-15
Bill To: Acme Corp
Subtotal: $1,200.00
Tax: $96.00
Total Amount: USD 1,296.00
Payment Terms: Net 30

Invoice #: INV-1223
Invoice Date: 2026-06-13
Bill To: Meta Corp
Subtotal: $1,200,000.00
Tax: $96,000.00
Total: USD 1,296,000.00
Payment Terms: Due on Receipt

Result

[
  {
    "type": "Invoice",
    "text": "Invoice No: INV-1042\nInvoice Date: 2026-05-15\nBill To: Acme Corp\nSubtotal: $1,200.00\nTax: $96.00\nTotal Amount: USD 1,296.00\nPayment Terms: Net 30",
    "start": 0,
    "end": 145,
    "fields": [
      {
        "type": "InvoiceNumber",
        "field": "number",
        "text": "INV-1042",
        "start": 12,
        "end": 20
      },
      {
        "type": "Date::ISO",
        "field": "date",
        "text": "2026-05-15",
        "start": 35,
        "end": 45,
        "fields": [
          {
            "type": "Number::Integer",
            "field": "year",
            "text": "2026",
            "start": 35,
            "end": 39
          },
          {
            "type": "Number::Integer",
            "field": "month",
            "text": "05",
            "start": 40,
            "end": 42
          },
          {
            "type": "Number::Integer",
            "field": "day",
            "text": "15",
            "start": 43,
            "end": 45
          }
        ]
      },
      {
        "type": "ClientName",
        "field": "billTo",
        "text": "Acme Corp",
        "start": 55,
        "end": 64
      },
      {
        "type": "Money",
        "field": "subtotal",
        "text": "$1,200.00",
        "start": 75,
        "end": 84,
        "fields": [
          {
            "type": "Currency::USD",
            "field": "currency",
            "text": "$",
            "start": 75,
            "end": 76
          },
          {
            "type": "Number::Decimal",
            "field": "amount",
            "text": "1,200.00",
            "start": 76,
            "end": 84
          }
        ]
      },
      {
        "type": "Money",
        "field": "tax",
        "text": "$96.00",
        "start": 90,
        "end": 96,
        "fields": [
          {
            "type": "Currency::USD",
            "field": "currency",
            "text": "$",
            "start": 90,
            "end": 91
          },
          {
            "type": "Number::Decimal",
            "field": "amount",
            "text": "96.00",
            "start": 91,
            "end": 96
          }
        ]
      },
      {
        "type": "Money",
        "field": "total",
        "text": "USD 1,296.00",
        "start": 111,
        "end": 123,
        "fields": [
          {
            "type": "Currency::USD",
            "field": "currency",
            "text": "USD",
            "start": 111,
            "end": 114
          },
          {
            "type": "Number::Decimal",
            "field": "amount",
            "text": "1,296.00",
            "start": 115,
            "end": 123
          }
        ]
      },
      {
        "type": "PaymentTerms::NetDays",
        "field": "terms",
        "text": "Net 30",
        "start": 139,
        "end": 145,
        "fields": [
          {
            "type": "Number::Integer",
            "field": "days",
            "text": "30",
            "start": 143,
            "end": 145
          }
        ]
      }
    ]
  },
  {
    "type": "Invoice",
    "text": "Invoice #: INV-1223\nInvoice Date: 2026-06-13\nBill To: Meta Corp\nSubtotal: $1,200,000.00\nTax: $96,000.00\nTotal: USD 1,296,000.00\nPayment Terms: Due on Receipt",
    "start": 147,
    "end": 304,
    "fields": [
      {
        "type": "InvoiceNumber",
        "field": "number",
        "text": "INV-1223",
        "start": 158,
        "end": 166
      },
      {
        "type": "Date::ISO",
        "field": "date",
        "text": "2026-06-13",
        "start": 181,
        "end": 191,
        "fields": [
          {
            "type": "Number::Integer",
            "field": "year",
            "text": "2026",
            "start": 181,
            "end": 185
          },
          {
            "type": "Number::Integer",
            "field": "month",
            "text": "06",
            "start": 186,
            "end": 188
          },
          {
            "type": "Number::Integer",
            "field": "day",
            "text": "13",
            "start": 189,
            "end": 191
          }
        ]
      },
      {
        "type": "ClientName",
        "field": "billTo",
        "text": "Meta Corp",
        "start": 201,
        "end": 210
      },
      {
        "type": "Money",
        "field": "subtotal",
        "text": "$1,200,000.00",
        "start": 221,
        "end": 234,
        "fields": [
          {
            "type": "Currency::USD",
            "field": "currency",
            "text": "$",
            "start": 221,
            "end": 222
          },
          {
            "type": "Number::Decimal",
            "field": "amount",
            "text": "1,200,000.00",
            "start": 222,
            "end": 234
          }
        ]
      },
      {
        "type": "Money",
        "field": "tax",
        "text": "$96,000.00",
        "start": 240,
        "end": 250,
        "fields": [
          {
            "type": "Currency::USD",
            "field": "currency",
            "text": "$",
            "start": 240,
            "end": 241
          },
          {
            "type": "Number::Decimal",
            "field": "amount",
            "text": "96,000.00",
            "start": 241,
            "end": 250
          }
        ]
      },
      {
        "type": "Money",
        "field": "total",
        "text": "USD 1,296,000.00",
        "start": 258,
        "end": 274,
        "fields": [
          {
            "type": "Currency::USD",
            "field": "currency",
            "text": "USD",
            "start": 258,
            "end": 261
          },
          {
            "type": "Number::Decimal",
            "field": "amount",
            "text": "1,296,000.00",
            "start": 262,
            "end": 274
          }
        ]
      },
      {
        "type": "PaymentTerms::DueOnReceipt",
        "field": "terms",
        "text": "Due on Receipt",
        "start": 290,
        "end": 304
      }
    ]
  }
]

Notes

# Invoice Parsing

Extract invoice fields from a multi-line document without one giant regex.

## Notice

- `spec.yml` imports reusable money, date, and payment-term specs.
- `Header` recognizes the invoice number.
- `Section` contains the document fields: date, client, subtotal, tax, total, and terms.
- `Invoice` composes one header with repeated sections.

```yaml
$imports:
  - types/money
  - types/date
  - types/payment-terms
```

Try changing `Net 30` to `Due on Receipt`, or `Total Amount` to `Total`.