Skip to main content

unstructured-transform-client

Python client for the Unstructured Transform v2 API. One document in, structured output back.

from unstructured_transform_client import TransformClient

with TransformClient() as client, open("invoice.pdf", "rb") as f:
    result = client.parse.run(input=f)
    print(result.markdown)

Install

pip install unstructured-transform-client
# export UNSTRUCTURED_API_KEY="your-key-here"

The three flows

Parse a document.

with open("invoice.pdf", "rb") as f:
    result = client.parse.run(input=f)

A path works too, and closes itself:

result = client.parse.run(input="invoice.pdf")

Extract fields from a document in one call. Supplying a schema adds an extraction step to the same job, so the document is parsed once.

result = client.parse.run(
    input="invoice.pdf",
    schema={
        "type": "object",
        "properties": {"invoice_number": {"type": "string"}},
        "required": ["invoice_number"],
        "additionalProperties": False,
    },
)
print(result.extracted_data)

The engine requires required to list every key in properties and additionalProperties to be false. That constraint is not expressible in OpenAPI, so it is not enforced by the types — a schema without it is rejected at request time rather than by your editor.

Extract against a parse you already have. The document is not parsed again.

extraction = client.extract.run(parse_id=result.id, schema=schema)

An extraction is a job like any other. If that call returns an accepted job, follow it to a terminal status before reading result.extracted_data. A single jobs.get right after submitting can still land on queued or processing, with result still None:

import time

accepted = client.extract.run(parse_id=result.id, schema=schema, wait_seconds=0)
deadline = time.monotonic() + 300
job = client.jobs.get(accepted.id)
while job.status in ("queued", "processing"):
    if time.monotonic() >= deadline:
        raise TimeoutError(f"extraction {accepted.id} is still {job.status}")
    time.sleep(2)
    job = client.jobs.get(accepted.id)
print(job.status, job.result.extracted_data if job.result else None)

Give the wait a bound, as above. A job can stay queued or processing, and a loop without a deadline polls forever. jobs.stream is the alternative: it ends on its own at the terminal event, and is shown under Long-running jobs below.

Long-running jobs

Send wait_seconds to block, or wait_seconds=0 to get a job handle back immediately and follow it yourself.

job = client.parse.run(input="contract.pdf", wait_seconds=0)

for event in client.jobs.stream(job.id):
    print(event.event, event.data)
    if event.is_terminal:
        break

stream yields status events as the job progresses, then exactly one terminal result or error. Polling with client.jobs.get(job.id) returns the same resource if you would rather not hold a connection open.

To scan jobs across every page, use the cursor-following iterator. list() still returns one page when you need page boundaries; its total_count is the number of matching jobs across all pages, or None when the service cannot count. Both take status and operation ("parse" or "extract") filters. Jobs whose result has expired are not listed.

for job in client.jobs.iterate(status="completed", operation="parse"):
    print(job.id, job.status)

Retries

Retries are enabled by default for transient failures. Configure them per client, or pass retries=None to disable them:

from unstructured_transform_client import RetryConfig, TransformClient

client = TransformClient(
    retries=RetryConfig(max_attempts=5, max_elapsed_seconds=20),
)
without_retries = TransformClient(retries=None)

GET and DELETE are retried on any transient failure. Everything else — a parse, extract or upload submit, and any other write — is retried only when the failure proves the request never reached the service, such as a refused connection or a DNS failure. A read timeout or a 5xx on a write is not retried, because the service may have acted on it already and a second attempt could duplicate the effect.

Credentials

Set UNSTRUCTURED_API_KEY for the default API-key authentication path:

export UNSTRUCTURED_API_KEY="your-key-here"

Then create the client without passing a key:

client = TransformClient()

An explicit api_key= argument takes precedence over the environment variable. For bearer authentication, pass bearer_token= explicitly. If neither an explicit credential nor UNSTRUCTURED_API_KEY is available, construction raises an error naming UNSTRUCTURED_API_KEY.

client = TransformClient(api_key="...")

What this client tells us about your environment

Every request carries a User-Agent and a set of X-Unstructured-Client-* headers: this package's version, the language, your Python version, your OS family and release, and your CPU architecture. That is what makes a support conversation start from facts.

It never sends your hostname, username, working directory, arbitrary environment variables, IP address, or anything read from your documents. When no explicit credential is provided, UNSTRUCTURED_API_KEY is used only as the API key sent for authentication.

To send only the User-Agent:

client = TransformClient(send_host_headers=False)

or set UNSTRUCTURED_TRANSFORM_DISABLE_HOST_HEADERS=1.

Versioning

This client's version tracks the Transform API revision it was generated from, so 0.18.x of this package describes 0.18.x of the API.

Anything importable from unstructured_transform_client is public. Modules with a leading underscore are not — _generated in particular is produced from the OpenAPI contract at build time and may be reorganised without notice.

Metadata

Release files for unstructured-transform-client 0.18.23

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for unstructured-transform-client 0.18.23
File Interpreter ABI Platform
unstructured_transform_client-0.18.23-py3-none-any.whl Python 3 none any Details

Release files / unstructured_transform_client-0.18.23-py3-none-any.whl

Download URL unstructured_transform_client-0.18.23-py3-none-any.whl
Size 93.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b3884e16f2a13311a01ecb23a683b2c9f0f8e17a1f05634c8ecd51733c3345f5
BLAKE2b-256 checksum
How to use checksums
a4b53ecc55f84e106e7912593211fba92cd0fb9351324108fcaa83d2b9ae29a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

Release history Release notifications | RSS feed

0.18.24

1 release file

This release

0.18.23 This release

1 release file

0.18.22

1 release file

0.18.21

1 release file

0.18.20

1 release file

0.18.18

1 release file

0.18.17

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page