Skip to main content
POST

Overview

The v3 endpoint parses a PDF (or archive of PDFs) and returns markdown text for each page. Compared to v1/v2 it is intentionally simpler: no layout / OCR-engine / segment-analysis knobs, no segment tree in the response. You submit a PDF, you get markdown back. The pipeline picks the best model per page internally. The endpoint is async: every submission returns a job_id you poll until the job reaches a terminal state. Endpoint base URL: https://prod.visionapi.unsiloed.ai/v3/parse
Use this endpoint when you want clean markdown out of a PDF without configuring layout or OCR settings. For fine-grained control over segment types, bounding boxes, and per-segment processing, use the v2 Parse Document endpoint instead.
The v3 surface has four routes:

Authentication

Every request requires an X-API-Key header. Keys are personal, rate-limited per key (100 requests/day, 2 RPS), and isolated — you can only see your own jobs.
v3 API keys are issued on request — they are separate from v1/v2 keys. To get one, email aman@unsiloed.ai (or open an issue at github.com/Unsiloed-AI/unsiloed-olmocr-benchmark) with a one-line note about what you’re evaluating. Typical turnaround is same-day.

Guarantees


POST /v3/parse — Submit a single PDF

POST /v3/parse accepts three body shapes (auto-detected from the Content-Type header). All three submit the same async job and return the same response.

Body shape 1 — Inline multipart upload

For small PDFs (up to ~3 MB raw). Single HTTP call.
file
required
PDF binary, sent as multipart/form-data. Capped at ~3 MB raw (≈ 4 MB after base64 encoding inside API Gateway). For larger files use body shape 2 or 3.
string
Optional query parameter on the request URL. Restrict OCR to a subset of pages.
  • "1-5": pages 1 through 5
  • "1,3,5": specific pages
  • omitted: all pages

Body shape 2 — JSON with caller-hosted URL

For PDFs up to 50 MB that you already host (S3 public-read, S3 presigned, GitHub release asset, your own web server, etc.). Single HTTP call.
string
required
Publicly fetchable https:// URL or s3://bucket/key reference to the PDF. We fetch it. URLs pointing at private IPs, link-local, or AWS instance metadata are rejected by an SSRF guard.

Body shape 3 — JSON with file_id from a presigned upload

For PDFs up to 50 MB that you do not want to host publicly. First call POST /v3/parse/upload (below) to get a presigned upload_url and file_id; PUT your PDF to the URL; then submit the parse using the file_id.
string
required
The file_id returned by POST /v3/parse/upload after you finish the PUT. Acts as the job_id for subsequent polling.
You must use the same API key that minted the file_id via POST /v3/parse/upload. Cross-key submissions return 404 (hiding existence) — this is how per-key isolation is enforced.

Response (any body shape)

string
required
Job identifier (32-character UUID hex). Pass to GET /v3/parse/{job_id} to poll. When you used body shape 3, this equals the file_id you submitted.
string
required
Always "queued" on submission. Subsequent values: "running""done" or "failed".
string
required
ISO 8601 timestamp when the job was created.

POST /v3/parse/upload — Presigned upload URL

Returns a presigned S3 PUT URL so you can upload a PDF directly (bypassing the API Gateway request size cap). Use this for the 3-call flow of body shape 3 above. No request body required — just an empty POST with the auth header.

Response

string
required
Opaque identifier. After you PUT the PDF to upload_url, pass this back as {"file_id": "..."} to POST /v3/parse to start parsing.
string
required
Presigned S3 PUT URL. 1-hour expiry from issuance. Send the PDF body directly to this URL with HTTP method PUT and Content-Type: application/pdf. The transfer bypasses our API Gateway entirely.
string
required
Always "PUT".
string
required
Always "application/pdf". Your PUT must set the same Content-Type header.
integer
required
Maximum PDF size accepted by the pipeline after upload. Currently 52428800 (50 MB).
integer
required
Seconds until the upload_url expires (3600).

Full 3-call flow


POST /v3/parse/batch — Archive of PDFs

Process many PDFs in one job. You host an archive of PDFs; we fetch it and process every PDF inside.
string
required
Public https:// URL or s3:// reference to a .tar, .tar.gz/.tgz, or .zip archive of PDFs. Archive format is auto-detected by content sniffing the first bytes, not by file extension. Non-PDF files inside the archive are skipped silently.
Submission response is the same shape as POST /v3/parse:
The completion response uses documents[] instead of pages[] (one entry per PDF in the archive) — see “Polling” below.

GET /v3/parse/ — Poll status + retrieve result

Query parameters

string
When set to "markdown" and status is "done", returns concatenated page markdown as Content-Type: text/markdown; charset=utf-8 instead of a JSON envelope. Useful for curl ... | tee out.md. Ignored while the job is queued/running/failed.

Response — while running

Response — single-PDF done

string
required
"done" for a completed single-PDF job.
integer
required
Number of pages in the PDF (after applying the pages selector, if any).
array
required
Per-page markdown. Each entry has page (1-indexed integer) and markdown (string). Page order is ascending.

Response — batch done

array
required
One entry per PDF found in the archive. Each entry has pdf (relative path inside the archive), page_count, and pages[] (same shape as single-PDF). If a particular PDF failed, the entry has an error field instead of pages.
If the JSON would exceed API Gateway’s 10 MB response cap, the response is { "job_id", "status": "done", "result_url" } instead — fetch result_url (presigned S3 GET) to download the same JSON. The schema of the downloaded JSON is identical to the inline shape, so clients can use one code path for both.

Response — failed

Polling example


Error responses

Code examples

See also

  • Open-source benchmark harness + client — reproduces our published olmOCR-Bench numbers across vendors and includes a thin client (clients/bench_via_api.py) that calls this endpoint, collects the returned markdown, and scores it with the unmodified upstream scorer.
  • v1 Parse Document — segmented response with bounding boxes, OCR data, and per-segment processing knobs.
  • v2 Parse Document (Presigned Upload) — segmented response variant with presigned upload for larger files and higher throughput.

Authorizations

X-API-Key
string
header
required

Personal API key. Issued separately from v1/v2 keys.

Query Parameters

pages
string

Optional page selector. Examples: 1-5, 1,3,5. Omitted means all pages.

Body

Body shape 1 — multipart inline upload for small PDFs (≤ ~3 MB raw).

file
file
required

PDF binary. Capped at ~3 MB raw.

Response

Job accepted and queued

Async job acknowledgment.

job_id
string
required

32-character UUID hex. Pass to GET /v3/parse/{job_id} to poll.

status
enum<string>
required

Always queued on submission.

Available options:
queued
created_at
string
required

ISO 8601 timestamp when the job was created.