Skip to main content

Overview

Math Verification transforms Parsefy from a probabilistic extraction tool into a deterministic verification platform. When enabled, Parsefy automatically verifies that extracted numeric data is mathematically consistent.
Validated output or fail loudly. Math verification ensures totals match subtotals + tax, line items sum correctly, and cross-field calculations are accurate.

How It Works

1

Schema Analysis

Parsefy scans your schema for verifiable fields (totals, subtotals, taxes, line items)
2

Rule Synthesis

Mathematical rules are automatically generated based on detected field roles
3

Secure Evaluation

Extracted values are verified against the synthesized rules
4

Result Reporting

Verification results are included in the API response

Enabling Verification

const { object, metadata, verification } = await client.extract({
  file: './invoice.pdf',
  schema,
  enableVerification: true, // Enable math verification
});

if (verification) {
  console.log(`Status: ${verification.status}`);
  console.log(`Checks passed: ${verification.checks_passed}`);
  console.log(`Checks failed: ${verification.checks_failed}`);
}

Verification Response

When enable_verification is set to true, the response includes a verification object:
{
  "verification": {
    "status": "PASSED",
    "checks_passed": 2,
    "checks_failed": 0,
    "cannot_verify_count": 0,
    "checks_run": [
      {
        "type": "HORIZONTAL_SUM",
        "status": "PASSED",
        "fields": ["total", "subtotal", "tax"],
        "passed": true,
        "delta": 0.0,
        "expected": 1250.00,
        "actual": 1250.00
      },
      {
        "type": "VERTICAL_SUM",
        "status": "PASSED",
        "fields": ["subtotal", "line_items"],
        "passed": true,
        "delta": 0.0,
        "expected": 1150.00,
        "actual": 1150.00
      }
    ]
  }
}

Verification Status Values

StatusDescription
PASSEDAll math checks passed
FAILEDOne or more math checks failed
PARTIALSome checks passed, some failed or couldn’t be verified
CANNOT_VERIFYRequired fields are missing (not a math error)
NO_RULESNo verifiable fields detected in schema

Supported Verification Rules

Rule TypeFormulaExample
HORIZONTAL_SUMtotal = subtotal + taxInvoice total verification
VERTICAL_SUMsubtotal = sum(items)Line item sum verification

Check Result Fields

Each check in checks_run contains:
FieldTypeDescription
typestringType of check: HORIZONTAL_SUM or VERTICAL_SUM
statusstringCheck status: PASSED, FAILED, or CANNOT_VERIFY
fieldsarrayFields involved in this check
passedbooleanWhether the check passed
deltanumberDifference between expected and actual values
expectednumberExpected value from the verification rule
actualnumberActual value extracted from the document

Shadow Extraction

When verification is enabled and only a single verifiable field is requested (e.g., just total), Parsefy automatically extracts supporting fields in the background:
  1. User requests: { "total": { "type": "number" } } with enable_verification=true
  2. Parsefy internally expands to include shadow fields: subtotal, tax, line_items
  3. LLM extracts all fields
  4. Math verification runs
  5. Shadow fields are removed before response
This ensures verification even when users only need the final total.

Best Practices

Include Verification Fields

For best verification, include subtotal, tax, and total in your schema

Use for Financial Data

Enable verification for invoices, receipts, and bills where math accuracy is critical

Handle Failures Gracefully

When verification fails, flag for manual review rather than rejecting outright

Check Individual Results

Review checks_run to identify which specific calculations failed

Example: Full Invoice Extraction with Verification

import { Parsefy } from 'parsefy';
import * as z from 'zod';

const client = new Parsefy();

const invoiceSchema = z.object({
  invoice_number: z.string().describe('The invoice number'),
  subtotal: z.number().describe('Subtotal before tax'),
  tax: z.number().describe('Tax amount'),
  total: z.number().describe('Total amount including tax'),
  line_items: z.array(z.object({
    description: z.string(),
    quantity: z.number(),
    unit_price: z.number(),
    amount: z.number(),
  })).optional().describe('Line items'),
});

const { object, verification, error } = await client.extract({
  file: './invoice.pdf',
  schema: invoiceSchema,
  enableVerification: true,
});

if (!error && object) {
  console.log(`Invoice #${object.invoice_number}`);
  console.log(`Total: $${object.total}`);
  
  if (verification) {
    if (verification.status === 'PASSED') {
      console.log('Math verification passed!');
    } else {
      console.log(`Verification: ${verification.status}`);
      verification.checks_run.forEach(check => {
        if (!check.passed) {
          console.log(`  Failed: ${check.type}`);
          console.log(`    Expected: ${check.expected}, Actual: ${check.actual}`);
          console.log(`    Delta: ${check.delta}`);
        }
      });
    }
  }
}

Next Steps