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.
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.
What you’ll build
Section titled “What you’ll build”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.
- Intake — the supplier packet arrives: PDFs, scans, photos.
- Classify — identify each of the 20+ document types.
- Extract — pull schema-driven fields with confidence scores.
- Cross-check — compare against SAP master data, field by field.
- 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.
Step 1 — Classify the incoming packet
Section titled “Step 1 — Classify the incoming packet”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 ClassifyClientfrom 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 type | Verified against | Critical fields |
|---|---|---|
bank_details_form | SAP LFBK / LFA1 | IBAN, BIC, VAT ID, legal name |
supplier_invoice | PO + vendor record | PO number, amounts, payment terms, tax rate |
iso_certificate | Vendor qualification record | Certificate number, expiry, issuing body |
insurance_certificate | Vendor qualification record | Coverage amount, validity window |
worker_credential | Contractor register | Name, ID number, qualification, expiry |
Step 3 — Extract with confidence scores
Section titled “Step 3 — Extract with confidence scores”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"]Step 4 — Cross-check against SAP
Section titled “Step 4 — Cross-check against SAP”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.Example verification run
Section titled “Example verification run”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:
| Field | Extracted from document | SAP master data | Status |
|---|---|---|---|
| Vendor name | Talleres Norte, S.L. | TALLERES NORTE SL | ✅ Match (normalized) |
| VAT ID | ESB84920157 | ESB84920157 | ✅ Match |
| IBAN | ES91 2100 0418 4502 0005 1332 | ES66 0049 1500 0512 3456 7892 | ❌ Mismatch |
| BIC / SWIFT | CAIXESBBXXX | BSCHESMMXXX | ❌ Mismatch |
| Payment currency | EUR | EUR | ✅ Match |
| Accounts contact email | cuentas@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.
Running it at onboarding scale
Section titled “Running it at onboarding scale”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 countfor 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.
Next steps
Section titled “Next steps”- 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).