Five different places document PDF4me's OCR quality setting: the REST API and four no-code platforms. Read all five pages back to back and you'll find they're not even using the same two words for it.
What the quality setting is actually deciding
A scanned page, or a PDF made from a photo of a document, is just an image. There's no text underneath it for a computer to read, search, or copy. OCR is the step that looks at each page image, works out what characters are on it, and writes that back into the file as real, selectable text.
The quality setting decides how hard that recognition pass works. A born-digital PDF that already has most of its text as a real text layer only needs a light, single pass to catch anything missing. A fully scanned or photographed document needs every page individually recognized, since none of it is real text to begin with. Pick the light option on a scan and you get an empty or garbled result. Pick the heavy option on a file that's already text and it runs the recognition anyway, on pages that didn't need it.
On PDF4me's own REST API, this is a required field in the request body: POST /api/v2/ConvertOcrPdf with qualityType set to the literal string "Draft" or "High". Draft is a fast single pass suited to normal PDFs that mostly already have a text layer. High is full per-page recognition, built for scanned or image-based documents. Pair it with ocrWhenNeeded (also a string, "true" or "false") to skip any page that's already searchable instead of reprocessing it, and language when the recognized text comes back garbled.
Five surfaces, two different vocabularies
Here's where it gets genuinely confusing, and it's the actual reason this parameter gets misconfigured more often than it should: PDF4me's own Power Automate PDF OCR action and n8n's Convert PDF to Editable PDF Using OCR node both use the exact same words as the REST API: Quality Type, set to Draft or High. Power Automate's docs even note the default is Draft if you don't specify one.
But Zapier's PDF OCR action and Make's PDF OCR module, built on the exact same underlying feature, both call the same choice Standard or Expert instead. Standard for normal PDFs, Expert for scanned or photographed documents. Same decision, same two options, different pair of words, on two of the five surfaces that expose it.
| Surface | Parameter name | Values | Docs page |
|---|---|---|---|
| REST API | qualityType |
Draft / High | ConvertOcrPdf |
| Power Automate | Quality Type | Draft / High (default: Draft) | PDF OCR action |
| n8n | Quality Type | Draft / High (response schema also lists "Archival") | Convert PDF to Editable PDF Using OCR |
| Zapier | Quality Type | Standard / Expert | PDF OCR - Searchable Document |
| Make | Quality Type | Standard / Expert | PDF OCR module |
So if you've automated this feature on more than one platform, there's a real chance you've been reading two completely different vocabularies for the same setting without realizing they map onto each other. A team that builds the Power Automate flow and hands the Zapier version to someone else, or vice versa, can easily lose that connection entirely.
There's a third wrinkle worth knowing about if you're on n8n specifically: its own documented output schema lists the possible values that come back in the response as "Draft", "High", and Archival, even though the parameter description itself only mentions Draft and High as the choices you can set. Whether Archival is a real third quality tier or just a stray value from a shared internal schema isn't something the parameter table itself explains.
The other setting worth knowing about: OCR Only When Needed
Every one of these five surfaces also exposes a second, related toggle: ocrWhenNeeded on the REST API, OCR Only When Needed on Power Automate and n8n. Set it on and the engine checks each page before processing, skipping any page that already has selectable text and only running recognition on the pages that are actually images. This matters most on hybrid documents: a contract that was born digital, printed, signed by hand, and rescanned. Most of that file is still real text. Only the signature page, or a handwritten margin note, became image data. Turning this on means you don't have to choose one setting for the whole document, the engine makes that call per page.
The language parameter isn't formatted the same way twice either
If the recognized text comes back garbled, every one of these five surfaces lets you tell the engine what language to expect. What they don't agree on is the format. The REST API's own sample payload and n8n's parameter example both use the full language name, "English". Power Automate's example uses a two-letter code, en. Make's parameter table lists three-letter codes: eng, deu, fra, spa, ita, por. Copy a value from one platform's documentation into another platform's field and there's a real chance it silently fails to match, or falls back to auto-detection instead of doing what you asked. Always check the example value on the specific page you're building against, not the platform you happen to remember from last time.
Calling it directly: a live-verified request
Here's the exact request shape, straight from PDF4me's own docs page for ConvertOcrPdf, adapted into Python with requests:
import base64
import requests
API_KEY = "your-pdf4me-api-key"
URL = "https://api.pdf4me.com/api/v2/ConvertOcrPdf"
with open("scanned-contract.pdf", "rb") as f:
doc_content = base64.b64encode(f.read()).decode("utf-8")
payload = {
"docContent": doc_content,
"docName": "scanned-contract.pdf",
"qualityType": "High",
"ocrWhenNeeded": "true",
"language": "English",
"outputFormat": "true",
"isAsync": True,
}
headers = {
"Content-Type": "application/json",
"Authorization": f"Basic {API_KEY}",
}
response = requests.post(URL, json=payload, headers=headers)
if response.status_code == 200:
result = response.json()
with open("searchable.pdf", "wb") as out:
out.write(base64.b64decode(result["docContent"]))
elif response.status_code == 202:
# Large scan: poll the Location URL with the same Authorization header
poll_url = response.headers["Location"]
print(f"Processing async, poll: {poll_url}")
A few things worth calling out about this payload, all live-verified against the current docs page rather than assumed: ocrWhenNeeded and outputFormat are sent as the strings "true"/"false", not JSON booleans, while isAsync is a real boolean. Mixing those two types up is a documented, common cause of 400 errors. outputFormat is required, but the docs page itself doesn't explain what it controls beyond noting it's sent as "true" in the official samples, worth flagging rather than guessing at. The official samples also include a mergeAllSheets boolean field on this endpoint, whose purpose isn't clearly documented for a PDF-in, PDF-out OCR action either, exactly the kind of parameter that's easy to skip past without reading.
For Python, C#, Java, JavaScript, and Salesforce reference implementations, PDF4me publishes official samples alongside the docs page itself.
When to reach for the heavier setting even on a file that looks fine
The trap isn't obviously scanned documents, most people get those right by instinct. It's the hybrid case above: a file that looks like a normal PDF at a glance but has had part of its content replaced by a scanned or photographed page at some point. If a document has passed through a printer, a scanner, a fax machine, or a phone camera at any point in its life, even once, treat it as a High (or Expert) candidate. If it has only ever existed as a digital file, the lighter setting gives you the same result while skipping the recognition step entirely. When your pipeline handles a mixed batch of both, defaulting to the heavier setting is the safer call, since running it on a file that doesn't need it doesn't change the outcome, it just also performs the recognition pass on a file that didn't need it.
A checklist worth keeping next to your workflow
Before wiring up OCR in any of these five places, it's worth asking one question: has this file, or any part of it, ever touched a printer, a scanner, a fax machine, or a camera? If the answer is yes, or even maybe, reach for the heavier quality setting, whichever pair of words your platform happens to use for it. Turn on the skip-already-searchable-pages toggle so the engine isn't reprocessing text that's already there. And if the output looks garbled afterward, check the language parameter, and double-check the exact format that specific platform's own docs page expects, before assuming the OCR itself failed.
Whether you're calling the REST API directly, or building on Make, Power Automate, Zapier, or n8n, you can also test the REST endpoint interactively, with a real file, through the API Tester before wiring it into anything.
Website: pdf4me.com
Documentation: docs.pdf4me.com
Developer portal: dev.pdf4me.com
Top comments (0)