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
/**
* 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
/**
* 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
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.
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_okCode examples
Tolerance check
Flags variance for workflow.
export function withinTolerance(a, b, pct = 0.01) {
return Math.abs(a - b) / Math.max(a, b) <= pct;
}System architecture
[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.
Related topics
PrimeAxiom connects AP workflows to ERP and CRM context—book a finance automation review.