klaaro
Official Python SDK for the Klaaro API — documents in, structured data out.
Install
pip install klaaro
Requires Python 3.9+. Dependencies: httpx, pydantic>=2.
Quick start
from klaaro import KlaaroClient
client = KlaaroClient(api_key="sk_your_key_here")
# 1. List datasets
datasets, meta = client.list_datasets()
print(datasets[0].name) # "Invoices 2026"
# 2. Upload a document (file)
with open("invoice.pdf", "rb") as f:
doc = client.upload_document(
datasets[0].id,
file=f,
filename="invoice.pdf",
)
print(doc.id, doc.status) # "b6d2a7f6-..." "queued"
# 3. Upload from URL
doc2 = client.upload_document(
datasets[0].id,
url="https://example.com/invoice.pdf",
)
# 4. Poll until complete
import time
document = client.get_document(doc.id)
while document.status in ("queued", "processing"):
time.sleep(3)
document = client.get_document(doc.id)
# 5. Read extracted records (clean values)
response = client.get_document_records(document.id)
print(response.records[0].data) # {"vendor_name": "Acme Corp", "total": 1234.56, ...}
Constructor
from klaaro import KlaaroClient
client = KlaaroClient(
api_key="sk_...", # or set KLAARO_API_KEY env var
base_url="https://dev.klaaro.ai/api/v1", # optional, defaults to prod
)
api_key falls back to the KLAARO_API_KEY environment variable if not passed.
Get your API key from Team → API keys in the Klaaro dashboard.
Async client
import asyncio
from klaaro import AsyncKlaaroClient
async def main():
async with AsyncKlaaroClient(api_key="sk_...") as client:
datasets, meta = await client.list_datasets()
doc = await client.get_document("b6d2a7f6-...")
asyncio.run(main())
Context manager
with KlaaroClient(api_key="sk_...") as client:
datasets, meta = client.list_datasets()
Authentication
All requests send Authorization: Bearer <api_key>. Three scopes:
| Scope | Unlocks |
|---|---|
read |
List and get endpoints |
write |
Upload, create, delete |
export |
Export endpoints |
Datasets
# List (paginated) — returns (list[Dataset], ListMeta)
datasets, meta = client.list_datasets(limit=20)
# Get one
dataset = client.get_dataset("a1b2c3d4-...")
# Delete
client.delete_dataset("a1b2c3d4-...")
# Records (clean extracted values)
records, meta = client.list_dataset_records(
"a1b2c3d4-...",
class_="invoice",
approval="approved",
limit=100,
)
# Records with full field metadata (review, validation, evidence)
flat_records, meta = client.list_dataset_records_flat("a1b2c3d4-...")
# Classes / schemas
classes, meta = client.list_dataset_classes("a1b2c3d4-...")
invoice_class = client.get_dataset_class("a1b2c3d4-...", "invoice")
Documents
# List with filters
docs, meta = client.list_documents(
dataset_id="a1b2c3d4-...",
status="completed",
limit=50,
)
# Upload (idempotent)
from pathlib import Path
doc = client.upload_document(
"a1b2c3d4-...",
file=Path("receipt.pdf"),
idempotency_key="my-unique-key-001",
)
# Get / delete
d = client.get_document("b6d2a7f6-...")
client.delete_document("b6d2a7f6-...")
# Records for a specific document
response = client.get_document_records("b6d2a7f6-...")
flat = client.get_document_records_flat("b6d2a7f6-...", include_unapproved=True)
Records
record = client.get_record("2c0c2e50-...") # clean values
flat = client.get_record_flat("2c0c2e50-...") # flat FieldView map
nested = client.get_record_nested("2c0c2e50-...") # nested FieldView tree
events, meta = client.list_record_field_events("2c0c2e50-...", field_path="total")
comments, meta = client.get_record_comments("2c0c2e50-...")
approvals, meta = client.get_record_approvals("2c0c2e50-...")
Webhooks
hook = client.create_webhook(
"a1b2c3d4-...",
url="https://my.app/hooks/klaaro",
events=["document.extraction_completed", "document.failed"],
)
client.update_webhook(hook.id, "a1b2c3d4-...", events=["document.extraction_completed"])
secret = client.rotate_webhook_secret(hook.id, "a1b2c3d4-...")
client.delete_webhook(hook.id, "a1b2c3d4-...")
Webhook signature verification
import hmac
import hashlib
import time
def verify_webhook(raw_body: str, sig_header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in sig_header.split(","))
timestamp = parts.get("t")
signature = parts.get("v1")
if not timestamp or not signature:
return False
if abs(time.time() - int(timestamp)) > 300:
return False
expected = hmac.new(
secret.encode(),
f"{timestamp}.{raw_body}".encode(),
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature)
Pagination
All list methods return (list[T], ListMeta). ListMeta has next_cursor and has_more.
cursor = None
while True:
records, meta = client.list_dataset_records(
"a1b2c3d4-...", limit=200, cursor=cursor
)
for record in records:
pass # process
if not meta.has_more:
break
cursor = meta.next_cursor
Error handling
from klaaro import KlaaroAPIError
try:
client.get_document("missing-id")
except KlaaroAPIError as e:
print(e.status, e.code, e.message)
# 404 document_not_found Document not found
| Code | Status | Meaning |
|---|---|---|
not_authenticated |
401 | Missing / invalid API key |
api_key_required |
401 | Session auth rejected on v1 |
insufficient_scope |
403 | Key missing required scope |
dataset_not_found |
404 | Dataset not found or inaccessible |
document_not_found |
404 | Document not found |
record_not_found |
404 | Record not found |
validation_error |
400 | Invalid request parameter |
rate_limited |
429 | Too many requests |
internal_error |
500 | Unexpected server error |
License
MIT
Metadata
Release files for klaaro 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| klaaro-0.1.1.tar.gz | 14.9 kB | With provenance | Details for klaaro-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| klaaro-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for klaaro-0.1.1-py3-none-any.whl |
Total release size: 30.0 kB
Release files / klaaro-0.1.1.tar.gz
| Download URL | klaaro-0.1.1.tar.gz |
|---|---|
| Size | 14.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9bff6659428b1da1b99ea619738540bb5d5799ab8c6c4c7a32d8a56a21216863
|
|
BLAKE2b-256 checksum How to use checksums |
f3fdfebf74793ccd095a9910f3ea9eb1d2c26b0479761b85fa1039ff8050b2ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.
Transparency logRelease files / klaaro-0.1.1-py3-none-any.whl
| Download URL | klaaro-0.1.1-py3-none-any.whl |
|---|---|
| Size | 15.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c8491207d6a1e93b8b02fa0099fd3c37a729f42b3e4f0b81e22810b13cadea9
|
|
BLAKE2b-256 checksum How to use checksums |
61e01ff841093a52d19f20d148602f44eb65a03a9877253baa39025f94661413
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.
Transparency logSecurity for klaaro 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for klaaro-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.