Skip to main content

myocr-client — Python SDK for myocr.app

Official Python client for the myocr.app API. Convert PDFs and images to structured Excel using myocr's OCR engine (invoice, receipt, bank statement, business card, generic tables, plain text).

PyPI version Python versions License: MIT


Install

pip install myocr-client

Quick start

Get an API key at /account/api (signup required), then:

from myocr_client import MyOCRClient

client = MyOCRClient(api_key="sk_live_...")
# or set MYOCR_API_KEY in env

# Synchronous conversion (≤5MB, ≤10 pages, returns immediately)
result = client.convert("invoice.pdf", model="invoice")
result.save("invoice.xlsx")

print(result.pages_used, result.model, result.request_id)

Models

Model Output Best for
tables xlsx with generic tables Any structured table
text plain txt OCR text extraction
invoice xlsx with Vendor / Customer / Total / Line items Invoices, bills
receipt xlsx with Merchant / Date / Items / Total Receipts
bank_statement xlsx with Account / Transactions sheet Bank statements
business_card xlsx with Contact / Company / Phones / Emails Business cards

Async jobs (files > 5MB or > 10 pages)

job = client.create_job(
    "annual_report.pdf",
    model="bank_statement",
    webhook_url="https://your.app/webhooks/myocr",  # optional
)

# Option 1: polling with exponential backoff
job.wait(timeout=600)
job.download("report.xlsx")

# Option 2: notified via webhook (preferred for prod) — see "Webhook verification" below

Batch (1–20 files in one call)

result = client.batch(
    ["a.pdf", "b.pdf", "c.pdf"],
    model="invoice",
    webhook_url="https://your.app/webhooks/myocr",
)
print(result.jobs_created, "jobs queued;", len(result.errors), "errors")

# Wait for all and download
for job in result.wait_all(timeout=1200):
    if job.is_done:
        job.download(f"{job.request_id}.xlsx")

Webhook verification

myocr signs every webhook with HMAC-SHA256 (header X-MyOCR-Signature: sha256=<hex>). Always verify before trusting the payload — and use raw bytes, not the parsed JSON:

from flask import Flask, request
from myocr_client import verify_webhook_signature

app = Flask(__name__)
SECRET = "your-shared-secret"   # same as server WEBHOOK_SIGNING_SECRET

@app.route("/webhooks/myocr", methods=["POST"])
def myocr_webhook():
    body = request.get_data()  # raw bytes, NOT request.get_json()
    sig = request.headers.get("X-MyOCR-Signature", "")
    if not verify_webhook_signature(body, sig, SECRET):
        return "invalid signature", 401

    event = request.get_json()  # safe now
    # {"event": "job.completed", "data": {"request_id": "...", "status": "done", ...}}
    return "", 200

Events: job.completed, job.failed. Retry policy: 1m → 5m → 30m → 2h (4 retries beyond the first attempt).

Error handling

Every error code maps to a typed exception:

from myocr_client import MyOCRClient, QuotaExceeded, InvalidApiKey, OcrEngineError

client = MyOCRClient(api_key="sk_live_...")

try:
    result = client.convert("doc.pdf", model="invoice")
except QuotaExceeded as e:
    print(f"Plan {e.current_plan}, used {e.calls_used}/{e.calls_limit}")
    print(f"Upgrade: {e.upgrade_url}")
    print(f"Resets: {e.reset_date}")
except InvalidApiKey:
    print("Rotate your key from /account/api")
except OcrEngineError:
    print("OCR engine upstream failure; safe to retry")
Exception HTTP Code
MissingApiKey 401 MISSING_API_KEY
InvalidApiKey 401 INVALID_API_KEY
UnsupportedModel 400 UNSUPPORTED_MODEL
UnsupportedFileType 400 UNSUPPORTED_FILE_TYPE
MissingFile 400 MISSING_FILE
FileTooLarge 413 FILE_TOO_LARGE
TooManyPages 413 TOO_MANY_PAGES
InvalidWebhookUrl 400 INVALID_WEBHOOK_URL
QuotaExceeded 402 QUOTA_EXCEEDED
NotReady 409 NOT_READY
NotFound 404 NOT_FOUND
OcrEngineError 502 OCR_ERROR
StorageError 503 STORAGE_ERROR
RateLimited 429
ServiceNotReady 503 SERVICE_NOT_READY
InternalError 500 INTERNAL_ERROR

The SDK automatically retries 429 and 5xx responses up to 3 times with exponential backoff (honoring Retry-After when present). After retries exhausted the exception is raised.

Input flexibility

client.convert() and client.create_job() accept:

  • A file path: client.convert("/path/to/doc.pdf", ...)
  • Raw bytes: client.convert(pdf_bytes, filename="doc.pdf", ...)
  • A file-like object: with open("doc.pdf", "rb") as f: client.convert(f, ...)

Configuration

Argument Env var Default
api_key MYOCR_API_KEY — (required)
base_url MYOCR_BASE_URL https://api.myocr.app
timeout 60s
retry_attempts 3
session new requests.Session()

For staging:

client = MyOCRClient(api_key="sk_test_...", base_url="https://beta.myocr.app")

Monitor your quota

Check current month usage programmatically (e.g. to upgrade before exhaustion):

usage = client.usage()
# {
#   "plan": "free", "calls_used": 42, "calls_limit": 100,
#   "percentage": 42.0, "reset_date": "2026-06-01T00:00:00",
#   "year_month": "2026-05", "is_test_key": False
# }
if usage["percentage"] and usage["percentage"] > 80:
    # alert ops, upgrade plan, or stop background workers
    ...

Status & limits

status = client.status()
# {
#   "service": "myocr.app API", "version": "v1",
#   "models_supported": ["bank_statement", "business_card", ...],
#   "features": {"sync_convert": True, "async_jobs": True, "webhook": True, ...},
#   "limits": {"sync_max_bytes": 5242880, "sync_max_pages": 10,
#              "jobs_max_bytes": 52428800, "sync_rate_per_minute": 60,
#              "jobs_rate_per_minute": 120}
# }

Rate limits (server-side)

Endpoint Limit
POST /v1/convert 60 / min
POST /v1/jobs 120 / min
POST /v1/batch 30 / min

The SDK handles 429 with automatic retry. If you saturate the quota, upgrade your plan from the dashboard.

Reference

  • Full OpenAPI spec: openapi.yaml
  • Interactive docs: /docs/api (Scalar UI)
  • Dashboard: /account/api — manage keys, view usage, upgrade
  • Webhook signing secret: generated when you create a webhook integration; shared via dashboard.

Development

git clone https://github.com/Selaf688/myocr-3.5
cd myocr-3.5/sdk/python
pip install -e ".[dev]"
pytest -v

Versioning

Semantic versioning. The API itself is v1 and stable; the SDK can release patch/minor independently.

License

MIT. See LICENSE.

Support

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

myocr_client-0.2.0.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

myocr_client-0.2.0-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

Details for the file myocr_client-0.2.0.tar.gz.

File metadata

  • Download URL: myocr_client-0.2.0.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.10.11

File hashes

Hashes for myocr_client-0.2.0.tar.gz
Algorithm Hash digest
SHA256 9ef5fa7e4569fdcb07579c4138334593ccbb7aef58d610796b06b795990f75bb
MD5 46f52502896f979894e5de9c2e1b2307
BLAKE2b-256 c03e97a4d0d31bfc044cdd87cd0545cbc590c1019d1a05ab01213fcac38184c9

See more details on using hashes here.

File details

Details for the file myocr_client-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: myocr_client-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.10.11

File hashes

Hashes for myocr_client-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a80aeb0e3b0b1aed4381250f6520665b2a3b1feb5350ca4243e3c3e32cdc479c
MD5 d4df8f6614ac58893801c39e4e9d2020
BLAKE2b-256 de0092cce684f0066f739ade3db6570f75e62e605d7c1176d809df501f9ac0c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page