Quickstart
Create a key in the dashboard, then send it a document.
curl -X POST https://quirelabs.com/api/folio/v1/convert \
-H "Authorization: Bearer $FOLIO_KEY" \
-H "x-filename: report.docx" \
--data-binary @report.docx
{
"markdown": "# Quarterly report\n\nRevenue grew across every region…",
"format": "docx",
"bytes": 24576,
"durationMs": 4.2,
"usage": { "documents": 1, "ocrPages": 0, "used": 118, "included": 10000 }
}
The filename is a hint, not a requirement. Formats are detected from the content
signature first, so a .xlsx that is really a .docx converts as what it
actually is. Only CSV has no signature to find, which is the one case where the
extension decides.
A PDF with scans in it
Nothing changes about the request. The response gains a pages breakdown.
curl -X POST https://quirelabs.com/api/folio/v1/convert \
-H "Authorization: Bearer $FOLIO_KEY" \
-H "x-filename: contract.pdf" \
--data-binary @contract.pdf
{
"markdown": "Master services agreement…\n\n# Schedule 4: Termination…",
"format": "pdf",
"durationMs": 936.6,
"pages": { "total": 3, "text": 2, "ocr": 1, "ocrPages": [2] },
"usage": { "documents": 1, "ocrPages": 1, "used": 119, "included": 10000 }
}
Two pages were read from their own text and cost nothing. Page 2 was a scan and
went to OCR. ocrPages names it, so the charge is checkable against the
document rather than something to take on trust.
Node
import { readFile } from 'node:fs/promises';
const response = await fetch('https://quirelabs.com/api/folio/v1/convert', {
method: 'POST',
headers: {
authorization: `Bearer ${process.env.FOLIO_KEY}`,
'x-filename': 'contract.pdf',
},
body: await readFile('contract.pdf'),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.code}: ${error.message}`);
}
const { markdown, pages } = await response.json();
Python
import os, requests
with open("contract.pdf", "rb") as document:
response = requests.post(
"https://quirelabs.com/api/folio/v1/convert",
headers={
"Authorization": f"Bearer {os.environ['FOLIO_KEY']}",
"x-filename": "contract.pdf",
},
data=document,
)
response.raise_for_status()
markdown = response.json()["markdown"]
Try it without a key first
The playground runs the same conversion in your browser. Nothing is uploaded, and it will tell you how many pages of your own document would need OCR before you decide anything.