Open in the interactive docs · markdown for agents: https://neuraldeep.tech/docs/ocr.md
OCR · document recognition
With the same key — OCR for PDFs and images (PNG/JPG/WEBP/BMP/TIFF). Endpoints under /v1/ocr/*. Available on all plans, with a bucket separate from chat — the limit is counted in pages.
Works asynchronously: upload a document → get a job → poll the status (no more than once per second) → fetch the result as markdown/json/text. For coordinate-based markup there's a PNG preview of the page (same coordinate system as bbox). There is one profile, fast: the former pro is retired, a request with it silently runs as fast. Remaining pages: GET /v1/ocr/quota or GET /v1/ocr/balance. When pages run out you get 429 with a quota_exceeded body and Retry-After.
Input limits.
- File up to 50 MB, otherwise
413. Empty file:400. - Up to 500 pages per request, otherwise
413. This is checked up front only whenpage_rangesis passed; without it, pages are counted after the document is parsed. page_rangesas a string:1-5,8,10-12.- The engine checks the format itself: an unsupported file returns
415or422. - The
Idempotency-Keyheader protects against double charging on retry. The same key returns the stored response withidempotent_replay: true, the same key with different parameters gives422, and while the first request is still running,409. - Someone else's or a missing job:
404. An empty wallet on a key in Wallet mode:402.
# 1. upload (returns {"id":"job_...","page_count":N})
curl https://api.neuraldeep.tech/v1/ocr/extract \
-H "Authorization: Bearer $YOUR_KEY" \
-F "[email protected]"
# (page range: -F 'page_ranges=1-5,8')
# 2. job status
curl https://api.neuraldeep.tech/v1/ocr/jobs/job_123 \
-H "Authorization: Bearer $YOUR_KEY"
# 3. result as markdown
curl "https://api.neuraldeep.tech/v1/ocr/jobs/job_123/result?format=markdown" \
-H "Authorization: Bearer $YOUR_KEY"
import time, httpx
H = {"Authorization": "Bearer $YOUR_KEY"}
# 1. upload
with open("invoice.pdf", "rb") as f:
job = httpx.post(
"https://api.neuraldeep.tech/v1/ocr/extract",
headers=H, files={"file": f},
).json()
jid = job["id"]
print("pages:", job["page_count"], "charged:", job["scan_pages_charged"])
# 2. polling (once per second)
while True:
st = httpx.get(f"https://api.neuraldeep.tech/v1/ocr/jobs/{jid}", headers=H).json()
if st["status"] == "completed":
break
time.sleep(1)
# 3. result
res = httpx.get(
f"https://api.neuraldeep.tech/v1/ocr/jobs/{jid}/result",
params={"format": "markdown"}, headers=H,
).json()
print(res["content"])
Status, result and preview don't consume the limit; you pay only for pages at upload.
Reference sections (markdown for agents)
- Start · key, errors, quotas
- Text · chat
- Vectorization
- Reranking
- Transcription
- Image recognition
- Structured output
- Clients · agents
- Remaining limits · Limits API
- Search · Search API
- OCR · documents
- Images · Image API
- Music · Music API
- PII anonymization · PII Guard
- SpeechCore · STT
- Speech synthesis · TTS API
- Who spoke when · diarization
- Text decisions · FRIDA-Decisions, clef-flash
- Drift · overview
- Files + sandbox preview
- Your own tools, skills, MCP
- Tasks · proactive
- Memory · memory
- Isolation and security
- Agent settings
- Limits · errors
- Book · search and MCP
- Streaming
- SDK · Python / JS
- Privacy