> ## 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.

# Upload

> Upload documents to Reducto using the Python SDK

The `upload` method uploads files to Reducto's servers and returns a file reference that you can use with other endpoints.

***

## Basic Usage

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

client = Reducto()

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

# Use the file_id in other operations
print(upload.file_id)  # "reducto://abc123def456.pdf"
```

***

## Method Signature

```python theme={null}
def upload(
    file: Path | bytes | tuple[str, bytes, str] | BinaryIO,
    extension: str | None = None
) -> Upload
```

### Parameters

| Parameter   | Type                                 | Required | Description                                                                                                            |
| ----------- | ------------------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `file`      | `Path \| bytes \| tuple \| BinaryIO` | Yes      | The file to upload. Can be a `Path` object, file-like object, bytes, or a tuple of `(filename, contents, media_type)`. |
| `extension` | `str \| None`                        | No       | Override the file extension (e.g., `".pdf"`). Useful when uploading bytes without filename context.                    |

### Returns

`Upload` with the following fields:

* `file_id` (str): The file reference to use with other endpoints (format: `reducto://...`)
* `presigned_url` (str | None): A presigned URL for the uploaded file (if applicable)

***

## Upload Options

### From File Path

The most common way to upload. Use `pathlib.Path`:

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

upload = client.upload(file=Path("invoice.pdf"))
```

### From File Object

```python theme={null}
with open("document.pdf", "rb") as f:
    upload = client.upload(file=f)
```

### From Bytes

When uploading raw bytes, use a tuple to provide filename and content type:

```python theme={null}
with open("document.pdf", "rb") as f:
    file_bytes = f.read()

upload = client.upload(
    file=("document.pdf", file_bytes, "application/pdf")
)
```

### With Extension Override

Use `extension` when the file type cannot be inferred:

```python theme={null}
upload = client.upload(
    file=Path("data_file"),
    extension=".pdf"
)
```

### From URL (Presigned URLs)

For large files, you can generate a presigned URL and pass it directly to parse/extract endpoints without uploading:

```python theme={null}
# For files > 100MB, use presigned URLs
# See: /upload/large-files for details

# You can pass presigned URLs directly to parse/extract
result = client.parse.run(input="https://bucket.s3.amazonaws.com/doc.pdf?X-Amz-...")
```

***

## Async Upload

The async client uses the same interface:

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

async def main():
    client = AsyncReducto()
    
    # If you pass a PathLike instance, the file contents will be read asynchronously automatically
    upload = await client.upload(file=Path("document.pdf"))
    return upload

result = asyncio.run(main())
```

***

## File Size Limits

* **Direct upload**: Up to 100MB
* **Presigned URLs**: Up to 5GB

For files larger than 100MB, use presigned URLs instead of the upload endpoint.

<Card title="Large File Upload Guide" icon="file-arrow-up" href="/upload/large-files">
  Complete guide to uploading large files using presigned URLs.
</Card>

***

## Supported File Types

The SDK accepts any file type that Reducto supports. Common formats include:

* **Documents**: PDF, DOCX, DOC, RTF
* **Images**: PNG, JPEG, TIFF, BMP
* **Spreadsheets**: XLSX, XLS, CSV
* **Presentations**: PPTX, PPT

<Card title="Supported File Formats" icon="file" href="/upload/overview#supported-file-types">
  Complete list of supported file formats.
</Card>

***

## Error Handling

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

try:
    upload = client.upload(file=Path("document.pdf"))
except reducto.APIConnectionError as e:
    print(f"Connection failed: {e}")
except reducto.APIStatusError as e:
    print(f"Upload failed: {e.status_code} - {e.response}")
```

Common errors:

* **File not found**: The file path doesn't exist
* **File too large**: File exceeds 100MB limit (use presigned URLs)
* **Invalid file type**: File format not supported
* **Network error**: Connection issues during upload

***

## Examples

### Upload and Parse

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

client = Reducto()

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

# Parse immediately
result = client.parse.run(input=upload.file_id)
```

### Batch Upload

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

client = Reducto()
files = ["doc1.pdf", "doc2.pdf", "doc3.pdf"]

uploads = []
for file_path in files:
    upload = client.upload(file=Path(file_path))
    uploads.append(upload)
    print(f"Uploaded {file_path}: {upload.file_id}")
```

### Upload with Extension Override

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

client = Reducto()

# Upload with explicit extension
upload = client.upload(
    file=Path("document_without_extension"),
    extension=".pdf"
)

print(upload.file_id)  # "reducto://..."
```

***

## Best Practices

<CardGroup cols={2}>
  <Card title="Use Path Objects" icon="file">
    Prefer `pathlib.Path` over string paths for better cross-platform compatibility.
  </Card>

  <Card title="Handle Large Files" icon="file-arrow-up">
    For files > 100MB, use presigned URLs instead of direct upload.
  </Card>

  <Card title="Reuse File IDs" icon="repeat">
    File IDs can be reused across multiple operations without re-uploading.
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation">
    Always wrap uploads in try/except blocks for production code.
  </Card>
</CardGroup>

***

## Next Steps

* Learn about [parsing documents](/sdk/python/parse) after upload
* Explore [extracting data](/sdk/python/extract) from uploaded files
* Check out [large file uploads](/upload/large-files) for files > 100MB
