LOGIN  login to app
Compliance

GDPR-compliant document processing

EU servers, 30-min auto-delete, DPA on request. Built for European businesses.

Read the compliance guide →
API v1

myocr.app API documentation

A simple REST API to turn PDFs and images into clean, structured Excel. Authenticate with one header, send a file, get a spreadsheet back.

Overview

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.

Base URL: https://api.myocr.app Authentication: X-API-Key

Authentication

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());

Quickstart

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()));

Synchronous conversion

Method: POST /v1/convert Auth required: Yes Rate limit: 60/min

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.

Parameters

NameTypeRequiredDescription
filefileYesThe document to convert (PDF, JPG, PNG). Multipart field.
modelstringYesOne of: tables, text, invoice, receipt, bank_statement, business_card.
outputstringNoxlsx (default), txt, json or csv.

Asynchronous jobs

Method: POST /v1/jobs Auth required: Yes Rate limit: 120/min

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.

NameTypeRequiredDescription
filefileYesDocument up to 50 MB.
modelstringYesConversion model (see Models).
webhook_urlstringNoHTTPS URL notified (signed) when the job finishes.
# 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")

Batch conversion

Method: POST /v1/batch Auth required: Yes Rate limit: 30/min

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"

Models

Pass one of these model values. tables and text run on our OCR engine; the specialized models return domain-specific fields.

ModelWhat it extracts
tablesAny document with tables → one sheet per table, layout preserved. The general-purpose default.
textFull plain-text extraction (OCR) from any document. Always returns txt.
invoiceInvoice fields: vendor, date, totals, VAT and line items.
receiptReceipt fields: merchant, date, total, tax and items — ideal for expense reports.
bank_statementBank statement rows: date, description, debit, credit and running balance. Includes automatic balance verification (reconciliation).
business_cardContact fields from business cards: name, company, role, email, phone.

Output formats

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.

Responses & headers

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

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.

CodeHTTPMeaning
MISSING_API_KEY401No X-API-Key header was sent.
INVALID_API_KEY401The API key is unknown, revoked or malformed.
UNSUPPORTED_MODEL400The model value is not one of the supported models.
UNSUPPORTED_FILE_TYPE400File extension/type is not accepted (use PDF, JPG, PNG).
MISSING_FILE400No file was included in the request.
FILE_TOO_LARGE413File exceeds the size limit for the endpoint.
TOO_MANY_PAGES413Document has more pages than the endpoint allows.
INVALID_WEBHOOK_URL400The webhook_url is missing or not a valid HTTPS URL.
INSUFFICIENT_PAGES402Not enough page credits to process the request.
QUOTA_EXCEEDED402Monthly page quota exhausted — returns an upgrade_url.
CARD_REQUIRED402A verified payment card is required before creating API keys or using the trial.
NO_ACTIVE_PLAN403No active plan on this account — subscribe to a plan to make API calls.
SPEND_CAP_REACHED402Your monthly spending cap is reached — raise the cap or upgrade your plan.
NOT_READY409The job is not finished yet; the result is not available.
NOT_FOUND404The requested job or resource does not exist.
OCR_ERROR502The upstream OCR engine failed to process the document.
STORAGE_ERROR502Temporary storage (upload/result) failed — safe to retry.
SERVICE_NOT_READY503A required service is not configured/enabled yet.
INTERNAL_ERROR500Unexpected server error — retry, then contact support with the request_id.

Rate limits & quota

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.

Webhooks

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.

SDKs

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 spec

Download OpenAPI spec

OpenAPI 3.1 (openapi.json) · Postman · Insomnia · code generators

Download OpenAPI spec

FAQ

Which file types and sizes are supported?

PDF, JPG and PNG. Sync /v1/convert allows up to 5 MB and 10 pages; async /v1/jobs handles files up to 50 MB.

How is usage billed?

Per page processed, counted across all endpoints, and reset monthly. The X-MyOCR-Pages-Used header tells you how many pages each call billed.

What's the difference between test and live keys?

Test keys (sk_test_) are for development and integration testing; live keys (sk_live_) are for production traffic. Both authenticate the same way.

Should I use sync or async?

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.

Where do I see every parameter and schema?

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.

Productivity

Convert 100 invoices in 10 minutes

Bulk processing tips and templates. Free guide.

Read the guide →