Python
Install the DocAI Python client (pip install doc-ai) and parse PDFs with an API key.
The official client is doc-ai on PyPI. The import package is docai.
pip install doc-aifrom docai import DocAI
client = DocAI() # reads DOCAI_API_KEY
# or: client = DocAI(api_key="docai_sk_live_...")
result = client.parse("invoice.pdf", extract_tier="plus")
print(result.extracted_json)If Butler Labs docai-py is also installed, from docai import DocAI may be overwritten. Uninstall docai-py in that environment.
Auth
Sign in on docai.subgradientlabs.com, open Settings → API keys, copy docai_sk_live_... once.
export DOCAI_API_KEY=docai_sk_live_...Every request uses Authorization: Bearer <key> against https://docaiapi.subgradientlabs.com/api/v1. There is no docai login CLI and no X-API-Key header.
New keys default to a 90-day lifetime (30 / 90 / 365 / never in Settings). Existing keys with no expiry stay valid until you rotate them. After Rotate, update DOCAI_API_KEY. The package does not call rotate (that endpoint is JWT-only).
If a key leaks, rotate it or revoke all keys. The prefix and last_used_at are visible on the key list; the secret is not.
Expired keys return 401 API_KEY_EXPIRED. The client raises AuthenticationError and does not retry. Open Settings → API keys, rotate, then set the new secret.
Parse and extract
Default extract_tier is plus. Public lanes only: lite, plus, pro, ultra. Do not send vendor aliases such as fast or agentic.
# Canned invoice schema (stable keys) - not parser=
result = client.parse("invoice.pdf", extract_tier="pro", schema_type="invoice")
# Pin Auto schema after the first run
result = client.parse("loan.pdf", schema_id=result.schema_id)extracted_json is schema-dependent. The typed envelope includes document_id, status, page_count, mode, extracted_json, schema_id, and confidence_score.
Files: path, bytes, or a file object. Timeout default is 180s. Every parse() / extract / batch sends Idempotency-Key (yours or a UUID4) and reuses it on timeout and 5xx retries so a charged extract is not billed twice.
Batch
Async extract is POST /extract/batch, not a separate /extract/async path.
batch = client.extract.batch(["a.pdf", "b.pdf"], extract_tier="plus")
done = client.batches.poll(batch.batch_id)Usage and credits
Credits live on the org, not on the key. client.usage() calls GET /billing/usage.
Insufficient balance is 402 INSUFFICIENT_CREDITS (includes required, balance, and a buy URL). Do not retry. Buying packs is browser checkout, not the Python client.
Errors the client maps
| HTTP | Code | Client behavior |
|---|---|---|
| 401 | API_KEY_EXPIRED / invalid key | AuthenticationError; no retry |
| 402 | INSUFFICIENT_CREDITS / TRIAL_MODE_RESTRICTED | stop; no downgrade retry |
| 429 | RATE_LIMIT_EXCEEDED | retry with backoff / retry_after_seconds |
| 5xx | upstream | limited retries, same idempotency key |
See Errors and Authentication. OpenAPI subset: https://docaiapi.subgradientlabs.com/api/openapi.json (Swagger UI at /docs on the API host).