Po Acknowledgment Matcher avatar

Po Acknowledgment Matcher

Pricing

Pay per usage

Go to Apify Store
Po Acknowledgment Matcher

Po Acknowledgment Matcher

Pricing

Pay per usage

Rating

0.0

(0)

Developer

ceeb

ceeb

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

20 days ago

Last modified

Categories

Share

A conservative, machine-callable Apify Actor that compares a normalized purchase order with a supplier acknowledgment and returns structured discrepancies.

The V0 goal is narrow: answer "What did the supplier change?" without trying to become an ERP, procurement platform, or workflow system.

Current scope

V0 accepts normalized JSON in a standard Actor run or over the Standby HTTP API.

For a standard run, use example-input.json as the input. The run compares one document pair, writes one comparison to its default dataset, and exits. Invalid input fails without writing a comparison. Standby runs retain the HTTP endpoints below and return results directly without writing a dataset. No billing event is implemented in either mode.

It compares:

  • purchase-order number
  • supplier identity
  • currency
  • freight and document total
  • line number and SKU
  • quantity
  • unit of measure
  • unit price
  • requested vs. confirmed delivery date
  • acknowledgment line status
  • missing PO lines
  • extra acknowledgment lines

Matching is deliberately conservative:

  • exact line number is preferred
  • otherwise an exact unique SKU may match
  • candidates are checked across both complete documents before pairing; contested candidates are always REVIEW
  • the Actor never guesses an ambiguous line match
  • numeric and date comparisons are deterministic after normalization

PDF extraction is intentionally deferred until the normalized matcher passes its benchmark suite.

API

Health

GET /
GET /health

Compare

POST /match
Content-Type: application/json

Example request:

{
"purchase_order": {
"document_id": "PO-1001",
"supplier": {"id": "ACME"},
"currency": "USD",
"freight": 0,
"total": 1840,
"lines": [
{
"line_number": "10",
"sku": "ABC-492",
"quantity": 100,
"uom": "EA",
"unit_price": 18.40,
"requested_date": "2026-10-12"
}
]
},
"acknowledgment": {
"document_id": "ACK-77",
"purchase_order_number": "PO-1001",
"supplier": {"id": "ACME"},
"currency": "USD",
"freight": 0,
"total": 1915,
"lines": [
{
"line_number": "10",
"sku": "ABC-492",
"quantity": 100,
"uom": "EA",
"unit_price": 19.15,
"confirmed_date": "2026-11-03",
"status": "accepted"
}
]
}
}

Example response:

{
"status": "REVIEW",
"purchase_order_number": "PO-1001",
"acknowledgment_id": "ACK-77",
"summary": {
"purchase_order_lines": 1,
"acknowledgment_lines": 1,
"matched_lines": 0,
"review_lines": 1,
"missing_lines": 0,
"extra_lines": 0,
"exception_count": 3
},
"exceptions": [
{
"code": "TOTAL_CHANGED",
"status": "REVIEW",
"field": "total",
"ordered": 1840,
"acknowledged": 1915,
"po_line": null,
"ack_line": null,
"sku": null,
"delta": 75.0,
"delta_pct": 4.0760869565,
"evidence": {
"purchase_order": {"path": "purchase_order.total", "value": 1840},
"acknowledgment": {"path": "acknowledgment.total", "value": 1915}
}
}
],
"line_results": []
}

The actual response includes every detected exception and every matched/missing/extra line result.

Optional tolerances

{
"tolerances": {
"price_abs": 0.01,
"price_pct": 0,
"quantity_abs": 0,
"date_days": 0
}
}

A price difference is flagged only when it exceeds both the absolute and percentage thresholds.

Input validation

Both documents must provide a lines array of objects, and the PO must contain at least one line. An empty acknowledgment array is valid and reports missing PO lines. Null, empty, and whitespace-only acknowledgment values require review when the corresponding PO value is populated, including freight and total.

Supplied numbers and dates are validated even on unmatched lines. Numbers must be finite; nonzero numeric magnitudes must be at least 1e-100 and less than 1e101, keeping delta calculations representable in JSON. Tolerances must be nonnegative, and date_days must be an integer. Identifiers and text fields accept strings or numbers, not arrays, objects, or booleans.

Malformed JSON or invalid encoding returns HTTP 400; invalid document input returns HTTP 422; bodies over 2 MiB return HTTP 413. HTTP results are returned directly, without writing a dataset.

MATCH applies to the supplied PO fields; it does not establish that an upstream extraction captured every required business field.

Result statuses

  • MATCH — no configured discrepancy found
  • REVIEW — one or more discrepancies or ambiguities require attention
  • MISSING_IN_ACK — a PO line could not be found in the acknowledgment
  • EXTRA_IN_ACK — an acknowledgment line could not be tied to a PO line

Safety invariant

The commercial benchmark is asymmetric:

A doubtful line may become REVIEW, but it must never become a false MATCH.

That principle takes precedence over maximizing automatic match rate.

Development

Run unit tests:

$python -m unittest discover -s tests -v

Run the Actor locally with the Apify CLI:

$apify run

The Actor keeps the Apify Standby readiness endpoint required by the template.

V0 benchmark cases

The included tests cover:

  • exact match
  • changed price
  • changed delivery date
  • missing line
  • extra line
  • SKU fallback matching
  • ambiguous duplicate SKU
  • PO number mismatch
  • supplier mismatch
  • tolerances
  • non-accepted line status
  • invalid dates and malformed/non-finite values
  • blank acknowledgment fields and missing document amounts
  • contested candidates on either side and input-order invariance
  • 100-line synthetic documents with price, quantity, and date changes
  • HTTP health/readiness, error responses, body limits, and abort cleanup

CI runs the matcher and HTTP tests on Python 3.12 and 3.14 (the Docker runtime). The next publication gate is a private platform benchmark with representative procurement documents and zero false MATCH results. Local tests do not substitute for platform validation.

Not in V0

  • OCR
  • PDF parsing
  • ERP integrations
  • user accounts
  • dashboards
  • write-back to purchasing systems
  • automatic approval/rejection decisions
  • billing or monetization logic