PDF to Markdown API
The MarkdFlow conversion API takes a document — as a base64 payload, a public URL, or an already-uploaded file URL — and returns structured Markdown plus per-block confidence scores. One credit is charged per processed page, and failed conversions cost nothing.
Updated
Endpoint
POST https://markdflow.org/api/convert
Content-Type: application/json
Authorization: Bearer mf_live_YOUR_KEY
{
"fileName": "quarterly-report.pdf",
"mimeType": "application/pdf",
"sourceType": "pdf",
"fileData": "data:application/pdf;base64,JVBERi0xLjQK...",
"pageCount": 12
}At least one source field must be provided: fileData (inline base64 data URL), rawText (plain text), documentUrl (public HTTPS URL) or fileUrl (a file already uploaded to our storage).
Authentication
Every request needs one of two credentials:
- API key (recommended for scripts) — send
Authorization: Bearer mf_live_.... Create keys in your profile under API Keys: name them, copy the key once, revoke any time. Up to 5 active keys per account; email verification required. - Session cookie — works for browser extensions and tools that already run inside your signed-in session.
Keys are shown once: The full key is displayed only at creation time and we store only its SHA-256 hash, so a database leak can never reveal it. If you lose the key, revoke it and create a new one.
Request fields
| Field | Type | Description |
|---|---|---|
| fileName | string | Original file name. Used to infer the source type from the extension. |
| fileSize | number | Size in bytes. |
| mimeType | string | MIME type of the source. |
| sourceType | string | One of image | pdf | text | document. Inferred from fileName when omitted. |
| fileData | string | Inline base64 data URL of the document. |
| rawText | string | Plain text content for text and source files. |
| documentUrl | string | Public HTTPS URL to fetch. Subject to SSRF checks. |
| fileUrl | string | URL of a file already uploaded through the upload endpoint. |
| pageCount | number | Known page count, used for the pre-flight credit check. |
Examples
curl -X POST https://markdflow.org/api/convert \
-H "Content-Type: application/json" \
-H "Authorization: Bearer mf_live_YOUR_KEY" \
-d '{
"fileName": "invoice.pdf",
"mimeType": "application/pdf",
"fileData": "data:application/pdf;base64,'"$(base64 -i invoice.pdf)"'"
}'import base64, requests
API_KEY = "mf_live_YOUR_KEY"
def to_markdown(path: str) -> dict:
with open(path, "rb") as fh:
data_url = "data:application/pdf;base64," + base64.b64encode(fh.read()).decode()
res = requests.post(
"https://markdflow.org/api/convert",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}",
},
json={"fileName": path.split("/")[-1], "mimeType": "application/pdf", "fileData": data_url},
timeout=120,
)
res.raise_for_status()
return res.json()
result = to_markdown("quarterly-report.pdf")
print(result["markdownText"])
print("blocks:", result["blocksCount"], "confidence:", result["confidence"])import fs from "node:fs/promises";
const API_KEY = "mf_live_YOUR_KEY";
const buf = await fs.readFile("paper.pdf");
const res = await fetch("https://markdflow.org/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`,
},
body: JSON.stringify({
fileName: "paper.pdf",
mimeType: "application/pdf",
fileData: "data:application/pdf;base64," + buf.toString("base64"),
}),
});
if (!res.ok) {
const { error } = await res.json();
throw new Error(error);
}
const { markdownText, blocks, confidence } = await res.json();Response
On success you get the Markdown plus structural metadata:
| Field | Description |
|---|---|
| markdownText | The converted Markdown |
| blocks | Per-block array: type, readingOrder, confidence, content |
| blocksCount | Counts by type: headers, paragraphs, tables, equations, lists |
| confidence | Overall confidence for the document |
| detectedLanguage | Detected language code |
| wordCount / charCount | Size of the output |
| pagesProcessed | Pages actually processed — this is what you are charged for |
Error codes
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_json | unsupported_source_type | document_required | Malformed body or no usable source |
| 401 | unauthorized | No valid session |
| 402 | points_insufficient | Not enough credits for the estimated pages |
| 413 | url_too_large | Remote document exceeds 50 MB |
| 415 | unsupported_url_format | URL points at an unsupported type |
| 422 | invalid_url | url_blocked | url_unreachable | URL failed validation or could not be fetched |
| 429 | rate_limited | Too many requests (30/hour per IP, 60/hour per user) |
| 503 | mistral_not_configured | conversion_failed | Upstream OCR failure — no credits charged |
Billing on failure: Credits are pre-checked but only deducted after a successful conversion, based on the pages actually processed. Failed, mock and unconfigured conversions cost nothing.
Limits and pricing
- 1 credit = 1 processed page.
- Max file size: 10 MB free tier, 20 MB trial, 50 MB Pro and Annual.
- Rate limits: 30 requests per hour per IP, 60 per hour per user (session and API-key requests share the user limit).
- Up to 5 active API keys per account; keys are revocable at any time.
- Remote URLs are fetched with SSRF protection; private and metadata addresses are blocked.
Frequently asked questions
How much does an API conversion cost?
One credit per processed page. Failed conversions are not charged.
Can I send a URL instead of a file?
Yes — documentUrl accepts a public HTTPS URL up to 50 MB. Private, localhost and cloud metadata addresses are blocked.
Do you return table structure?
Yes. Tables are returned as Markdown tables inside markdownText, and are counted in blocksCount.tables so you can assert on them.
Are there long-lived API keys?
Yes. Create keys in your profile under API Keys (email verification required, up to 5 active keys). The key is shown once and only its hash is stored, and you can revoke it any time.
What are the rate limits?
30 requests per hour per IP and 60 per hour per user. Exceeding them returns 429 rate_limited.
Related guides
- LLM Document Parsing: From Raw Files to a RAG-Ready CorpusA practical guide to LLM document parsing: the ingest-parse-structure-chunk-embed pipeline, why Markdown beats…
- The Best PDF to Markdown Converter for AI PipelinesWhat matters when you convert PDFs for LLMs: heading structure, table fidelity, LaTeX formulas, token efficien…
- PDF to Markdown ConverterConvert PDF files to clean Markdown in seconds. Headings, tables and formulas preserved, per-block confidence …
- MarkItDown Alternative for AI-Ready MarkdownMarkItDown is a great local converter. If you need OCR for scans, table fidelity, per-block confidence and no …
Wire document conversion into your pipeline
One endpoint, per-page pricing, per-block confidence. Start with 30 free credits.