Real enterprise documents are rarely clean text. A single supplier invoice might carry a scanned signature, a line-item table, and a photo of damaged goods. This pattern builds one ingestion pipeline that classifies incoming files, sends each through the right Claude input path, and lands validated structured data — using the model's native PDF and vision support instead of a brittle OCR-then-parse chain.
How Claude actually reads a PDF
Send a PDF as a document content block and the platform processes each page twice: the page is converted to an image and its extracted text is provided alongside. That dual view is why tables, stamps, and layout survive — Claude sees the picture, not just the character stream. It also means dual token cost: typically 1,500–3,000 text tokens per page depending on density, plus image tokens under the vision formula. Limits to build around: 32 MB per request and up to 600 pages (100 pages when the request's context window is under 1M tokens); password-protected PDFs are not supported. Dense documents can fill the context window before the page limit — split at logical boundaries in code.
Standalone images (JPEG, PNG, GIF, WebP) go in image blocks and are tokenized in 28x28-pixel patches: ceil(width/28) x ceil(height/28), so a 1000x1000 image costs 1,296 tokens. High-resolution-tier models such as Sonnet 5 and Opus 4.8 accept larger images (long edge up to 2576 px) and can use up to ~3x more visual tokens — downsample in your pipeline when you don't need the fidelity, since oversized images are otherwise downscaled automatically on the platform's terms, not yours.
Platform routing rules
The pipeline's file-transport layer must adapt per platform:
| Concern | Claude API / Claude Platform on AWS | Bedrock / Google Cloud | Foundry |
|---|---|---|---|
| PDF & image input | URL, base64, or Files API file_id | base64 only | PDF input GA |
| Max image size | 10 MB | 5 MB | check docs |
| Files API | Available (beta) | Not available | Beta (Hosted-on-Anthropic) |
The Files API matters at volume: uploading once (500 MB per file, 500 GB per organization) and referencing by file_id keeps each request small, where inline base64 can hit the 32 MB request cap long before you hit image-count limits. On Bedrock and Google Cloud, base64-only transport means your splitter should also compress. Note that .docx and .xlsx are not supported as document blocks anywhere — convert to PDF or plain text upstream.
Tables: extract with grounding, then structure
Tables are where mixed pipelines usually fail silently, so use two documented features together — in two passes, because they cannot be combined in one request. First pass: enable citations on the document ("citations": {"enabled": true}) and extract line items; PDF citations return page_location references so reviewers can verify each row against the source page. Scanned pages without extractable text cannot be cited — detect that case and route to OCR or human review. Second pass: convert the verified extraction to schema-guaranteed JSON with structured outputs for your database. On Bedrock specifically, the Converse API needs citations enabled to get full visual PDF understanding; without them it falls back to text-only extraction, which is exactly wrong for tables.
The assembled pipeline
End to end, recommended practice looks like: a classifier stage in code sorts files by type and size; a normalizer converts unsupported formats and downsamples oversized images; transport picks Files API or base64 per platform; extraction runs the citation pass, then the structuring pass; validation applies business rules in code; and everything below your review threshold queues for humans. Every stage except the two Claude calls is deterministic — keep it that way.
Where to go next
See vision and documents, the Files API, and document processing use cases for adjacent patterns.