Accounts Payable Intake: PO Matching and Exception Workflows

Overview

AP automation is less about “AI” and more about disciplined intake: clean purchase data, receipt signals, and predictable exception handling.

Quick definition

AP intake matches invoices to PO lines using vendor IDs, amounts, tolerances, and three-way match (PO, receipt, invoice) before posting—exceptions route to approvers.


Definition

PO matching compares purchase order lines, receipts, and invoices—flagging quantity, price, and tax variances for review.

Why it matters

Payment errors and late payments damage vendor relationships and audit posture. Automation should accelerate *matching*, not bypass controls.

Core framework

Step-by-step model as TypeScript interfaces (machine-readable checkpoints).

Standardize vendor channels

TypeScript
/** * Standardize vendor channels * Email PDFs, EDI, portals—normalize into one intake queue. */ export interface CoreFrameworkStep1StandardizeVendorChannels { /** Order in the core framework (0-based) */ readonly stepIndex: 0; /** Display title for this step */ readonly title: "Standardize vendor channels"; /** Narrative checkpoints as published in the guide */ readonly narrative: readonly string[]; } export const CoreFrameworkStep1StandardizeVendorChannels_NARRATIVE: readonly string[] = [ "Email PDFs, EDI, portals—normalize into one intake queue." ] as const;

Exception taxonomy

TypeScript
/** * Exception taxonomy * Reason codes: price mismatch, missing receipt, duplicate invoice. */ export interface CoreFrameworkStep2ExceptionTaxonomy { /** Order in the core framework (0-based) */ readonly stepIndex: 1; /** Display title for this step */ readonly title: "Exception taxonomy"; /** Narrative checkpoints as published in the guide */ readonly narrative: readonly string[]; } export const CoreFrameworkStep2ExceptionTaxonomy_NARRATIVE: readonly string[] = [ "Reason codes: price mismatch, missing receipt, duplicate invoice." ] as const;

Detailed breakdown

Logic sections encoded as Python functions with structured narrative payloads.

Segregation of duties

Python
def logic_block_1_segregation_of_duties(context: dict) -> dict: """Operational logic: Segregation of duties""" # Narrative steps from the guide (logic section) paragraphs = ["Automation roles must not combine approval and payment initiation against policy."] return { "heading": "Segregation of duties", "paragraphs": paragraphs, "context_keys": tuple(sorted(context.keys())), }

Technical patterns

Three-way match

  • Join invoice, PO, and receipt lines; apply tolerances before posting.
Python
def match_three_way(inv_line: dict, po_line: dict, rcpt_line: dict, *, price_tol_pct: float) -> bool: """invoice_line ↔ po_line ↔ receipt_line on SKU/qty with price tolerance.""" if inv_line["sku"] != po_line["sku"] or inv_line["sku"] != rcpt_line["sku"]: return False qty_ok = inv_line["qty"] <= po_line["qty"] and inv_line["qty"] <= rcpt_line["qty_received"] price_a, price_b = inv_line["unit_price"], po_line["unit_price"] price_ok = abs(price_a - price_b) / max(price_a, price_b) <= price_tol_pct return qty_ok and price_ok

Code examples

Tolerance check

Flags variance for workflow.

TypeScript
export function withinTolerance(a, b, pct = 0.01) { return Math.abs(a - b) / Math.max(a, b) <= pct; }

System architecture

YAML
[Invoice ingest: EDI / email / portal] [OCR + field extract] [PO lookup + receipt lookup] [Match engine → post | exception] [ERP GL]

Real-world example

A manufacturer cut invoice cycle time by routing only true exceptions to AP specialists—routine matches posted automatically.

Common mistakes

  • OCR without validation—garbage in, wrong payments out.
  • No audit trail linking invoice to PO and receipt artifacts.

PrimeAxiom connects AP workflows to ERP and CRM context—book a finance automation review.