There's a small tool that keeps showing up in the sharing feeds: a PDF-to-Markdown converter aimed at people who paste PDFs into Obsidian or Notion and get tired of fixing formatting by hand. The maker was refreshingly honest about the split in it. Ordinary PDFs with a real text layer convert locally in the browser, free, without uploading file contents, capped at 50 MB or 500 pages. DOCX and HTML convert locally too. Scanned PDFs and images are a different animal: those go through cloud OCR that consumes credits, and the maker flat-out says complex tables, formulas, multi-column layouts, and embedded images may convert wrong and should be checked against the original. There's also an API and an MCP surface so the whole thing can be automated.
That honesty is the interesting signal, not the tool itself. The market keeps asking for a boring, reliable primitive: turn a document into clean Markdown so an agent or a human can work with it. And the maker drew a line down the middle of that primitive. One half is deterministic and trustworthy. The other half is probabilistic and needs a human to verify. If you're building your own version, the mistake is pretending that line doesn't exist.
The part that rebuilds cleanly
Text-layer extraction is a solved, deterministic problem. You open the PDF, pull the text objects that are already there, and shape them into Markdown. No model guessing, no accuracy caveat for the straightforward cases. This is exactly the kind of thing you can run Python online as a hosted endpoint, using the usual PDF parsing libraries, and get a stable result every time for documents that carry their own text.
What makes this worth building as an endpoint rather than a one-off script is the automation surface the original maker already gestured at. If you expose the conversion as an API endpoint with an in-platform tool call, a coding agent can hand it a file and get Markdown back mid-task, without a human in the loop. That's the shape a lot of current AI agent development is converging on: small, single-purpose tools an agent calls when it needs them, instead of one monolith that tries to do everything. Your converter becomes a callable capability. Store the source files and the converted output with file management, keep a job log or conversion history in SQLite, and you have a service an agent can lean on repeatedly.
A rough shape for the endpoint: accept an uploaded file, branch on whether a text layer is present, run the deterministic extraction path for the ones that have it, return Markdown plus a small metadata block saying which path was taken. That metadata matters more than it looks, and I'll come back to why.
The part you flag, not promise
Scanned documents and image-only PDFs have no text layer to extract. There's nothing deterministic to pull, so you're into OCR, and OCR on complex tables, math, and multi-column pages is where accuracy quietly falls apart. The original maker got this right by making cloud OCR an opt-in that costs credits and by telling people to check the output. That's the model to copy.
Here's the honest boundary, and I want to be precise about it: OCR and complex-table accuracy is unverified. Not "probably fine," not "good enough in practice" — unverified. I have no measured accuracy figures for any specific OCR path, and neither did the source. So don't design a flow that silently swallows a scanned page and returns Markdown as if it were ground truth. Design one that says, out loud, "this came from OCR, verify it."
Concretely, that's where the metadata block earns its place. When the extraction path is text-layer, mark the result high-confidence. When it's OCR, mark it unverified and surface that to whatever's downstream, whether that's a human reviewer or an agent deciding whether to trust the content. If you're calling a model for OCR, the Model Center APIs cover models already on the platform; anything beyond that list is outside the boundary and you shouldn't imply otherwise. The point isn't to make OCR perfect. It's to make the uncertainty visible so nobody builds on top of a guess thinking it's a fact.
Wiring it together without overbuilding
The smallest useful version is a Python backend behind an API endpoint, plus file management for inputs and outputs, plus a SQLite table tracking each conversion and its confidence flag. That's enough for an agent to call it as a tool and for you to see what's been processed. If you later want retrieval over the converted Markdown — say, answering questions across a stack of documents — a LanceDB knowledge base fits, but only feed it the text-layer output you trust, or clearly tag the OCR-derived chunks so the uncertainty travels with the data instead of getting laundered into a clean-looking answer.
If you want a human-facing side too, a small HTML front end for uploads and preview can be hosted and published alongside the endpoint. It's the same split as before: the browser page is convenience, the endpoint is the thing your automation actually calls. Keeping both under one project makes it straightforward to share or monetize later if the tool earns its keep. Plenty of the maker-built online tools in this space follow that same pattern — a public page for people, a callable surface for agents.
The discipline that makes this worth doing is the one the original maker modeled: know which half of your tool is deterministic and which half is a probability, build the deterministic half to be boring and reliable, and put a clear label on the probabilistic half rather than a promise. A converter that says "I'm sure about this text and unsure about that scan" is more useful than one that sounds confident about both and is quietly wrong on one.