Pick a converter — every tool exports a clean Excel file
EU servers, 30-min auto-delete, DPA on request. Built for European businesses.
A simple REST API to turn PDFs and images into clean, structured Excel. Authenticate with one header, send a file, get a spreadsheet back.
The myocr.app API converts document files (PDF, JPG, PNG) into structured Excel, CSV, text or JSON. You send a file and a model name; we run OCR and layout analysis and return a clean result.
Every request is authenticated with an API key passed in the X-API-Key header. Responses use a predictable JSON envelope and every call returns a request_id you can use for support and debugging.
Use the synchronous endpoint for small files you need answered immediately, and the asynchronous jobs endpoint (with optional webhook) for larger files or high volume.
Authenticate every request with the X-API-Key header. Create and manage keys from your dashboard at /account/api. A verified payment card is required to issue a key (anti-abuse).
Two key types exist: test keys (prefix sk_test_) run against the same pipeline without consuming paid quota where applicable, and live keys (prefix sk_live_) for production. Keep keys secret and server-side — never embed them in client-side code.
Key management endpoints (/v1/keys) use your logged-in web session, not the API key itself.
curl https://api.myocr.app/v1/status \ -H "X-API-Key: sk_live_xxxxxxxxxxxx"
from myocr_client import MyOCRClient client = MyOCRClient(api_key="sk_live_xxxxxxxxxxxx") print(client.status())
const res = await fetch("https://api.myocr.app/v1/status", { headers: { "X-API-Key": "sk_live_xxxxxxxxxxxx" } }); console.log(await res.json());
Convert your first document in under a minute. Get a key from the dashboard, then send a multipart request with your file and the model you want.
The example below converts any PDF or image with tables into an .xlsx spreadsheet and saves it to out.xlsx.
curl -X POST https://api.myocr.app/v1/convert \ -H "X-API-Key: sk_live_xxxxxxxxxxxx" \ -F "file=@invoice.pdf" \ -F "model=tables" \ -o out.xlsx
from myocr_client import MyOCRClient client = MyOCRClient(api_key="sk_live_xxxxxxxxxxxx") result = client.convert("invoice.pdf", model="tables") result.save("out.xlsx")
import fs from "node:fs"; const form = new FormData(); form.append("file", new Blob([fs.readFileSync("invoice.pdf")]), "invoice.pdf"); form.append("model", "tables"); const res = await fetch("https://api.myocr.app/v1/convert", { method: "POST", headers: { "X-API-Key": "sk_live_xxxxxxxxxxxx" }, body: form, }); fs.writeFileSync("out.xlsx", Buffer.from(await res.arrayBuffer()));
POST /v1/convert accepts a single file (max 5 MB, max 10 pages) and returns the result file directly in the response body — an .xlsx by default, or text/JSON/CSV if you set the output parameter.
This endpoint is best when you need the answer immediately. For larger files or batches, use async jobs instead.
file
model
output
For files up to 50 MB (and PDFs up to 500 pages) or higher throughput, create a job with POST /v1/jobs. The call returns a request_id immediately; the file is processed in the background. PDFs above the page cap are rejected upfront with TOO_MANY_PAGES — split the document.
Poll GET /v1/jobs/{request_id} for status (pending → processing → done/failed), then download the result from GET /v1/jobs/{request_id}/result. Provide a webhook_url to be notified automatically when the job finishes, instead of polling.
webhook_url
# 1. create the job curl -X POST https://api.myocr.app/v1/jobs \ -H "X-API-Key: sk_live_xxxxxxxxxxxx" \ -F "file=@statement.pdf" -F "model=bank_statement" # → {"success": true, "data": {"request_id": "abcd1234"}} # 2. poll status, then download the result curl https://api.myocr.app/v1/jobs/abcd1234 -H "X-API-Key: sk_live_xxxxxxxxxxxx" curl https://api.myocr.app/v1/jobs/abcd1234/result -H "X-API-Key: sk_live_xxxxxxxxxxxx" -o out.xlsx
job = client.create_job("statement.pdf", model="bank_statement") job.wait() # polls with backoff until done job.result().save("out.xlsx")
POST /v1/batch accepts 1–20 files in a single multipart request, all processed with the same model. Each file is reported independently; per-file failures are returned in an errors array without failing the whole batch.
curl -X POST https://api.myocr.app/v1/batch \ -H "X-API-Key: sk_live_xxxxxxxxxxxx" \ -F "files=@a.pdf" -F "files=@b.pdf" -F "files=@c.jpg" \ -F "model=invoice"
Pass one of these model values. tables and text run on our OCR engine; the specialized models return domain-specific fields.
tables
text
invoice
receipt
bank_statement
business_card
Set the output parameter to choose the response format: xlsx (default, structured spreadsheet), txt (plain text), json (extracted fields as JSON) or csv. The text model always returns txt.
For model=bank_statement you can also set output to csv_quickbooks (4-column bank import CSV), csv_xero (Xero import template) or ofx (standard OFX file for most accounting software). With output=json the response also includes a reconciliation object: opening/closing balances, total credits and debits, the computed difference and ok=true when the extracted transactions match the statement totals.
JSON responses follow a fixed envelope: a success boolean, a data object (or an error object), and a request_id. File responses return the binary directly with the appropriate Content-Type.
Every response includes the X-MyOCR-Request-Id header. File responses also include X-MyOCR-Pages-Used (pages billed) and X-MyOCR-Model (the model used).
{ "success": true, "data": { "request_id": "abcd1234" }, "request_id": "abcd1234" }
Errors return success: false with an error.code and human-readable error.message, plus the request_id. Use the code (stable) for branching, the message (may change) for humans.
MISSING_API_KEY
INVALID_API_KEY
UNSUPPORTED_MODEL
UNSUPPORTED_FILE_TYPE
MISSING_FILE
FILE_TOO_LARGE
TOO_MANY_PAGES
INVALID_WEBHOOK_URL
INSUFFICIENT_PAGES
QUOTA_EXCEEDED
CARD_REQUIRED
NO_ACTIVE_PLAN
SPEND_CAP_REACHED
NOT_READY
NOT_FOUND
OCR_ERROR
STORAGE_ERROR
SERVICE_NOT_READY
INTERNAL_ERROR
Rate limits are enforced per API key (not per IP), so clients behind a shared proxy don't share a limit: /v1/convert 60 req/min, /v1/jobs 120 req/min, /v1/batch 30 req/min.
Billing is per page, not per call. Plans: Free 10 pages total (one-time, card required), Starter €29/mo (2,500), Pro €99/mo (10,000), Scale €190/mo (20,000). Your service is never interrupted: when monthly pages run out we email you and auto-charge an extra pack at your plan's per-page rate — Starter 500 @ €0.0116, Pro 2,000 @ €0.0099, Scale 4,000 @ €0.0095 — up to a monthly auto-recharge cap you set (and can turn off). Once the cap is reached the API returns 402 with an upgrade_url. Check usage with GET /v1/usage.
When you pass a webhook_url to /v1/jobs, we POST a JSON payload to that URL when the job reaches done or failed. Deliveries are retried with backoff on failure.
Each delivery is signed: verify the signature header with your webhook signing secret (shown in the dashboard) to confirm the request really came from myocr.app. The Python SDK ships a verify_webhook_signature helper.
The official Python SDK (myocr-client) wraps every endpoint with typed methods and exceptions, automatic Job.wait() polling with backoff, and webhook signature verification.
Prefer raw HTTP? Any HTTP client works — see the cURL and Node examples throughout this guide and the full interactive reference.
pip install myocr-client
OpenAPI 3.1 (openapi.json) · Postman · Insomnia · code generators
PDF, JPG and PNG. Sync /v1/convert allows up to 5 MB and 10 pages; async /v1/jobs handles files up to 50 MB.
Per page processed, counted across all endpoints, and reset monthly. The X-MyOCR-Pages-Used header tells you how many pages each call billed.
Test keys (sk_test_) are for development and integration testing; live keys (sk_live_) are for production traffic. Both authenticate the same way.
Use /v1/convert for small files you need answered right away. Use /v1/jobs (optionally with a webhook) for large files, batches or background processing.
Every endpoint, parameter and response is documented in the sections above. For machine use, download the OpenAPI spec (openapi.json) and import it into Postman, Insomnia or a client generator.
Bulk processing tips and templates. Free guide.