Quickstart
Your first parse, in five minutes
The HTTP API is the canonical interface — no SDK, no setup beyond an API key. Below: get a key, POST a PDF, read the Markdown and the routing trace back.
Get an API key
Sign up at docira.io/signup — no credit card required. Every account starts on the free tier: 25 pages/day. Once you have a key, export it:
export DOCIRA_API_KEY="docira_live_sk_..."Send the key on every request as the X-API-Key header. Keys are scoped to your account and can be rotated without downtime from Settings → API Keys.
Make your first parse
Two entry points: POST /v1/parse/upload takes a multipart file; POST /v1/parse takes a publicly reachable URL and fetches the document for you.
File upload
curl -X POST https://api.docira.io/v1/parse/upload \
-H "X-API-Key: $DOCIRA_API_KEY" \
-F "file=@report.pdf" \
-F "operation_mode=ocr"import httpx, os
with open("report.pdf", "rb") as f:
r = httpx.post(
"https://api.docira.io/v1/parse/upload",
headers={"X-API-Key": os.environ["DOCIRA_API_KEY"]},
files={"file": ("report.pdf", f, "application/pdf")},
data={"operation_mode": "ocr"},
timeout=120.0,
)
r.raise_for_status()
page = r.json()["pages"][0]
print(page["content_markdown"])
print(f"Tier: {page['tier_used']} | Provider: {page['provider']} | Model: {page['model']}")import { readFileSync } from "fs";
const fd = new FormData();
fd.append("file", new Blob([readFileSync("report.pdf")]), "report.pdf");
fd.append("operation_mode", "ocr");
const res = await fetch("https://api.docira.io/v1/parse/upload", {
method: "POST",
headers: { "X-API-Key": process.env.DOCIRA_API_KEY },
body: fd,
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
const page = data.pages[0];
console.log(page.content_markdown);
console.log(`Tier: ${page.tier_used} | Provider: ${page.provider}`);URL fetch
curl -X POST https://api.docira.io/v1/parse \
-H "X-API-Key: $DOCIRA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"file_url": "https://arxiv.org/pdf/1706.03762",
"operation_mode": "ocr"
}'import httpx, os
r = httpx.post(
"https://api.docira.io/v1/parse",
headers={"X-API-Key": os.environ["DOCIRA_API_KEY"]},
json={
"file_url": "https://arxiv.org/pdf/1706.03762",
"operation_mode": "ocr",
},
timeout=120.0,
)
r.raise_for_status()
print(r.json()["pages"][0]["content_markdown"])const res = await fetch("https://api.docira.io/v1/parse", {
method: "POST",
headers: {
"X-API-Key": process.env.DOCIRA_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
file_url: "https://arxiv.org/pdf/1706.03762",
operation_mode: "ocr",
}),
});
const data = await res.json();
console.log(data.pages[0].content_markdown);The URL must be publicly reachable over HTTPS and respond with a supported content-type (PDF, PNG, JPEG, TIFF, DOCX, PPTX, XLSX). Private IPs are rejected.
Read the routing trace
Each entry in pages[] includes the full routing decision. You never have to guess which model handled a page.
{
"id": "req_01abc...",
"status": "completed",
"pages": [
{
"page_number": 1,
"content_markdown": "# Attention Is All You Need\n\n...",
"tier_used": "pro",
"provider": "anthropic",
"model": "claude-sonnet-4.5",
"confidence": {
"layout_score": 0.94,
"ocr_score": 0.91,
"verbatim_score": 0.92,
"mean_grade": "good"
},
"tokens": { "input_tokens": 1240, "output_tokens": 380 },
"latency_ms": 2840,
"re_routed": false
}
],
"usage": {
"estimated_cost_usd": 0.0061,
"pages_by_tier": { "pro": 1 }
}
}The router picked tier_used, provider, and model automatically based on the page's complexity score. See Agentic routing for the full decision logic.
Use an SDK (or skip it)
First-party Python and Node SDKs ship Q3 2026. Until then, the HTTP API is the full interface — any HTTP client works. See SDKs and HTTP recipes for complete copy-paste patterns including error handling, retries, and batch submission.
When you hit limits
| Limit | Free | Pro | Scale |
|---|---|---|---|
| Pages / day | 100 | 5,000 | 100,000 |
| Req / min | 10 | 60 | custom |
| Max file size | 50 MB on all tiers | ||
| Batch | — | 100 docs | 100 docs |
A 429 response includes a Retry-After header in seconds. Upgrade on the pricing page.