Skip to content

Text recognition (OCR)

maKI recognises text in images and PDF documents and returns it as Markdown, page by page. Behind it runs PaddleOCR-VL on Uni Mannheim’s GPU infrastructure; documents never leave the university network.

The endpoint follows the schema of the Mistral OCR API. It is not a chat endpoint: there is no prompt, no messages and no tokens. Document in, text out.

EndpointPOST https://maki.uni-mannheim.de/v1/ocr
Modelpaddleocr-vl
Access groupocr (select it when requesting a key)
InputPNG, JPEG or PDF as a data URL in the request body
OutputMarkdown per page

The image is passed Base64-encoded as a data URL in the document field:

Terminal window
MAKI_API_KEY="..."
IMAGE=$(base64 -i scan.png | tr -d '\n')
curl https://maki.uni-mannheim.de/v1/ocr \
-H "Authorization: Bearer ${MAKI_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"paddleocr-vl\",
\"document\": {
\"type\": \"image_url\",
\"image_url\": \"data:image/png;base64,${IMAGE}\"
}
}"

Response:

{
"object": "ocr",
"model": "paddleocr-vl",
"pages": [
{
"index": 0,
"markdown": "Invoice no. 2026-0815\n\nUniversität Mannheim, Schloss\n\nAmount: 1,234.56 EUR",
"images": [],
"dimensions": { "dpi": null, "height": null, "width": null }
}
],
"usage_info": { "pages_processed": 1 }
}

For PDFs the document type is document_url. Every page of the PDF becomes one entry in pages, in order, with index starting at 0:

Terminal window
PDF=$(base64 -i minutes.pdf | tr -d '\n')
curl https://maki.uni-mannheim.de/v1/ocr \
-H "Authorization: Bearer ${MAKI_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"paddleocr-vl\",
\"document\": {
\"type\": \"document_url\",
\"document_url\": \"data:application/pdf;base64,${PDF}\"
}
}"

The endpoint is not part of the OpenAI SDK; a plain HTTP call is enough:

import base64
import requests
MAKI_API_KEY = "..."
with open("minutes.pdf", "rb") as f:
data = base64.b64encode(f.read()).decode()
response = requests.post(
"https://maki.uni-mannheim.de/v1/ocr",
headers={"Authorization": f"Bearer {MAKI_API_KEY}"},
json={
"model": "paddleocr-vl",
"document": {
"type": "document_url",
"document_url": f"data:application/pdf;base64,{data}",
},
},
timeout=120,
)
response.raise_for_status()
for page in response.json()["pages"]:
print(f"--- page {page['index'] + 1} ---")
print(page["markdown"])

For images: "type": "image_url", "image_url": "data:image/png;base64,...".

  • Data URLs only. An https:// address as image_url or document_url is currently not fetched and rejected with HTTP 400. Download the document yourself and pass it Base64-encoded.
  • All pages. The pages field for page selection is still ignored, as is include_image_base64; images stays empty. The response always contains every page of the document.
  • Latency. One page takes about one to two seconds. Documents are processed in blocks of twelve pages; split very long PDFs beforehand, since a request is cut off after 75 seconds.
  • Size. Base64 inflates the file by a third. Scale images to a sensible resolution before sending (text clearly legible, roughly 150 to 300 dpi).
  • No prompt. To process the recognised text further (summarise, extract fields), send the Markdown to a chat model in a second step, see Structured output.