# OCR · document recognition — neuraldeep.tech API

> One section of the machine-readable reference. All sections: https://neuraldeep.tech/llms.txt · everything in one file: https://neuraldeep.tech/llms-full.txt

Base URL: `https://api.neuraldeep.tech/v1`
Auth: `Authorization: Bearer $YOUR_KEY`

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 when `page_ranges` is passed; without it, pages are counted after the document is parsed.
- `page_ranges` as a string: `1-5,8,10-12`.
- The engine checks the format itself: an unsupported file returns `415` or `422`.
- The `Idempotency-Key` header protects against double charging on retry. The same key returns the stored response with `idempotent_replay: true`, the same key with different parameters gives `422`, 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`.

```bash
# 1. upload (returns {"id":"job_...","page_count":N})
curl https://api.neuraldeep.tech/v1/ocr/extract \
  -H "Authorization: Bearer $YOUR_KEY" \
  -F "file=@invoice.pdf"
# (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"
```

```python
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.
