API reference
Base URL https://api.ocrrouter.ai. Requests and responses are JSON. Send your key as a Bearer token.
POST/v1/ocr
Read a PDF or image and return Markdown or JSON. Waits for the result.
Body
modelstring- A model ID from GET /v1/models, or auto. Default auto.
file_urlstring- Public http(s) URL of the file. Send exactly one of file_url, file_base64, file_id.
file_base64string- The file as base64 (a data: URL prefix is accepted). Up to 20 MB.
file_idstring- ID returned by POST /v1/files.
filenamestring- Name shown in your activity log.
formatstring- markdown (default) or json.
pagesstring- Page range such as 1-5,8. Default all pages. PDF only.
fallbacksstring[]- Up to 5 model IDs to try, in order, if the first fails.
routestring- Used with model auto: quality (default), cheapest or fastest.
Errors
- 400 invalid_request, unknown_model, unsupported_file, unreadable_pdf, invalid_pages, invalid_file_url, file_fetch_failed
- 401 missing_api_key, invalid_api_key
- 402 insufficient_credits, key_limit_reached
- 413 file_too_large, too_many_pages
- 429 rate_limited
- 502 all_models_failed
- 503 model_unavailable
curl https://api.ocrrouter.ai/v1/ocr \
-H "Authorization: Bearer $OCRROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"mistral/mistral-ocr","file_url":"https://example.com/invoice.pdf","format":"json"}'{
"id": "req_8f2c1a41d0b3c7e9a2",
"model": "mistral/mistral-ocr",
"format": "json",
"attempts": [
{
"model": "mistral/mistral-ocr",
"ok": true,
"ms": 1180
}
],
"pages": [
{
"index": 1,
"width": null,
"height": null,
"blocks": [
{
"type": "heading",
"level": 1,
"text": "Invoice INV-2041",
"bbox": null,
"confidence": null
},
{
"type": "paragraph",
"text": "Acme Supply Co.\n14 Harbour Street, Sydney NSW 2000",
"bbox": null,
"confidence": null
},
{
"type": "table",
"rows": [
[
"Item",
"Qty",
"Unit price",
"Amount"
],
[
"A4 paper, 5 reams",
"4",
"$24.00",
"$96.00"
]
],
"markdown": "| Item | Qty | Unit price | Amount |\n|---|---|---|---|\n| A4 paper, 5 reams | 4 | $24.00 | $96.00 |",
"bbox": null,
"confidence": null
}
]
}
],
"usage": {
"pages": 1,
"credits": 6,
"latency_ms": 1180,
"cached": false
}
}POST/v1/files
Upload a file once and refer to it by ID for 24 hours. Add public=true to also get a public link to it. Send multipart/form-data with a file field.
Body
filefile, required- PDF, PNG, JPG, WebP or GIF, up to 20 MB. With public=true: any file type, up to 50 MB.
publicboolean- true returns a url anyone can open. PDFs, images, audio, video and plain text open in the browser; other types download.
expires_ininteger- With public=true: seconds until the link expires. Default 86400, at most 604800.
Errors
- 400 invalid_request, unsupported_file, empty_file
- 401 invalid_api_key
- 413 file_too_large
curl https://api.ocrrouter.ai/v1/files \
-H "Authorization: Bearer $OCRROUTER_API_KEY" \
-F "file=@report.pdf" \
-F "public=true"{
"id": "file_3b9c1e7a52d0f48e61",
"filename": "report.pdf",
"mime": "application/pdf",
"bytes": 482113,
"pages": 12,
"expires_at": "2026-11-13T09:00:00.000Z",
"url": "https://ocrrouter.ai/f/Jq3vX0aYb1dKc8mTn2pRzw/report.pdf"
}DELETE/v1/files/{id}
Delete an upload now. Its public link stops working immediately.
Errors
- 401 invalid_api_key
- 404 file_not_found
curl -X DELETE https://api.ocrrouter.ai/v1/files/file_3b9c1e7a52d0f48e61 \
-H "Authorization: Bearer $OCRROUTER_API_KEY"{
"id": "file_3b9c1e7a52d0f48e61",
"deleted": true
}GET/v1/requests/{id}
Fetch an earlier result again, in either format, without paying again.
Query
formatstring- markdown or json. Default: the format of the original request.
Errors
- 401 invalid_api_key
- 404 not_found
curl "https://api.ocrrouter.ai/v1/requests/req_8f2c1a41d0b3c7e9a2?format=markdown" \
-H "Authorization: Bearer $OCRROUTER_API_KEY"{
"id": "req_8f2c1a41d0b3c7e9a2",
"model": "mistral/mistral-ocr",
"format": "markdown",
"attempts": [
{
"model": "mistral/mistral-ocr",
"ok": true,
"ms": 1180
}
],
"markdown": "<!-- page:1 -->\n# Invoice INV-2041\n…",
"pages": [
{
"index": 1,
"markdown": "# Invoice INV-2041\n…"
}
],
"usage": {
"pages": 1,
"credits": 6,
"latency_ms": 1180,
"cached": false
}
}GET/v1/modelsNo key
List every model with its price and whether it can be called right now. No key needed.
curl https://api.ocrrouter.ai/v1/models{
"data": [
{
"id": "mistral/mistral-ocr",
"name": "Mistral OCR",
"provider": "Mistral",
"type": "OCR API",
"description": "Fast document OCR that returns clean Markdown with tables and embedded images.",
"available": true,
"credits_per_page": 6,
"inputs": [
"pdf",
"image"
],
"max_pages": 1000,
"supports": [
"Tables",
"Math",
"Bounding boxes",
"Multilingual"
]
}
]
}GET/v1/credits
Your credit balance and this key's usage against its limit.
Errors
- 401 invalid_api_key
curl https://api.ocrrouter.ai/v1/credits \
-H "Authorization: Bearer $OCRROUTER_API_KEY"{
"credits": 14280,
"key": {
"credits_used": 5120,
"credit_limit": 20000
}
}GET/v1/statsNo key
Measured success rate and speed per model from recent traffic. No key needed.
Query
hoursinteger- Window size, 1 to 720. Default 24.
curl "https://api.ocrrouter.ai/v1/stats?hours=24"{
"window_hours": 24,
"models": {
"mistral/mistral-ocr": {
"requests": 412,
"ok": 409,
"failed": 3,
"successRate": 0.9927,
"pages": 3120,
"medianMsPerPage": 940
}
}
}POST/v1/keys/temporaryNo key
Get a temporary key with 50 credits, without an account. One per IP address per day. Meant for agents and first tries.
Errors
- 429 temporary_key_limit
curl -X POST https://api.ocrrouter.ai/v1/keys/temporary{
"api_key": "ocr_tmp_5f0c…",
"credits": 50,
"note": "Temporary key with 50 credits. Sign up to keep going."
}Errors
Every error has the same shape: a short machine-readable code and a message you can show to a person. A 429 response includes a Retry-After header. When all models fail, the 502 body also lists each attempt, and you are not charged.
{
"error": {
"code": "insufficient_credits",
"message": "This request needs up to 72 credits and your balance is lower. Add credits or pick a cheaper model."
}
}