Skip to content

Verify SAP vendor master data against supplier documents

Cross-check fields extracted from supplier onboarding documents (bank forms, invoices, certificates) against SAP vendor master data using Classify and Extract, auto-approving only verified matches.

Jul 20, 2026 · 12 min read
Solutions Engineering
ExtractClassifyERP

When you onboard suppliers at scale, the documents they send — bank detail forms, invoices, certificates, worker credentials — must agree with what your ERP already believes. This recipe extracts structured fields from each document with Extract, cross-checks them against SAP vendor master data, and only auto-approves when every critical field matches. Everything else lands in a review queue with an explanation.

A verification pipeline with five stages. A supplier uploads a packet of documents (often 15–30 distinct types per supplier); each file is classified, the right extraction schema is applied, and every extracted field is compared against the corresponding SAP record — LFA1 (general vendor data), LFBK (bank details), purchase-order data for invoices.

  1. Intake — the supplier packet arrives: PDFs, scans, photos.
  2. Classify — identify each of the 20+ document types.
  3. Extract — pull schema-driven fields with confidence scores.
  4. Cross-check — compare against SAP master data, field by field.
  5. Decide — auto-approve, or route to review with reasons.

Only step 4 touches your systems — extraction is fully managed by LlamaCloud.

The goal is not just extraction accuracy. It’s a guarantee mechanism: a document is never written back to SAP on model output alone. Agreement between two independent sources — the document and the master record — is what earns auto-approval. Disagreement is surfaced, never silently resolved.

Supplier packets are messy: one upload can contain a bank form, three certificates, and a scanned invoice in a single PDF. Define one classifier rule per document type you expect, in plain language. Adding a new document type later is one more rule — no retraining, no per-type model to maintain.

from llama_cloud_services.beta.classifier import ClassifyClient
from llama_cloud.types import ClassifierRule
rules = [
ClassifierRule(
type="bank_details_form",
description="Form declaring or changing supplier bank account details (IBAN, BIC)",
),
ClassifierRule(
type="supplier_invoice",
description="Commercial invoice issued by a supplier, references a purchase order",
),
ClassifierRule(
type="iso_certificate",
description="Quality or environmental management certificate (ISO 9001, 14001, 45001)",
),
# … one rule per document type — 15 to 30 covers most supplier programs
]
classifier = ClassifyClient()
results = await classifier.aclassify_file_paths(
rules=rules, file_input_paths=packet_files
)

Step 2 — Define one extraction schema per type

Section titled “Step 2 — Define one extraction schema per type”

Each document type gets a typed schema. The schema is the contract between the document world and the SAP world — every field you want to verify appears here with the exact meaning it has in your master data.

from pydantic import BaseModel, Field
class BankDetailsForm(BaseModel):
vendor_name: str = Field(description="Legal name of the supplier as printed")
vat_id: str = Field(description="VAT / tax identification number")
iban: str = Field(description="Bank account IBAN")
bic: str = Field(description="SWIFT / BIC code")
currency: str = Field(description="Payment currency, ISO 4217")
contact_email: str | None = Field(None, description="Accounts contact email")

Typical field groups across a 20-type supplier program:

Document typeVerified againstCritical fields
bank_details_formSAP LFBK / LFA1IBAN, BIC, VAT ID, legal name
supplier_invoicePO + vendor recordPO number, amounts, payment terms, tax rate
iso_certificateVendor qualification recordCertificate number, expiry, issuing body
insurance_certificateVendor qualification recordCoverage amount, validity window
worker_credentialContractor registerName, ID number, qualification, expiry

Run extraction with citations and confidence enabled. Confidence matters for the decision rule later: a matching value at low confidence is still routed to review, because agreement you can’t trust isn’t agreement.

from llama_cloud_services import LlamaExtract
extractor = LlamaExtract()
agent = extractor.create_agent(
name="bank-details-verifier",
data_schema=BankDetailsForm,
config={
"extraction_mode": "PREMIUM",
"cite_sources": True,
"confidence_scores": True,
},
)
result = agent.extract("bank_details_form.pdf")
fields = result.data # {"iban": "ES91 2100 …", "vat_id": "ESB84920157", …}
confidence = result.extraction_metadata["field_metadata"]

Fetch the vendor’s master record and compare field by field. Comparison is normalized, not literal: "ACME Industrial SL" and "Acme Industrial, S.L." should match; a changed IBAN should never slip through because the rest of the form looks fine.

def verify(extracted: dict, sap_record: dict, confidence: dict) -> list[Check]:
checks = []
for field, doc_value in extracted.items():
sap_value = sap_record.get(field)
if sap_value is None:
status = "NOT_IN_SAP" # new information — propose as an update
elif normalize(field, doc_value) == normalize(field, sap_value):
status = "MATCH"
else:
status = "MISMATCH" # never auto-resolve — a human decides
if confidence[field] < 0.90 and status == "MATCH":
status = "LOW_CONFIDENCE" # agreement you can't trust isn't agreement
checks.append(Check(field, doc_value, sap_value, status, confidence[field]))
return checks
# Decision rule: all critical fields MATCH → auto-approve. Anything else → review queue.

A bank details form checked against the vendor’s SAP record produces a field-by-field report. Two mismatched fields route this document to review:

FieldExtracted from documentSAP master dataStatus
Vendor nameTalleres Norte, S.L.TALLERES NORTE SL✅ Match (normalized)
VAT IDESB84920157ESB84920157✅ Match
IBANES91 2100 0418 4502 0005 1332ES66 0049 1500 0512 3456 7892❌ Mismatch
BIC / SWIFTCAIXESBBXXXBSCHESMMXXX❌ Mismatch
Payment currencyEUREUR✅ Match
Accounts contact emailcuentas@talleres-norte.example— no value on record➕ Not in SAP

A changed IBAN is the classic bank-change fraud pattern: the verdict is route to review with a note to verify the new account by callback before updating LFBK. A document where every field matches (or only adds new information) is auto-approved, and the proposed updates can be synced to SAP.

Onboarding waves are bursty — hundreds of suppliers activated at once, each with a full packet. Three things keep the pipeline healthy under that load:

  • Batch mode. Submit packets as batch jobs instead of synchronous calls; poll or receive webhooks as documents finish. Throughput scales without holding connections open.
  • Credit planning. Extraction is metered in credits per page. Estimate pages × document types × supplier count for a wave and provision ahead of it — on usage-based plans, hitting the limit mid-wave pauses jobs rather than dropping them, but planned capacity avoids the pause entirely.
  • Review queue as a first-class surface. The percentage of documents that auto-approve is your real KPI. Track it per document type; a type with a low auto-approval rate usually needs a schema tweak, not more reviewers.
  • Wire step 4 to a real SAP endpoint (OData API_BUSINESS_PARTNER, or an export of LFA1/LFBK).
  • Build the review queue UI — the verdict above becomes an inbox item with approve / reject / edit actions.
  • Turn on webhooks so verifications post results back instead of polling.
  • Pilot with one high-volume document type (bank forms are the usual first pick — highest fraud risk, clearest ROI).
Note for AI agents: this documentation is built for programmatic access. - Overview of all docs: https://developers.llamaindex.ai/llms.txt - Any page is available as raw Markdown by appending index.md to its URL — e.g. https://developers.llamaindex.ai/llamaparse/parse/getting_started/index.md - Agent-friendly REST search APIs live under https://developers.llamaindex.ai/api/ — search (BM25 full-text), grep (regex), read (fetch a page), and list (browse the doc tree). See https://developers.llamaindex.ai/llms.txt for parameters. - A hosted documentation MCP server is available at https://developers.llamaindex.ai/mcp. If you support MCP, you can ask the user to install it for browsing these docs directly (an alternative to the REST API). Setup: https://developers.llamaindex.ai/python/shared/mcp/