SDK · Python
ocrqueen — Python
Typed Python client. Sync + idempotency baked in. Zero configuration after the install.
Install
pip install ocrqueenQuickstart
from ocrqueen import OCRQueen
client = OCRQueen(api_key="pk_test_xxx")
with open("invoice.pdf", "rb") as f:
job = client.extract.create(file=f)
final = client.jobs.wait(job)
print(final.markdown)
for page in final.document["pages"]:
for block in page["blocks"]:
print(block["type"], block.get("text", ""))That's the whole loop. extract.create() uploads and returns a job; jobs.wait() polls with exponential backoff until the job reaches a terminal status. Small documents finish in under a second.
Environment variables
The client picks up your key from the environment if you don't pass it explicitly — convenient for production and CI:
export OCRQUEEN_API_KEY=pk_live_xxx
# optional — for staging / self-hosted
export OCRQUEEN_BASE_URL=https://api.ocrqueen.comIdempotent retries
Pass any stable string to make retries safe across queue redelivery, crashes, and network blips:
job = client.extract.create(
file=open("invoice.pdf", "rb"),
idempotency_key="invoice-3034-2026-05-14",
)See the idempotency reference for the contract.
Fire-and-forget with webhooks
For batch pipelines, skip jobs.wait() entirely and pass a callback_url in options — we POST the completed result to your webhook URL when done.
job = client.extract.create(
file=open("invoice.pdf", "rb"),
options={"callback_url": "https://your-server.com/hooks/ocrqueen"},
)
print(job.id) # save this so the webhook handler can correlateThe batch + webhooks cookbook walks through a real receiver with HMAC verification.
Error handling
from ocrqueen import (
RateLimitError,
BadRequestError,
APIError,
)
try:
job = client.extract.create(file=open("doc.pdf", "rb"))
final = client.jobs.wait(job)
except RateLimitError as e:
time.sleep(5)
# retry
except BadRequestError:
# Bad input — fix the request, don't retry.
raise
except APIError as e:
print("extraction failed:", e.error_code) # e.g. "PDF_PASSWORD_PROTECTED"Full reference
The complete API surface (every method, every option, every exception type) lives in the package README:
