> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reducto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK Overview

> Get started with the Reducto Python SDK

The Reducto Python SDK provides a type-safe interface to the Reducto API. It handles authentication, request formatting, and response parsing automatically.

***

## Quick Start

```python theme={null}
from pathlib import Path
from reducto import Reducto

# Initialize the client (reads REDUCTO_API_KEY from environment)
client = Reducto()

# Upload a document
upload = client.upload(file=Path("invoice.pdf"))

# Parse the document
result = client.parse.run(input=upload.file_id)

# Access the extracted content
for chunk in result.result.chunks:
    print(chunk.content)
```

***

## Key Features

<CardGroup cols={2}>
  <Card title="Type Safety" icon="shield-check">
    Full type hints and IDE autocomplete for all methods and responses using Pydantic models.
  </Card>

  <Card title="Simple API" icon="code">
    Intuitive method names that match the REST API endpoints.
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation">
    Clear exception hierarchy with helpful error messages and status codes.
  </Card>

  <Card title="Async Support" icon="clock">
    Both synchronous and asynchronous clients with the same interface.
  </Card>

  <Card title="Advanced Features" icon="wand-magic-sparkles">
    Raw responses, streaming, custom HTTP clients, and per-request options.
  </Card>

  <Card title="Automatic Retries" icon="repeat">
    Built-in retry logic with exponential backoff for transient errors.
  </Card>
</CardGroup>

***

## Installation

```bash theme={null}
pip install reductoai
```

Requires Python 3.9+. Upgrade with `pip install --upgrade reductoai`.

***

## Authentication

Set your API key as an environment variable:

```bash theme={null}
export REDUCTO_API_KEY="your_api_key_here"
```

The SDK reads it automatically:

```python theme={null}
from reducto import Reducto

client = Reducto()  # Reads REDUCTO_API_KEY from environment
```

Or pass it explicitly:

```python theme={null}
client = Reducto(api_key="your_api_key_here")
```

Get your API key from [Reducto Studio](https://studio.reducto.ai/) → API Keys.

***

## Core Methods

The SDK provides methods for all Reducto endpoints:

### Upload

Upload documents to Reducto's servers before processing:

```python theme={null}
upload = client.upload(file=Path("document.pdf"))
# Returns: Upload with file_id and presigned_url fields
```

<Card title="Upload Documentation" icon="upload" href="/sdk/python/upload">
  File upload options, size limits, and presigned URLs.
</Card>

### Parse

Convert documents into structured JSON with text, tables, and figures:

```python theme={null}
result = client.parse.run(input=upload.file_id)
# Returns: ParseResponse with chunks, blocks, and metadata
```

<Card title="Parse Documentation" icon="file-lines" href="/sdk/python/parse">
  Parse configuration, chunking options, and response structure.
</Card>

### Extract

Pull specific fields from documents using JSON schemas:

```python theme={null}
result = client.extract.run(
    input=upload.file_id,
    instructions={
        "schema": {
            "type": "object",
            "properties": {
                "invoice_number": {"type": "string"},
                "total": {"type": "number"}
            }
        }
    }
)
```

<Card title="Extract Documentation" icon="brackets-curly" href="/sdk/python/extract">
  Schema design, array extraction, and citations.
</Card>

### Split

Divide documents into sections based on content type:

```python theme={null}
result = client.split.run(
    input=upload.file_id,
    split_description=[
        {"name": "Introduction", "description": "The introduction section"},
        {"name": "Methodology", "description": "The methodology section"},
        {"name": "Results", "description": "The results section"}
    ]
)
# Returns: SplitResponse with splits array (name, pages, conf: "high" or "low")
```

<Card title="Split Documentation" icon="scissors" href="/sdk/python/split">
  Split configuration and section types.
</Card>

### Edit

Fill PDF forms and modify DOCX documents:

```python theme={null}
result = client.edit.run(
    document_url=upload.file_id,
    edit_instructions="Fill name with 'John Doe' and date with '12/25/2024'"
)
```

<Card title="Edit Documentation" icon="pen-to-square" href="/sdk/python/edit">
  Form schemas and document modification.
</Card>

### Pipeline

Run pre-configured workflows from Reducto Studio:

```python theme={null}
result = client.pipeline.run(
    input=upload.file_id,
    pipeline_id="your_pipeline_id"  # From Reducto Studio
)
```

<Card title="Pipeline Documentation" icon="diagram-project" href="/sdk/python/pipeline">
  Running studio-configured pipelines.
</Card>

***

## Async Client

The SDK provides an async client with the same interface:

```python theme={null}
import asyncio
from reducto import AsyncReducto

async def main():
    client = AsyncReducto()
    
    upload = await client.upload(file=Path("document.pdf"))
    result = await client.parse.run(input=upload.file_id)
    
    return result

# Run the async function
result = asyncio.run(main())
```

<Card title="Async Client Guide" icon="clock" href="/sdk/python/async">
  Concurrent processing, rate limiting, and batch operations.
</Card>

***

## Response Types

All SDK methods return strongly-typed response objects. The SDK uses Pydantic models for validation and type safety:

```python theme={null}
from reducto.types import ParseResponse

result: ParseResponse = client.parse.run(input=upload.file_id)

# Access typed fields
print(result.job_id)  # str
print(result.usage.num_pages)  # int
print(result.usage.credits)  # float
print(result.result.chunks)  # list[Chunk]
```

***

## Error Handling

The SDK raises specific exceptions for different error conditions:

```python theme={null}
from reducto import Reducto
import reducto

try:
    result = client.parse.run(input="invalid-file-id")
except reducto.APIConnectionError as e:
    print(f"Connection failed: {e}")
    print(e.__cause__)  # underlying exception
except reducto.RateLimitError as e:
    print(f"Rate limited: {e}")
except reducto.APIStatusError as e:
    print(f"API error: {e.status_code} - {e.response}")
```

<Card title="Error Handling Guide" icon="triangle-exclamation" href="/sdk/python/error-handling">
  Complete error handling reference with all exception types.
</Card>

***

## Advanced Features

### Raw Response Access

Access raw HTTP response data including headers:

```python theme={null}
response = client.parse.with_raw_response.run(input=upload.file_id)
print(response.headers.get('X-My-Header'))
parse_result = response.parse()  # Get the parsed object
```

### Streaming Responses

Stream large responses without loading everything into memory:

```python theme={null}
with client.parse.with_streaming_response.run(input=upload.file_id) as response:
    for line in response.iter_lines():
        print(line)
```

### Per-Request Options

Override client settings for individual requests:

```python theme={null}
# Custom timeout for this request
client.with_options(timeout=30.0).parse.run(input=upload.file_id)

# Custom retry settings
client.with_options(max_retries=5).parse.run(input=upload.file_id)
```

### Custom HTTP Client

Configure the underlying HTTP client:

```python theme={null}
import httpx
from reducto import Reducto, DefaultHttpxClient

client = Reducto(
    http_client=DefaultHttpxClient(
        proxy="http://my.proxy.com",
        timeout=httpx.Timeout(60.0),
    ),
)
```

***

## Next Steps

<Steps>
  <Step title="Get your API key">
    Create an API key in [Reducto Studio](https://studio.reducto.ai/) and set it as `REDUCTO_API_KEY`.
  </Step>

  <Step title="Try the quickstart">
    Run your first parse operation with the [quickstart example](/quickstart).
  </Step>

  <Step title="Explore the methods">
    Check out the [core methods documentation](/sdk/python/parse) for detailed usage.
  </Step>
</Steps>
