Suparse

Python SDK & CLI

Ostatnia aktualizacja: 2026-10-15

Suparse Python SDK

Official Python SDK and CLI for the Suparse Document Processing API.

Suparse is an AI-powered document processing API for extracting structured data from any document type, including invoices, receipts, bank statements, purchase orders and many more. This SDK wraps the REST API with a Python client and CLI.

Requirements

Python 3.10+ is required. pip install suparse automatically installs the SDK dependencies: httpx, pydantic, pydantic-settings, and tenacity.

Installation

pip install suparse

Authentication

You'll need an API key to use the SDK or CLI. To obtain one:

  1. Sign in at suparse.com
  2. Go to the API Keys tab
  3. Enter a key name and click Generate New Key
  4. Copy the key value — it will be shown only once

Set it as an environment variable:

export SUPARSE_API_KEY="your_api_key_here"

For the CLI, you can also store it in ~/.config/suparse/config.json:

{
  "apiKey": "your_api_key_here"
}

Or pass it directly to the SDK constructor (see below).

Quick Start

With SUPARSE_API_KEY set, process a document from the terminal:

suparse process invoice.pdf -o results.json

Or use Python synchronously:

from suparse import SuparseClient
 
with SuparseClient() as client:
    result = client.extract("invoice.pdf")
    for document in result.succeeded:
        print(document.original_file, document.data)
    for failure in result.failed:
        print(f"Failed: {failure.file}: {failure.error}")

For an async application:

import asyncio
from suparse import AsyncSuparseClient
 
async def main():
    async with AsyncSuparseClient() as client:
        result = await client.extract("invoice.pdf")
        for document in result.succeeded:
            print(document.original_file, document.data)
        for failure in result.failed:
            print(f"Failed: {failure.file}: {failure.error}")
 
asyncio.run(main())

Always inspect result.failed, even for a single file: per-file failures are returned there without raising an exception. Setup or cleanup errors can still raise exceptions. See Error Handling.

CLI Usage

Run suparse --help or suparse process --help for full usage information.

Set your API key and process a file directly from the terminal. The SDK will auto-upload, poll, and download the resulting JSON.

Process a Document

export SUPARSE_API_KEY="your_api_key_here"
 
# Auto-detect template
suparse process path/to/invoice.pdf -o results.json
 
# Use specific template without auto-splitting
suparse process path/to/invoice.pdf --template-id YOUR_TEMPLATE_ID
 
# Auto-split a multi-page PDF containing mixed document types (e.g. receipts + bank statements)
suparse process path/to/merged.pdf --with-split
 
# Use specific template with auto-splitting
suparse process path/to/invoice.pdf --template-id YOUR_TEMPLATE_ID --with-split
 
# Process and auto-delete documents from server after download
suparse process path/to/invoice.pdf --cleanup
 
# Export directly to XLSX
suparse process path/to/invoice.pdf --format xlsx
 
# Choose the flat XLSX layout
suparse process path/to/invoice.pdf --format xlsx --xlsx-layout flat
 
# Export CSV using original template columns
suparse process path/to/invoice.pdf --format csv --export-type original
 
# Process an encrypted PDF without putting the password in shell history
suparse process path/to/encrypted.pdf --prompt-pdf-password
 
# Assign uploaded documents to a folder
suparse process path/to/invoice.pdf --folder-id <folder-id>
 
# Start automatic schema creation and wait for the generated template
suparse quick-create path/to/example.pdf --wait
 
# Start schema creation for an encrypted PDF without putting the password in shell history
suparse quick-create path/to/encrypted.pdf --prompt-pdf-password
 
# Inspect a previously started schema-creation run
suparse quick-create-status <run-id>

Process a Folder

Process all supported files (.pdf, .jpg, .jpeg, .png, .heic, .heif) in a folder. All files are uploaded and polled individually. By default, results are combined into a single JSON file.

Use --format csv or --format xlsx to export spreadsheet files; exports that produce multiple files may be returned as a ZIP. Use --format google_sheets to export to Google Sheets (requires the Google Sheets integration).

# Process all supported files in a folder
suparse process --folder path/to/receipts/
 
# Output to a specific file (default: {folder_name}_results.json)
suparse process --folder path/to/receipts/ -o all_results.json
 
# Process a folder with a specific template
suparse process --folder path/to/receipts/ --template-id YOUR_TEMPLATE_ID
 
# Process a folder with auto-splitting enabled
suparse process --folder path/to/receipts/ --with-split
 
# Process a folder and auto-delete documents from server after download
suparse process --folder path/to/receipts/ --cleanup
 
# Export a folder to CSV, XLSX, or Google Sheets
suparse process --folder path/to/receipts/ --format csv
suparse process --folder path/to/receipts/ --format xlsx -o ./exports
suparse process --folder path/to/receipts/ --format google_sheets

Export Existing Documents

Export documents by their IDs without uploading them again:

suparse export DOCUMENT_ID --format json -o results.json
suparse export DOCUMENT_ID --format xlsx --xlsx-layout flat -o export.xlsx
suparse export DOCUMENT_ID --format csv --export-type original -o export.csv
suparse export DOCUMENT_ID --format xlsx --wait-timeout 900 \
  --idempotency-key 44444444-4444-4444-8444-444444444444 -o export.xlsx

--wait-timeout controls how long to wait for a background export (default: 900 seconds). --idempotency-key accepts a UUID; save it to recover an uncertain submission. Accepted job IDs and recovery instructions are printed to stderr.

Choose an Export Mode and XLSX Layout

--export-type controls which template defines the columns for CSV, XLSX, and Google Sheets. The SDK uses the same values through ExportType.

ModeColumn selectionWhen to use it
originalEach document's historical processing templatePreserve the fields and columns used when that document was processed
unifiedDocuments grouped by template group, using the latest active template's columnsCombine documents processed with different versions of the same template for reporting

Unified export projects existing extracted values onto the selected columns; it does not reprocess documents. Fields missing from older results appear blank. Different template groups remain separate; an export producing multiple files may be returned as a ZIP.

--xlsx-layout controls how XLSX data is arranged, independently of export mode:

LayoutOrganizationWhen to use it
standard (default)Document-level fields in a summary sheet; line items in a separate items sheetReview document summaries and item details separately
flatDocument-level fields repeated beside each line-item row in a data sheetFilter, build pivot tables, or import rows into another tool

For example, an invoice INV-001 from Acme with two items would have these simplified data sheets (actual columns come from your template):

Standard — summary sheet

InvoiceSupplier
INV-001Acme

Standard — items sheet

ItemAmount
Paper10
Ink20

Flat — data sheet

InvoiceSupplierItemAmount
INV-001AcmePaper10
INV-001AcmeInk20

The example illustrates unified output; original standard output presents summary fields as key/value pairs. Unified workbooks also include a FileName column to identify the source document.

suparse export DOCUMENT_ID --format xlsx --export-type unified --xlsx-layout standard -o standard.xlsx
suparse export DOCUMENT_ID --format xlsx --export-type unified --xlsx-layout flat -o flat.xlsx

Read Task Results and Resume Exports

# Read currently available results; these commands do not wait for processing.
suparse task-results TASK_ID
suparse task-results TASK_ID --jsonl
suparse task-results TASK_ID --output results.json --overwrite
suparse task-results TASK_ID --single-page --cursor TOKEN --page-size 50
 
# Inspect, wait for, and download a background export.
suparse export-job-status JOB_ID --format json
suparse export-job-wait JOB_ID --timeout 900 --format json
suparse export-job-download JOB_ID -o export.xlsx --overwrite

task-results prints a JSON array by default, streams JSONL with --jsonl, or prints a page containing documents and next_cursor with --single-page. --page-size accepts 1–100 (default: 100). --cursor requires --single-page; --jsonl and --single-page are mutually exclusive.

Task-result file output is saved only after all requested pages are read successfully. Replacing an existing file requires --overwrite. JSONL written to stdout may contain partial results if a later page fails; errors are printed to stderr.

export-job-download requires a completed job and does not wait. Omit -o to use the artifact filename in the current directory, or pass an existing output directory. Replacing a file requires --overwrite. A wait timeout does not cancel the server job; run export-job-wait again to resume waiting.

CLI exit codes are 0 for success, 1 for execution failure, and 2 for invalid arguments. Check schema-creation result status as described in Automatic Schema Creation: starting a run successfully does not mean schema creation has completed.

Delete Documents

# Delete one or more documents by ID (prompts for confirmation)
suparse delete <document_id>
suparse delete <id1> <id2> <id3>
 
# Skip confirmation prompt
suparse delete <id1> <id2> -y

Deleting a parent document automatically deletes all its child documents (server-side cascade).

List Available Templates

Templates define how a document type (invoice, receipt, bank statement, etc.) is parsed. Before processing a document, check which templates are already assigned to your account:

# List templates assigned to your account (table format)
suparse templates
 
# List templates in JSON format
suparse templates --format json
 
# Include all system templates (not yet assigned to your account)
suparse templates --include-system
 
# Request complete template records, including schema and saved document IDs
suparse templates --view full --format json

The recommended way to process documents is with auto-split enabled (--with-split), which handles both single-type and mixed document types automatically:

suparse process path/to/documents.pdf --with-split -o results.json

If you consistently process one document type, look up the template ID and pass it directly:

  1. Run suparse templates to see templates assigned to your account.
  2. Use the matching template ID:
    suparse process invoice.pdf --template-id <id> -o results.json
  3. If no template matches, run suparse templates --include-system to browse all system templates. Assign one to your account via the Suparse UI.
  4. If no system template fits, create a custom template using the template creator in the Suparse UI.

Configuration

The CLI reads settings from environment variables or a .env file in the working directory:

VariableDefaultDescription
SUPARSE_API_URLhttps://api.suparse.com/api/v1/API base URL
SUPARSE_API_KEY—Your API key (required)
POLL_INTERVAL5Seconds between polling attempts
MAX_POLL_ATTEMPTS300Max polling attempts before timeout
LOG_LEVELINFOLogging level

Priority: CLI flags > environment variables > .env file > defaults.

For API keys, the CLI also checks ~/.config/suparse/config.json after SUPARSE_API_KEY and .env. The config file should contain a JSON object with an apiKey string.

Global Options

Place global options before the subcommand, for example suparse --verbose process invoice.pdf. Use suparse --version to print the installed CLI version.

OptionDescription
--api-urlAPI URL (default: from SUPARSE_API_URL env var)
--api-keyAPI Key (default: from SUPARSE_API_KEY env var)
-v, --verboseEnable verbose (DEBUG) output

CLI Options

CommandOptionDescription
process--folderProcess all supported files in a folder (mutually exclusive with file path)
process, export-o, --outputOutput file path or existing output directory; omit to use a default filename
process--template-idTemplate ID to use (default: auto-detect)
process--with-splitAuto-split multi-page PDFs containing mixed document types (e.g. receipts + bank statements) so each is processed with the correct template (default: off)
process--cleanupDelete uploaded documents after processing; cleanup is deferred if an export may still be running (default: off)
process, export--formatExport format: json, csv, xlsx, or google_sheets (default: json)
process, export--export-typeExport mode for CSV, XLSX, and Google Sheets: unified or original (default: unified)
process, export--xlsx-layoutXLSX layout: standard or flat (default: standard)
process--folder-idFolder ID applied to every uploaded input
process--prompt-pdf-passwordPrompt securely for an encrypted PDF password
templates--formatOutput format: table or json (default: table)
templates--include-systemInclude system templates not yet assigned to your account (default: off)
templates--viewTemplate response view: summary or full (default: summary)
quick-create--waitWait for automatic schema creation to reach a terminal state
quick-create--formatOutput format: table or json (default: table)
quick-create--prompt-pdf-passwordPrompt securely for an encrypted PDF password
quick-create-status--formatOutput format: table or json (default: table)
delete-y, --yesSkip confirmation prompt
export--wait-timeoutBackground completion wait in seconds (default: 900)
export--idempotency-keyUUID key to retain for submission recovery
task-results--jsonl, --single-pageStream records or return a single page (mutually exclusive)
task-results--cursor, --page-sizeContinuation token (single-page only) and page size from 1–100
task-results, export-job-download-o, --output, --overwriteSave output; explicitly allow replacing an existing file
export-job-status, export-job-wait--formatOutput format: table or json (default: table)
export-job-wait--timeoutLocal completion wait in seconds (default: 900)

Python SDK Usage

The SDK provides both synchronous and asynchronous clients. Both manage connections, process multiple inputs concurrently, and retry eligible transient failures. Use the synchronous client in synchronous code and the asynchronous client in an async application.

The Quick Start shows complete examples for both clients. The examples below use SuparseClient unless they demonstrate async-specific behavior. With AsyncSuparseClient, use async with and await the corresponding methods; options and result types are the same.

The client reads SUPARSE_API_KEY and SUPARSE_API_URL from environment variables or a .env file by default, so you can simply use SuparseClient() or AsyncSuparseClient() if those are set.

Use a context manager to close connections automatically, or call client.close() (await client.close() for the async client).

Extract One or More Documents

extract() is the primary API. It accepts a single file, a list of files, or any iterable (like Path.glob). Each input can be a string path, a Path object, or an open file handle.

BatchResult.total counts input sources. BatchResult.succeeded contains the task export groups returned by the API, so one input can produce multiple successful entries when splitting or template grouping is involved. Progress callbacks run once per returned export group (or once for a failed input). Callbacks preserve API order within one input, but callbacks from concurrently processed inputs may be interleaved.

from pathlib import Path
from suparse import FailedResult, SuparseClient
 
def print_progress(result):
    if isinstance(result, FailedResult):
        print(f"Failed: {result.file}: {result.error}")
    else:
        print(f"Done: {result.original_file}")
 
with SuparseClient() as client:
    # A list can mix string paths and Path objects. A glob iterable also works:
    # files=Path("./receipts/").glob("*.pdf")
    result = client.extract(
        files=["./receipts/jan.pdf", Path("./receipts/feb.pdf")],
        on_progress=print_progress,
    )
    for document in result.succeeded:
        print(document.original_file, document.data, document.document_ids)
    for failure in result.failed:
        print(failure.file, failure.error)
    print(f"Input files: {result.total}")

document.data contains the extracted fields. Use document.documents for the DocumentExport records, including credits_used, template_id, document_id, file_name, page_start, and page_end. Serialize the complete export group with document.model_dump(mode="json").

Extract a Folder

extract_folder() discovers supported files and delegates to extract(). The default pattern "*" scans the immediate directory; use pattern="**/*" to include subdirectories. A pdf_password or folder_id passed to extract() or extract_folder() applies to every input. Use separate calls when inputs need different values.

from suparse import SuparseClient
 
with SuparseClient() as client:
    result = client.extract_folder(
        "./receipts/",
        template_id="YOUR_TEMPLATE_ID",
        split=True,
        cleanup=True,
    )
    for document in result.succeeded:
        print(document.original_file, document.data)
    for failure in result.failed:
        print(failure.file, failure.error)

For async code, use result = await client.extract_folder(...) inside an async with AsyncSuparseClient() block, then inspect the same result lists.

Automatic Schema Creation

Create a template from an example document with start_quick_schema_creation(). It accepts a string path, Path, or open binary stream and returns a typed result containing a run ID. Use get_quick_schema_creation(run_id) to check status once, or wait_for_quick_schema_creation(run_id) to wait for a terminal result. Inspect result.status: failed and completed_with_errors runs are returned as typed results, including error and failed-document details.

from pathlib import Path
from suparse import SuparseClient
 
with SuparseClient() as client:
    started = client.start_quick_schema_creation("example.pdf")
    # Persist the ID before waiting so a later timeout can be recovered.
    Path("schema-run-id.txt").write_text(started.run_id, encoding="utf-8")
    result = client.wait_for_quick_schema_creation(started.run_id)
    print(result.status, result.model_dump(mode="json"))

Use start_quick_schema_creation(..., pdf_password=...) for encrypted PDFs. The SDK leaves caller-owned streams open. Start requests are attempted once unless both upload_batch_id and source_upload_id are supplied for an existing batch source. If a start request fails without a response, follow Schema Creation Recovery before submitting again.

The quick-create and quick-create-status CLI commands return exit code 1 for failed runs and for completed_with_errors; queued, processing, and fully completed results return 0.

Error Handling

All SDK exceptions inherit from SuparseError. extract() and extract_folder() collect per-file processing errors in result.failed, even for a single input. Check that list after every call. Setup or cleanup errors can still raise exceptions.

Low-level methods raise exceptions directly, so you can handle specific types:

from suparse import SuparseClient
from suparse.exceptions import (
    SuparseError,
    SuparseAuthError,
    SuparseNetworkError,
)
 
with SuparseClient(api_key="your_api_key_here") as client:
    try:
        client.list_templates()
    except SuparseAuthError:
        print("Invalid API key")
    except SuparseNetworkError:
        print("Connection failed")
    except SuparseError as e:
        print(f"Unexpected error: {e}")

With AsyncSuparseClient, use the same exception handlers around await client.list_templates().

File objects and in-memory binary streams can also be passed to extract(). The SDK leaves caller-owned streams open; inspect result.failed as in the Quick Start.

Read Task Results

Use get_task_results() to read one page of completed documents, or iter_task_results() to traverse all available pages. These methods return current results immediately. While a task is processing, results may be empty or partial; an empty page does not mean processing has finished.

from pathlib import Path
from suparse import SuparseClient
 
with SuparseClient() as client:
    task_id = client.upload_file(Path("invoice.pdf"))
    client.poll_task_status(task_id)  # Wait if you need the complete result set.
 
    for document in client.iter_task_results(task_id):
        print(document.id, document.extraction_data)
 
    page = client.get_task_results(task_id, limit=50)
    if page.next_cursor is not None:
        next_page = client.get_task_results(task_id, cursor=page.next_cursor, limit=50)

limit and the iterator's page_size accept integers from 1 to 100 (default: 100). Each TaskResultPage contains documents and next_cursor; a null cursor indicates the end of the available pages. Save a non-null cursor to resume pagination. TaskResultDocument.extraction_data contains the extracted fields, including nested JSON; page numbers are returned as supplied by the API.

With AsyncSuparseClient, await get_task_results() and use async for with iter_task_results():

import asyncio
from suparse import AsyncSuparseClient
 
async def main():
    async with AsyncSuparseClient() as client:
        task_id = "your-task-id"
        async for document in client.iter_task_results(task_id, page_size=50):
            print(document.extraction_data)
 
asyncio.run(main())

Export Processed Documents

Use document IDs from TaskExport.document_ids or poll_task_status() to export previously processed documents:

from pathlib import Path
from suparse import ExcelLayout, ExportFormat, ExportType, SuparseClient
 
with SuparseClient() as client:
    result = client.extract("invoice.pdf")
    document_ids = [doc_id for group in result.succeeded for doc_id in group.document_ids]
    if document_ids:
        saved_path = client.download_results(
            document_ids,
            Path("invoices.xlsx"),
            format=ExportFormat.XLSX,
            export_type=ExportType.UNIFIED,
            xlsx_layout=ExcelLayout.FLAT,
        )
        print(saved_path)
    for failure in result.failed:
        print(failure.file, failure.error)

See Choose an Export Mode and XLSX Layout for column selection, layout examples, and CLI equivalents.

Choose a method based on how you want to consume the export:

MethodReturnsUse for
export_documents() / fetch_results()ExportResultParsed JSON in .task_exports, CSV/XLSX bytes in .data, or Google Sheets details in .google_sheets_export
download_results()Saved path as strWriting an export to a file
download_documents()FileExportExact attachment bytes in .data, with .filename, .content_type, and .is_zip metadata

All four methods accept format, export_type, xlsx_layout, wait_timeout, and idempotency_key as keyword arguments. download_results() also accepts an output path. An omitted path uses the API filename or a generated fallback in the current directory; an existing directory receives the export filename.

Advanced Developer Workflows

Use these sections when you need direct control over uploads, recovery after an uncertain request, or background export artifacts. For standard extraction, start with Quick Start and Export Processed Documents.

Low-Level API

For cases where you need file-based output or direct control over the upload/poll/download cycle:

from pathlib import Path
from suparse import ExportFormat, SuparseClient
 
with SuparseClient() as client:
    # Upload a file and get back a task ID
    task_id = client.upload_file(
        Path("invoice.pdf"),
        template_id="YOUR_TEMPLATE_ID",
        split=False,
        auto_approve=True,  # Set to False to require human review in the Suparse UI
    )
 
    # Poll until processing completes (returns status + document IDs)
    status, doc_ids = client.poll_task_status(task_id)
 
    # Export results by document IDs to a JSON file. Omitting the output path
    # uses the API filename or a timestamped fallback in the current directory.
    saved_path = client.download_results(
        doc_ids,
        Path("output.json"),
    )
 
    # Fetch non-JSON exports in memory
    csv_export = client.fetch_results(
        doc_ids,
        format=ExportFormat.CSV,
    )
    print(csv_export.filename, csv_export.content_type, csv_export.is_zip)
 
    # Delete documents by ID
    client.delete_documents(doc_ids)
 
    # List available templates
    templates = client.list_templates()
    for t in templates:
        print(f"{t.name} ({t.template_language})")

The async client also provides process_document() for file output and process_batch() for raw batch tuples. process_document() returns a success boolean; process_batch() returns (succeeded, failed), where successful entries are (Path, task_id, document_ids) and failures are (Path, task_id_or_none, exception). Check these outcomes before continuing. Use extract() for the shared BatchResult interface shown above.

For the async equivalent, await upload_file(), poll_task_status(), download_results(), fetch_results(), delete_documents(), and list_templates() inside async with AsyncSuparseClient().

Schema Creation Recovery

Before starting a run, retain the input filename, submission time (with time zone), destination folder, and any existing upload_batch_id / source_upload_id. Save the returned run_id immediately, as in the schema-creation example.

  • You have a run ID: call get_quick_schema_creation(run_id) or run suparse quick-create-status RUN_ID. Resume waiting with wait_for_quick_schema_creation(run_id); do not start another run.

  • The start response was lost: the SDK and CLI have no activity-list method. Query the REST activity endpoint using the same API key and API base URL. For the default API URL:

    curl --get 'https://api.suparse.com/api/v1/templates/quick-create' \
      --header "X-API-Key: $SUPARSE_API_KEY" \
      --data-urlencode 'limit=50'

    Compare each entry in items by filename, created_at, and, when known, upload_batch_id and folder_id. You can filter the request by upload_batch_id or folder_id. Follow a non-null next_cursor by sending it as the next request's cursor query parameter. Use a matching entry's run_id with the status command above.

Activity is scoped to the authenticated uploader and effective team. Fully successful runs are omitted, and failed/partial runs are visible only within their observation window. An empty list therefore does not prove that the request was rejected. Check the Suparse UI for the resulting documents and template. If you cannot identify the outcome, contact support with the retained filename, time, folder, source IDs, and error details before resubmitting. Do not send your API key or PDF password.

Detailed Upload Confirmations

upload_file() returns a task ID string. Use upload_file_detailed() when you need the complete confirmation, including upload or replay metadata:

from pathlib import Path
from suparse import SuparseClient
 
with SuparseClient() as client:
    confirmation = client.upload_file_detailed(
        Path("invoice.pdf"),
    )
    print(confirmation.model_dump(mode="json"))

For an existing upload batch, pass its upload_batch_id and source_upload_id to upload_file_detailed(). Obtain these IDs from the workflow that created the batch; this SDK does not provide methods to create upload batches.

Upload confirmations without both IDs are attempted once. A network failure or 5xx response raises SuparseUploadConfirmationUnknownError: the upload may already have been accepted. Retain the exact upload_reference_id, filename, submission time (with time zone), folder ID, and any batch/source IDs. With extract() or extract_folder(), read the reference from failure.upload_reference_id in result.failed.

The SDK and CLI have no lookup by upload reference. To find candidate documents, open the Suparse UI and search for the filename around the submission time, or query the REST document list using the same API key. For example, replace the filename and timestamp below (and the base URL if you use a custom API URL):

curl --get 'https://api.suparse.com/api/v1/documents/' \
  --header "X-API-Key: $SUPARSE_API_KEY" \
  --data-urlencode 'filename=invoice.pdf' \
  --data-urlencode 'created_after=2026-10-15T09:00:00Z' \
  --data-urlencode 'uploaded_by=me' \
  --data-urlencode 'page=1' \
  --data-urlencode 'items_per_page=100'

Inspect all matching pages, checking creation time, folder/batch, and document contents; filenames alone are not unique. Export confirmed processed document IDs with suparse export DOCUMENT_ID. If no candidate can be reliably matched, ask support to reconcile the upload using the saved upload_reference_id and submission details before uploading again. An empty search does not establish that confirmation failed.

When both IDs are supplied, the SDK uses the server's replay protection for bounded transient retries. A 503 response is surfaced without retry because the upload may already have been accepted.

Structured API Errors

SuparseAPIError and its subclasses expose status_code and the raw response_body. Structured API errors also provide .code and .meta:

from suparse import SuparseAPIError, SuparseClient
 
with SuparseClient() as client:
    try:
        client.list_templates()
    except SuparseAPIError as exc:
        print(exc.status_code, exc.code, exc.meta, exc.response_body)

Background Exports and Recovery

Export methods automatically wait when the API accepts an export as a background job. wait_timeout defaults to 900 seconds and bounds the background completion wait, including polling retries. It does not set a deadline for submission or download; individual HTTP requests have separate timeouts.

The SDK generates a UUID idempotency key for each export submission and reuses it for automatic submission retries. To retain the key before making a request, pass your own UUID string as idempotency_key. Keep it with any reported job ID so you can recover after a timeout or uncertain response. An idempotency key does not guarantee exactly-once generation for immediate exports.

If the submission response was lost and you only have the key, repeat the same export request with the same document IDs, format, export mode, layout, and idempotency_key. For the CLI, rerun the original suparse export command with its saved --idempotency-key. Retain the original request options alongside the key so you can reproduce it. Once a job ID is available, resume that job using the methods below.

Use get_export_job() to inspect a job, wait_for_export_job() to wait for completion, and download_export_job() to save its artifact:

from pathlib import Path
from suparse import SuparseClient, SuparseExportError, SuparsePollingTimeoutError
 
export_job_id = "your-export-job-id"  # Job ID reported by an earlier export.
output_dir = Path("exports")
output_dir.mkdir(parents=True, exist_ok=True)
 
with SuparseClient() as client:
    job = client.get_export_job(export_job_id)
    print(job.status)
    try:
        client.wait_for_export_job(export_job_id, wait_timeout=900)
        saved_path = client.download_export_job(export_job_id, output_dir)
        print(saved_path)
    except SuparsePollingTimeoutError as exc:
        print(exc.export_job_id, exc.last_status, exc.idempotency_key)
        # Resume later with wait_for_export_job(exc.export_job_id).
    except SuparseExportError as exc:
        print(exc.reason, exc.code, exc.meta, exc.export_job_id)

get_export_job() also returns failed jobs and jobs whose artifacts are no longer available. Job counts describe document selection, generation, and exclusions; they are not a progress percentage.

Artifact Downloads and Integrity

download_export_job() requires a completed job with an available artifact and does not wait. It verifies the artifact's size and SHA-256 checksum before publishing the file. It refuses to replace an existing file unless overwrite=True. download_results() can replace an existing file. In-memory export methods buffer the artifact in memory.

Timeouts, Cancellation, and Deferred Cleanup

A local timeout or cancellation does not cancel the server job. Export errors include export_job_id, idempotency_key, and job when available. For async cancellation, use get_export_recovery_context() to retrieve these details through the exception's cause/context chain on all supported Python versions. Retain the returned context to resume later, and propagate cancellation:

import asyncio
from suparse import get_export_recovery_context
 
try:
    result = await export_task
except asyncio.CancelledError as exc:
    recovery = get_export_recovery_context(exc)
    if recovery is not None:
        print(recovery.export_job_id, recovery.idempotency_key)
        # Persist these values; resume by job ID when available.
        # Before acceptance, only the idempotency key may be known.
    raise

SuparsePollingTimeoutError also exposes last_status and operation_may_be_running. If processing with cleanup=True leaves an export running or its submission outcome uncertain, cleanup is deferred for the affected source documents. Inspect or resume the export, then delete those documents explicitly. For extract(), recovery identifiers appear in FailedResult.error.

Export Failure Reasons and Format Limits

SuparseExportError.reason identifies the failure:

ReasonMeaning
job_failureThe export job failed
artifact_unavailableThe artifact is unavailable or expired
unsupported_stateThe job is in a state the SDK cannot handle
protocol_failureThe export response does not match the expected protocol
storage_failureThe artifact could not be downloaded
integrity_failureThe downloaded artifact's size or checksum does not match
incompatible_artifactThe artifact cannot be used as the requested result type

Parsed JSON exports require a JSON array matching list[TaskExport]. Incompatible background JSON or ZIP artifacts raise SuparseExportError; the SDK does not unpack ZIPs. Use download_documents() or download_export_job() when you need the original artifact bytes. Google Sheets exports are supported for immediate API responses; background Google Sheets jobs raise SuparseExportError with reason="incompatible_artifact".

SDK Reference

Constructor Parameters

Both SuparseClient and AsyncSuparseClient accept the same parameters:

ParameterTypeDefaultDescription
api_urlstrSUPARSE_API_URL env var or https://api.suparse.com/api/v1/API base URL
api_keystrSUPARSE_API_KEY env varYour API key (required)
poll_intervalint5Seconds between polling attempts
max_poll_attemptsint300Max polling attempts before timeout

Result Objects

ObjectPropertiesDescription
TaskExporttask_id, original_file, total_documents_extracted, documents, data, document_idsExport group for a processed input; documents contains DocumentExport objects with credits_used, template_id, etc.
FailedResultfile, error, upload_reference_idFile that failed during extraction
BatchResultsucceeded, failed, totalContainer for batch results; total counts inputs while succeeded contains returned task export groups
ExportResultformat, content_type, filename, is_zip, data, task_exports, google_sheets_exportLow-level export result for JSON, CSV, XLSX, and Google Sheets
QuickSchemaStartResult, QuickSchemaStatusResult, QuickSchemaTerminalResultUnions of typed lifecycle modelsAutomatic schema-creation results; inspect .status and model-specific fields
TaskResultPagedocuments, next_cursorOne page of currently completed task results
TaskResultDocumentid, file_name, extraction_data, page and template fieldsExtracted document returned by task-result reads
ExportJobReadexport_job_id, status, counts, artifact, errorBackground export status and recovery details
ExportJobArtifactfilename, content_type, size_bytes, checksum_sha256Downloadable artifact metadata
FileExportformat, content_type, filename, is_zip, dataExact attachment bytes from download_documents()

Export Formats

FormatResultNotes
jsonTaskExport listDefault structured extraction result
csvBinary export bytesUses API filename when provided; may be a ZIP
xlsxBinary export bytesUses API filename when provided; may be a ZIP
google_sheetsGoogleSheetsExportRequires Google Sheets integration

export_type selects the template columns as explained in Choose an Export Mode and XLSX Layout. It accepts unified or original. The CLI and parsed export methods default to unified; download_documents() defaults to original. It affects CSV, XLSX, and Google Sheets exports; parsed JSON returns task export groups.

xlsx_layout accepts ExcelLayout.STANDARD (the default) or ExcelLayout.FLAT. It only affects XLSX exports.

Exceptions

All exceptions inherit from SuparseError.

ExceptionRaised When
SuparseErrorBase exception for all SDK errors
SuparseNetworkErrorNetwork connection fails or times out
SuparsePollingTimeoutErrorProcessing/schema polling exceeds its attempt limit, or a background export exceeds wait_timeout
SuparseExportErrorBackground job, artifact download, integrity, or format failure; inspect .reason and recovery context
SuparseProcessingErrorDocument fails to process on the server
SuparseAPIErrorBase for HTTP error responses (has status_code, response_body, code, meta)
SuparseAuthError401/403 authentication or authorization error
SuparseNotFoundError404 resource not found
SuparseRateLimitError429 too many requests
SuparseServerError5xx server error
SuparseUploadConfirmationUnknownErrorUpload confirmation outcome is unknown; inspect upload_reference_id before taking action
SuparseSDKErrorSDK fails to parse the API response into the expected data model

extract() Parameters

ParameterTypeDefaultDescription
filesstr, Path, IO[bytes], or iterable of theserequiredOne or more files to process
template_idstrNoneTemplate ID (auto-detect if omitted)
splitboolFalseAuto-split multi-page documents
auto_approveboolTrueSet to False to require human review in the Suparse UI
pdf_passwordstrNonePassword applied to every input encrypted PDF
folder_idstrNoneFolder ID applied to every uploaded input
cleanupboolFalseDelete documents from server after extraction
on_progresscallableNoneCalled with each TaskExport or FailedResult as it completes

extract_folder() Parameters

ParameterTypeDefaultDescription
folderstr or PathrequiredDirectory to scan
patternstr"*"Glob pattern for file discovery (filtered by supported extensions)
template_idstrNoneTemplate ID (auto-detect if omitted)
splitboolFalseAuto-split multi-page documents
auto_approveboolTrueSet to False to require human review in the Suparse UI
pdf_passwordstrNonePassword applied to every input encrypted PDF
folder_idstrNoneFolder ID applied to every uploaded input
cleanupboolFalseDelete documents from server after extraction
on_progresscallableNoneCalled with each result as it completes