---
title: "Mailroom automation with an API: Split, classify, route"
canonical_url: "https://www.nutrient.io/blog/mailroom-automation-api/"
md_url: "https://www.nutrient.io/blog/mailroom-automation-api.md"
last_updated: "2026-10-23T18:09:24.278Z"
description: "Build mailroom automation with an API: Split merged scans into documents, classify each one with your own labels, and route it, with a confidence score per step."
---

A mailroom scan rarely holds just one document. Yesterday’s mail goes through the scanner in batches, so one PDF can contain a claim form, two invoices, a contract amendment, and a copy of someone’s driver’s license. Before anything else happens, a person opens the file, works out where each document starts, decides what it is, and forwards it.

Mailroom automation is supposed to remove that step, and in a lot of setups, it doesn’t. The scanner works, the optical character recognition (OCR) works, and someone still sits between the scanner and the rest of the business, sorting pages.

This post builds the sorting part with Nutrient Data Extraction API: split the batch into documents, classify each one against your own labels, and route it. It also covers what to do with the documents the API isn’t sure about, because that’s where most of a mailroom’s real work ends up.

## What is mailroom automation?

Mailroom automation is software that takes incoming documents (scanned paper, email attachments, uploads) and gets each one to the right team or system without someone sorting it by hand. When the starting point is paper, you’ll often see it called a digital mailroom.

Most pipelines do four things, in this order.

1. Capture the paper or the files.

2. Separate each batch into individual documents.

3. Classify each document: invoice, claim, contract, ID.

4. Route it, and extract the fields the receiving team needs.

Scanners and intake tools usually cover capture already. This post is about steps 2 to 4, which start once you have a PDF.

## Why merged scans are the hard part

Many classification setups assume one file is one document. That holds for an invoice uploaded through a supplier portal. It falls apart with a scanner batch, a 30-page claim packet, or an email where someone attached everything as a single PDF.

The usual workarounds push the work back onto people. Separator sheets and barcodes mean someone prints a cover page and slots it between documents before scanning. Keyword rules (“a new document starts on any page with INVOICE at the top”) break the first time a supplier changes its layout. Templates per document type mean every new form waits until someone builds one.

Text alone also misses boundaries. The last page of one contract and the first page of the next can read almost the same. What gives the boundary away is often visual: a new letterhead, a different layout, a form header. That’s why [split](https://www.nutrient.io/api/data-extraction-api/split/) looks at the page image as well as the text.

## Why sorting needs a different kind of model

Sorting mail is a chain of small questions with fixed answers: whether a new document starts on this page; whether this is an invoice, a claim, or a contract; and whether a total is really on the page. None of them needs a paragraph in reply.

A general-purpose large language model (LLM) answers each one by writing text, one token at a time. That’s slow and costly when a morning batch holds hundreds of pages, and the answer still has to be parsed before code can act on it.

Split and classify run on the Nutrient document decision model, which is trained for document tasks. It reads the page image as well as the text, and it answers with a choice and a score instead of generated text:

- **Split** asks, page by page, whether a new document starts here.

- **Classify** scores each document against every label you send, so each label gets its own score.

- **Extract** checks that each value it returns is supported by the page.

Classify takes about half a second to a second per document, and split takes about five seconds per batch. On the public [document-splitting leaderboard](https://huggingface.co/spaces/nutrientdocs/doc-split-leaderboard), the model scores 96.2 percent F1 on splitting merged PDFs, where OpenAI’s Decision API scores 82.5 percent. It also runs fully on Nutrient’s own infrastructure, so pages aren’t sent to an outside model provider.

Austin Nguyen, the Nutrient AI engineer who built the model, covers how it was trained and where it wins in [an interview on the Nutrient blog](https://www.nutrient.io/blog/decision-model-for-documents.md). The [AI models page](https://www.nutrient.io/ai/models/) lists its benchmarks.

## The pipeline: Split, classify, route

Clear cases go straight to a team, and a person only sees the documents the API wasn’t sure about.

1. **Split** finds where each document starts and ends, and it returns the page ranges, separate PDFs, or both.

2. **Classify** scores each document against labels you pass in, like “invoice,” “insurance claim,” or “contract.” There’s no model to train and no template to maintain.

3. **Routing** is your own code. A score above your threshold goes to the matching queue; anything below goes to review.

4. **Extract** then pulls the fields each team needs, with a confidence score and the page each value came from. The document decision model checks each value against the page before it’s returned.

## Build a mailroom router in Python

The code makes two API calls and adds your own routing. It uses `requests` for the API and `pypdf` to cut each document out of the batch.

### 1. Split the batch into documents

The first call sends the batch to split, which returns one segment per document with its page range and a boundary confidence score:

```python

import io
import json

import requests
from pypdf import PdfReader, PdfWriter

API = "https://api.nutrient.io"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
BATCH = "morning-batch.pdf"

with open(BATCH, "rb") as f:
    split = requests.post(
        f"{API}/extraction/split",
        headers=HEADERS,
        files={"file": f},
        data={"instructions": json.dumps({"options": {"output": "json"}})},
    ).json()

# One segment per document found, in page order:

# {"output": {"segments": [

#   {"startPage": 1, "endPage": 3, "pageCount": 3, "boundaryConfidence": 1},

#   {"startPage": 4, "endPage": 5, "pageCount": 2, "boundaryConfidence": 0.61},...]}}

documents = split["output"]["segments"]

```

### 2. Classify each document with your own labels

[Classify](https://www.nutrient.io/api/data-extraction-api/classify/) scores a document against the labels you send in the request. To add a document type later, add a label:

```python

LABELS = [
    {"label": "invoice", "description": "A supplier invoice or bill"},
    {"label": "insurance claim", "description": "A claim form or claim packet"},
    {"label": "contract", "description": "A signed agreement or amendment"},
    {"label": "identity document", "description": "A passport, ID card, or driver's license"},
    {"label": "other"},
]

reader = PdfReader(BATCH)

def document_pdf(doc):
    """Cut one document's pages out of the batch."""
    writer = PdfWriter()
    for page in range(doc["startPage"] - 1, doc["endPage"]):
        writer.add_page(reader.pages[page])
    buffer = io.BytesIO()
    writer.write(buffer)
    return buffer.getvalue()

for doc in documents:
    result = requests.post(
        f"{API}/extraction/classify",
        headers=HEADERS,
        files={"file": ("document.pdf", document_pdf(doc), "application/pdf")},
        data={"instructions": json.dumps({"labels": LABELS})},
    ).json()
    top = result["output"]["classification"]   # The top-ranked label.

    doc["label"], doc["label_score"] = top["label"], top["score"]

```

Split can also return the separate PDFs as a ZIP, if you’d rather not cut the pages yourself.

### 3. Route on the result

The routing step is plain code. A document goes to its team’s queue when both scores clear the threshold, and to review otherwise:

```python

QUEUES = {
    "invoice": "accounts-payable",
    "insurance claim": "claims-intake",
    "contract": "legal",
    "identity document": "kyc",
}
THRESHOLD = 0.85   # A starting point; tune it on your own mail.

for doc in documents:
    sure = doc["boundaryConfidence"] >= THRESHOLD and doc["label_score"] >= THRESHOLD
    queue = QUEUES.get(doc["label"], "review") if sure else "review"
    send_to(queue, doc)   # Your queue, DMS, or workflow tool.

```

From there, [extract](https://www.nutrient.io/guides/dws-data-extraction/extract.md) can pull the fields each team cares about (invoice total, policy number, contract date) for the documents that landed in its queue. If you already route documents by type, the post on [routing documents with the classify API](https://www.nutrient.io/blog/route-documents-automatically-classify-api.md) covers that part in more depth.

## Leave the hard cases to people

Aim for a mailroom where people only handle the documents that need judgment. Pick a threshold, route everything above it automatically, and send the rest to a review queue. Include the page range and the top two labels with each item so the reviewer confirms a suggestion instead of starting from a blank screen.

Don’t guess the threshold. Run a week of real batches through the pipeline, compare the scores with what your reviewers decide, and move the threshold until the review queue holds the documents people actually change.

It’s also worth logging the reviewers’ corrections. They often point at a vague label. “Letter” gives the classifier little to go on; “proof of address” or “change of address request” gives it much more.

The scores tell you how sure the model is, not why. When a reviewer needs a written reason, such as why a page was flagged as a new document, send just those low-score cases to an LLM for an explanation. The clear cases stay fast and cheap, and only the hard ones pay for generated text.

## Try it on your own mail

The quickest test is a real batch from your scanner. Run it through [split](https://www.nutrient.io/api/data-extraction-api/split/) and [classify](https://www.nutrient.io/api/data-extraction-api/classify/), look at where the scores land, and you’ll know within an afternoon how much of your daily mail could skip the sorting desk.

Classify costs a flat 1 credit per page and split costs 3 credits per page. New accounts get 5,000 free credits a month, no credit card needed.

**Call to Action**

Get your free API key

[Learn More](https://dashboard.nutrient.io/sign_up/?product=data-extraction)

## FAQ

#### What is the difference between mailroom automation and a digital mailroom?

A digital mailroom turns incoming paper into digital files. Mailroom automation goes further: It separates, classifies, and routes those files without someone sorting them by hand.

#### Can an API split a scanned batch into separate documents?

Yes. The split endpoint of Nutrient Data Extraction API finds where each document starts and ends in a merged PDF and returns the page ranges, the separate files, or both.

#### Do I need to train a model on my document types?

No. Classify scores each document against the labels you send with the request, so adding a document type means adding a label.

#### What happens to documents the API is unsure about?

Classify returns a score with every label, and split returns one with every boundary. Send low scores to a review queue so a person confirms them.

#### What model do split and classify use?

They run on the Nutrient document decision model, which is trained for document tasks. It answers with a choice and a score instead of generated text, and it reads the page image as well as the text.

#### Are my documents sent to an outside AI provider?

No. The document decision model runs on Nutrient’s own servers, so pages aren’t sent to an outside model provider.

#### Does this replace my scanners or capture software?

No. Keep your capture step; the API works on the PDFs it produces.

#### Is it a virtual mailbox service?

No. Virtual mailbox services receive and scan your personal or business mail. This is an API for teams that already have documents coming in and need to sort them.
---

## Related pages

- [The business case for accessibility: Five ways it drives enterprise value](/blog/5-ways-accessibility-drives-enterprise-value.md)
- [Accessibility Untangled Why It Matters Guide](/blog/accessibility-untangled-why-it-matters-guide.md)
- [Advanced Techniques For React Native Ui Components](/blog/advanced-techniques-for-react-native-ui-components.md)
- [`vector_store` holds your indexed documents (see the multimodal RAG post](/blog/agentic-rag.md)
- [Ai Assistant Agent Governance](/blog/ai-assistant-agent-governance.md)
- [How to build an AI agent for contract redlining against a compliance playbook](/blog/ai-contract-redlining-compliance-playbook.md)
- [Ai Document Automation Extraction To Action](/blog/ai-document-automation-extraction-to-action.md)
- [Ai Document Workflows Ocr Compliance Heavy Teams](/blog/ai-document-workflows-ocr-compliance-heavy-teams.md)
- [Ai Legal Assistant Document Authoring](/blog/ai-legal-assistant-document-authoring.md)
- [Ai Schema Generator Document Extraction](/blog/ai-schema-generator-document-extraction.md)
- [Amazon Textract Alternatives](/blog/amazon-textract-alternatives.md)
- [Start (clears any prior buffer), navigate the document, then stop into a file.](/blog/android-faster-pdf-rendering.md)
- [Android Pdf Out Of Memory Handling](/blog/android-pdf-out-of-memory-handling.md)
- [Angular File Viewer Pdf Image Office Files](/blog/angular-file-viewer-pdf-image-office-files.md)
- [Approval Workflow Software](/blog/approval-workflow-software.md)
- [Approvals Matrix](/blog/approvals-matrix.md)
- [Apryse To Nutrient Migration](/blog/apryse-to-nutrient-migration.md)
- [Auto Tagging And Document Accessibility In Dotnet Sdk](/blog/auto-tagging-and-document-accessibility-in-dotnet-sdk.md)
- [Simple PII redaction.](/blog/automated-pii-removal.md)
- [Azure Document Intelligence Alternatives](/blog/azure-document-intelligence-alternatives.md)
- [Best Ai Document Workflow Platforms](/blog/best-ai-document-workflow-platforms.md)
- [Best Csharp Pdf Library](/blog/best-csharp-pdf-library.md)
- [Best Document Ai Platforms](/blog/best-document-ai-platforms.md)
- [Best Document Classification Platforms](/blog/best-document-classification-platforms.md)
- [Best document parser for RAG: LlamaParse vs. Unstructured vs. Reducto vs. Nutrient](/blog/best-document-parser-llamaparse-unstructured-reducto.md)
- [Best Document Parsing Apis](/blog/best-document-parsing-apis.md)
- [Best Document Viewers](/blog/best-document-viewers.md)
- [Best Llm Document Understanding Platforms](/blog/best-llm-document-understanding-platforms.md)
- [Best Multilingual Ocr Software](/blog/best-multilingual-ocr-software.md)
- [Best Pdf Parsers For Rag](/blog/best-pdf-parsers-for-rag.md)
- [Best Salesforce Document Generation Apps](/blog/best-salesforce-document-generation-apps.md)
- [Best Secure Document Collaboration Platforms](/blog/best-secure-document-collaboration-platforms.md)
- [Bpm Guide](/blog/bpm-guide.md)
- [Bpm Tools](/blog/bpm-tools.md)
- [Build Vs Buy Document Extraction](/blog/build-vs-buy-document-extraction.md)
- [Business Automation](/blog/business-automation.md)
- [Capex Vs Opex](/blog/capex-vs-opex.md)
- [The CEO’s AI playbook: Why decision architecture beats model selection](/blog/ceo-ai-playbook-decision-architecture.md)
- [1. Extract and chunk the PDF.](/blog/chat-with-pdf.md)
- [Complete Guide To Pdfjs](/blog/complete-guide-to-pdfjs.md)
- [Construction Document Data Extraction](/blog/construction-document-data-extraction.md)
- [Convert One Drive Files To Pdf In Sharepoint](/blog/convert-one-drive-files-to-pdf-in-sharepoint.md)
- [Create And Edit Pdfs In Flutter](/blog/create-and-edit-pdfs-in-flutter.md)
- [Create Pdfs With React](/blog/create-pdfs-with-react.md)
- [Creating A Document Scanner With Ocr In Python](/blog/creating-a-document-scanner-with-ocr-in-python.md)
- [Creating And Filling Pdf Forms Programmatically In Javascript](/blog/creating-and-filling-pdf-forms-programmatically-in-javascript.md)
- [The CTO’s AI playbook: Why accountability architecture beats orchestration](/blog/cto-ai-playbook-accountability-architecture.md)
- [Nutrient document decision: Why we built a decision model for documents](/blog/decision-model-for-documents.md)
- [Digital Signatures](/blog/digital-signatures.md)
- [Digital Workflow Automation](/blog/digital-workflow-automation.md)
- [Docling Alternatives](/blog/docling-alternatives.md)
- [Document Ai Vs Ocr](/blog/document-ai-vs-ocr.md)
- [Document Authoring Audit Trail](/blog/document-authoring-audit-trail.md)
- [Document Extraction Confidence Scores](/blog/document-extraction-confidence-scores.md)
- [Document Extraction For Underwriting](/blog/document-extraction-for-underwriting.md)
- [Document Viewer](/blog/document-viewer.md)
- [Document Watermarking](/blog/document-watermarking.md)
- [Debian/Ubuntu.](/blog/easyocr-vs-tesseract-python.md)
- [Electronic signature API: How to sign PDFs programmatically](/blog/electronic-signature-api.md)
- [Emerging threats: Your logging system may be an agentic threat vector](/blog/emerging-threats-your-logging-system.md)
- [Extend Alternatives](/blog/extend-alternatives.md)
- [Extract Patient Data On Premises](/blog/extract-patient-data-on-premises.md)
- [app.py](/blog/extract-text-from-pdf-using-python.md)
- [Stricter thresholds for fields that move money. Calibrate on your own sample.](/blog/extraction-hallucination-detection.md)
- [Fillable Pdf](/blog/fillable-pdf.md)
- [Google Document Ai Alternatives](/blog/google-document-ai-alternatives.md)
- [How To Add Digital Signature To Pdf Using React](/blog/how-to-add-digital-signature-to-pdf-using-react.md)
- [How To Build A Dotnet Maui Pdf Viewer](/blog/how-to-build-a-dotnet-maui-pdf-viewer.md)
- [How To Build A Flutter Pdf Viewer](/blog/how-to-build-a-flutter-pdf-viewer.md)
- [or](/blog/how-to-build-a-javascript-pdf-viewer-with-pdfjs.md)
- [or](/blog/how-to-build-a-javascript-pdf-viewer.md)
- [How To Build A Nextjs Pdf Viewer](/blog/how-to-build-a-nextjs-pdf-viewer.md)
- [How To Build A Powerpoint Viewer Using Javascript](/blog/how-to-build-a-powerpoint-viewer-using-javascript.md)
- [Using Yarn](/blog/how-to-build-a-react-excel-viewer.md)
- [How To Build A React Native Pdf Viewer](/blog/how-to-build-a-react-native-pdf-viewer.md)
- [How To Build A React Powerpoint Viewer](/blog/how-to-build-a-react-powerpoint-viewer.md)
- [Using Yarn](/blog/how-to-build-a-react-word-viewer.md)
- [How To Build A Reactjs File Viewer](/blog/how-to-build-a-reactjs-file-viewer.md)
- [How To Build A Reactjs Pdf Viewer With React Pdf](/blog/how-to-build-a-reactjs-pdf-viewer-with-react-pdf.md)
- [or](/blog/how-to-build-a-reactjs-pdf-viewer.md)
- [How To Build A Reactjs Viewer With Pdfjs](/blog/how-to-build-a-reactjs-viewer-with-pdfjs.md)
- [How To Build A Vuejs Pdf Viewer With Pdfjs](/blog/how-to-build-a-vuejs-pdf-viewer-with-pdfjs.md)
- [How To Build A Vuejs Pdf Viewer](/blog/how-to-build-a-vuejs-pdf-viewer.md)
- [How To Build An Android Pdf Viewer](/blog/how-to-build-an-android-pdf-viewer.md)
- [How To Build An Angular Pdf Viewer With Ng2 Pdf Viewer](/blog/how-to-build-an-angular-pdf-viewer-with-ng2-pdf-viewer.md)
- [How To Build An Angular Pdf Viewer With Pdfjs](/blog/how-to-build-an-angular-pdf-viewer-with-pdfjs.md)
- [How To Convert Docx To Pdf Using Javascript](/blog/how-to-convert-docx-to-pdf-using-javascript.md)
- [How To Convert Docx To Pdf Using Python](/blog/how-to-convert-docx-to-pdf-using-python.md)
- [How To Convert Html To Pdf Using Html2pdf](/blog/how-to-convert-html-to-pdf-using-html2pdf.md)
- [How To Convert Html To Pdf Using React](/blog/how-to-convert-html-to-pdf-using-react.md)
- [How To Convert Html To Pdf Using Wkhtmltopdf And Csharp](/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-csharp.md)
- [or](/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-python.md)
- [How To Convert Html To Pptx](/blog/how-to-convert-html-to-pptx.md)
- [How To Convert Pdf To Json](/blog/how-to-convert-pdf-to-json.md)
- [Quarterly report](/blog/how-to-convert-pdf-to-markdown-using-python.md)
- [How To Convert Word To Pdf In Nodejs](/blog/how-to-convert-word-to-pdf-in-nodejs.md)
- [or](/blog/how-to-create-a-react-js-signature-pad.md)
- [How To Create Pdfs With React To Pdf](/blog/how-to-create-pdfs-with-react-to-pdf.md)
- [How to digitally sign PDFs in C# with Nutrient .NET SDK](/blog/how-to-digitally-sign-pdf-in-csharp.md)
- [How To Edit Pdfs Using Ios Pdf Library](/blog/how-to-edit-pdfs-using-ios-pdf-library.md)
- [How To Embed A Pdf Viewer In Your Website](/blog/how-to-embed-a-pdf-viewer-in-your-website.md)
- [How To Extract Tables From Pdf And Images](/blog/how-to-extract-tables-from-pdf-and-images.md)
- [How To Generate Pdf From Html With Nodejs](/blog/how-to-generate-pdf-from-html-with-nodejs.md)
- [How to generate PDFs in C# with Nutrient .NET SDK](/blog/how-to-generate-pdf-in-csharp.md)
- [base_url tells WeasyPrint where to resolve relative asset paths](/blog/how-to-generate-pdf-reports-from-html-in-python.md)
- [How To Merge Pdfs Using Javascript](/blog/how-to-merge-pdfs-using-javascript.md)
- [How To Ocr Pdfs In Linux](/blog/how-to-ocr-pdfs-in-linux.md)
- [How To Print Pdf In Csharp](/blog/how-to-print-pdf-in-csharp.md)
- [How To Programmatically Create And Fill Pdf Form In Angular](/blog/how-to-programmatically-create-and-fill-pdf-form-in-angular.md)
- [C# barcode scanner: How to scan and read 1D barcodes and QR codes](/blog/how-to-scan-barcodes-in-csharp.md)
- [Open an image.](/blog/how-to-use-tesseract-ocr-in-python.md)
- [From an HTML string.](/blog/html-in-pdf-format.md)
- [Html To Pdf In Javascript](/blog/html-to-pdf-in-javascript.md)
- [Intelligent Data Extraction](/blog/intelligent-data-extraction.md)
- [Invoice Approval Software](/blog/invoice-approval-software.md)
- [Javascript Document Editor](/blog/javascript-document-editor.md)
- [Javascript Pdf Editors](/blog/javascript-pdf-editors.md)
- [Javascript Pdf Libraries](/blog/javascript-pdf-libraries.md)
- [Landing Ai Alternatives](/blog/landing-ai-alternatives.md)
- [Langextract Vs Llamaindex Extraction Comparison](/blog/langextract-vs-llamaindex-extraction-comparison.md)
- [Linearized Pdf](/blog/linearized-pdf.md)
- [Uses OpenAI by default — set OPENAI_API_KEY.](/blog/llamaindex-vs-langchain-rag.md)
- [Llamaindex Vs Langchain Vs Haystack](/blog/llamaindex-vs-langchain-vs-haystack.md)
- [Llamaindex Workflows Vs Langgraph](/blog/llamaindex-workflows-vs-langgraph.md)
- [Llamaparse Alternatives](/blog/llamaparse-alternatives.md)
- [Low Code No Code Document Integrations](/blog/low-code-no-code-document-integrations.md)
- [Material Requisition](/blog/material-requisition.md)
- [or](/blog/merge-pdfs.md)
- [Migrating Observability Hyperdx To Dash0](/blog/migrating-observability-hyperdx-to-dash0.md)
- [Swift Package Manager](/blog/mobile-pdf-sdk.md)
- [`elements` come from your document parser — each has a type and content.](/blog/multimodal-rag.md)
- [Multipage Extraction Page Boundaries](/blog/multipage-extraction-page-boundaries.md)
- [Nutrient Flutter 6 Bindings Api](/blog/nutrient-flutter-6-bindings-api.md)
- [Nutrient Flutter Bindings Architecture](/blog/nutrient-flutter-bindings-architecture.md)
- [Nutrient Vs Conga Composer](/blog/nutrient-vs-conga-composer.md)
- [Ocr Api Comparison](/blog/ocr-api-comparison.md)
- [Online Document Viewer](/blog/online-document-viewer.md)
- [Open Pdf In Your Web App](/blog/open-pdf-in-your-web-app.md)
- [Operations Management Software](/blog/operations-management-software.md)
- [Optical Character Recognition In Scanned Pdfs](/blog/optical-character-recognition-in-scanned-pdfs.md)
- [CPU](/blog/paddleocr-python-guide.md)
- [PDF accessibility for developers: Meeting WCAG 2.2, Section 508, and PDF/UA with an SDK](/blog/pdf-accessibility.md)
- [Extract data from PDF files: A developer guide to structured data from PDFs and scans](/blog/pdf-data-extraction-developer-guide.md)
- [Pdf Extraction Benchmark Opendataloader Bench](/blog/pdf-extraction-benchmark-opendataloader-bench.md)
- [Pdf Extraction Document Case Studies](/blog/pdf-extraction-document-case-studies.md)
- [Pdf Page Labels](/blog/pdf-page-labels.md)
- [Pdf Sdk Compliance Security Checklist](/blog/pdf-sdk-compliance-security-checklist.md)
- [Pdf Sdk Performance Benchmark](/blog/pdf-sdk-performance-benchmark.md)
- [Pdf Ua Compliance Guide](/blog/pdf-ua-compliance-guide.md)
- [Pdf Ua Validation](/blog/pdf-ua-validation.md)
- [Pdfjs Accessibility Structtree Printing](/blog/pdfjs-accessibility-structtree-printing.md)
- [Pdfjs Advanced Loading Streaming Workers](/blog/pdfjs-advanced-loading-streaming-workers.md)
- [Pdfjs Annotation Editor Layer](/blog/pdfjs-annotation-editor-layer.md)
- [Pdfjs Area Annotations Canvas Capture](/blog/pdfjs-area-annotations-canvas-capture.md)
- [Pdfjs Coordinate Systems Pdf To Screen](/blog/pdfjs-coordinate-systems-pdf-to-screen.md)
- [Pdfjs Document Outline Bookmarks Metadata](/blog/pdfjs-document-outline-bookmarks-metadata.md)
- [Pdfjs Eventbus Guide](/blog/pdfjs-eventbus-guide.md)
- [macOS](/blog/pdfjs-file-format-conversion-to-pdf.md)
- [macOS](/blog/pdfjs-generating-pdf-thumbnails-pdf2pic.md)
- [Pdfjs Limitations Commercial Upgrade](/blog/pdfjs-limitations-commercial-upgrade.md)
- [Pdfjs Native Annotation Layer Forms](/blog/pdfjs-native-annotation-layer-forms.md)
- [Pdfjs Navigation Zoom Rotation](/blog/pdfjs-navigation-zoom-rotation.md)
- [Pdfjs Pdf Page Manipulation Pdf Lib](/blog/pdfjs-pdf-page-manipulation-pdf-lib.md)
- [Pdfjs React Viewer Setup](/blog/pdfjs-react-viewer-setup.md)
- [Pdfjs Rendering Overlays React Portals](/blog/pdfjs-rendering-overlays-react-portals.md)
- [Pdfjs Server Side Text Extraction](/blog/pdfjs-server-side-text-extraction.md)
- [Pdfjs Sticky Note Annotations](/blog/pdfjs-sticky-note-annotations.md)
- [Pdfjs Text Highlight Annotations](/blog/pdfjs-text-highlight-annotations.md)
- [Pdfjs Text Search Pdffindcontroller](/blog/pdfjs-text-search-pdffindcontroller.md)
- [Pdfjs Thumbnail Sidebar](/blog/pdfjs-thumbnail-sidebar.md)
- [Pdfplumber Python Guide](/blog/pdfplumber-python-guide.md)
- [People Process Tools](/blog/people-process-tools.md)
- [Process Flows](/blog/process-flows.md)
- [React Docx Editor](/blog/react-docx-editor.md)
- [React Native Pdf Annotation](/blog/react-native-pdf-annotation.md)
- [React Pdf Annotation Layer Forms](/blog/react-pdf-annotation-layer-forms.md)
- [React Pdf Custom Rendering Hooks](/blog/react-pdf-custom-rendering-hooks.md)
- [Using Yarn](/blog/react-pdf-editor.md)
- [React Pdf Loading States Errors Passwords](/blog/react-pdf-loading-states-errors-passwords.md)
- [React Pdf Non Latin Fonts Special Pdfs](/blog/react-pdf-non-latin-fonts-special-pdfs.md)
- [React Pdf Outline Table Of Contents](/blog/react-pdf-outline-table-of-contents.md)
- [React Pdf Performance Optimization](/blog/react-pdf-performance-optimization.md)
- [React Pdf Setup Basic Rendering](/blog/react-pdf-setup-basic-rendering.md)
- [React Pdf Text Layer Custom Renderer](/blog/react-pdf-text-layer-custom-renderer.md)
- [React Pdf Thumbnails Page Navigation](/blog/react-pdf-thumbnails-page-navigation.md)
- [Reducto Alternatives](/blog/reducto-alternatives.md)
- [Requisition System](/blog/requisition-system.md)
- [labels.py](/blog/route-documents-automatically-classify-api.md)
- [or](/blog/sample-blog-updated.md)
- [Sdk Product Updates Q2 2026](/blog/sdk-product-updates-q2-2026.md)
- [System Of Record Vs Source Of Truth](/blog/system-of-record-vs-source-of-truth.md)
- [Add DWS MCP Server to your Claude Code project.](/blog/teaching-llms-to-read-pdfs.md)
- [Open an image file.](/blog/tesseract-python-guide.md)
- [The Six Best Pdf Generator Apis](/blog/the-six-best-pdf-generator-apis.md)
- [Define the HTML part of the document.](/blog/top-10-ways-to-generate-pdfs-in-python.md)
- [Top 5 Javascript Pdf Viewers](/blog/top-5-javascript-pdf-viewers.md)
- [Top Js Pdf Libraries](/blog/top-js-pdf-libraries.md)
- [Top Ten Ways To Convert Html To Pdf](/blog/top-ten-ways-to-convert-html-to-pdf.md)
- [Unstructured Alternatives](/blog/unstructured-alternatives.md)
- [Using Javascript In Pdf Form Fields](/blog/using-javascript-in-pdf-form-fields.md)
- [Vector Pdf](/blog/vector-pdf.md)
- [Wcag2 Accessibility Requirements Documents](/blog/wcag2-accessibility-requirements-documents.md)
- [Web Sdk Is Now Headless](/blog/web-sdk-is-now-headless.md)
- [What Are Annotations](/blog/what-are-annotations.md)
- [What Is A Vpat](/blog/what-is-a-vpat.md)
- [What Is Business Logic](/blog/what-is-business-logic.md)
- [What Is Document Processing](/blog/what-is-document-processing.md)
- [What Is Intelligent Document Processing](/blog/what-is-intelligent-document-processing.md)
- [What Is Ocr Invoice Processing](/blog/what-is-ocr-invoice-processing.md)
- [What Is Pdf Ua](/blog/what-is-pdf-ua.md)
- [Why Pdfium Is A Trusted Platform For Pdf Rendering](/blog/why-pdfium-is-a-trusted-platform-for-pdf-rendering.md)
- [Why Your Ai Agent Hallucinates Pdf Table Data](/blog/why-your-ai-agent-hallucinates-pdf-table-data.md)

