Metadata-Version: 2.4
Name: fingest-ai
Version: 0.1.0
Summary: Python SDK for the Fingest document processing API
Project-URL: Homepage, https://fingestai.online
Project-URL: Documentation, https://fingestai.online/docs
Author: Fingest Team
License-Expression: MIT
License-File: LICENSE
Keywords: document,extraction,fingest,parsing,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.22; extra == 'dev'
Description-Content-Type: text/markdown

# Fingest Python SDK

A lightweight Python SDK for the [Fingest](https://fingestai.online) document processing API. Parse documents into markdown and extract structured data using AI.

## Installation

```bash
pip install fingest-ai
```

Or install from source:

```bash
git clone <repo-url>
cd fingest-sdk
pip install -e .
```

## Quick Start

```python
from fingest import FingestClient

client = FingestClient(api_key="fg_your_api_key")

# Parse a document → markdown
result = client.parse("./invoice.pdf")
print(result.markdown)

# Extract structured data
extracted = client.extract(
    result.markdown,
    schema={
        "invoice_number": "string",
        "date": "string",
        "total_amount": "number",
    }
)
print(extracted.data)

client.close()
```

## Context Manager

```python
with FingestClient(api_key="fg_...") as client:
    result = client.parse("./report.pdf")
    print(result.markdown)
```

## Async Support

```python
import asyncio
from fingest import AsyncFingestClient

async def main():
    async with AsyncFingestClient(api_key="fg_...") as client:
        result = await client.parse("./doc.pdf")
        extracted = await client.extract(result.markdown, schema={"title": "string"})
        print(extracted.data)

asyncio.run(main())
```

## API Reference

### `FingestClient` / `AsyncFingestClient`

```python
FingestClient(
    api_key: str,                                       # Required
    base_url: str = "https://api.fingestai.online/api/v1",  # Override for self-hosted
    timeout: float = 120.0,                             # Request timeout (seconds)
    max_retries: int = 3,                               # Retries for 429/5xx
)
```

### `client.parse(file_path, *, page_number=None) → ParseResult`

Parse a document file into markdown.

| Parameter | Type | Description |
|---|---|---|
| `file_path` | `str \| Path` | Path to PDF or image file |
| `page_number` | `int \| None` | Parse a single page (1-indexed) |

**Returns** `ParseResult(markdown: str, message: str)`

### `client.extract(markdown, schema, *, model="qwen3:0.6b") → ExtractResult`

Extract structured data from markdown using a JSON schema.

| Parameter | Type | Description |
|---|---|---|
| `markdown` | `str` | Markdown content (from `parse()`) |
| `schema` | `dict` | JSON schema describing desired output |
| `model` | `str` | Model to use (default: `"qwen3:0.6b"`) |

**Returns** `ExtractResult(data: dict, raw_response: dict)`

## Error Handling

```python
from fingest.exceptions import (
    FingestError,              # Base — catch-all
    AuthenticationError,       # 401/403 — invalid API key
    InsufficientCreditsError,  # 403 — no credits remaining
    RateLimitError,            # 429 — rate limited (has .retry_after)
    ValidationError,           # 400 — bad request
    ServerError,               # 5xx — server error
)

try:
    result = client.parse("doc.pdf")
except InsufficientCreditsError:
    print("Out of credits!")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except FingestError as e:
    print(f"Error [{e.status_code}]: {e.message}")
```

## Configuration

| Environment Variable | Description |
|---|---|
| `FINGEST_API_KEY` | API key (used by example scripts) |

## Examples

```bash
# Parse a document
FINGEST_API_KEY="fg_..." python examples/parse_document.py invoice.pdf

# Parse page 3 only
FINGEST_API_KEY="fg_..." python examples/parse_document.py report.pdf --page 3

# Extract structured data from a document
FINGEST_API_KEY="fg_..." python examples/extract_data.py invoice.pdf
```

## License

MIT
