Metadata-Version: 2.4
Name: etld
Version: 1.0.0
Summary: Official Python SDK for the ETL-D API - Stateless Data Middleware for AI Agents.
Home-page: https://github.com/pablixnieto2/enrichermagic
Author: ETL-D Team
Author-email: hello@etl-d.net
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.25.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# ETL-D Python SDK

The ultimate AI-powered data normalization and enrichment engine. Clean, structure, and standardize chaotic global data (addresses, names, financial amounts, and dates) using our deterministic LLM-routing architecture.

## Installation

```bash
pip install etld
```

## Features
🌍 **Global Address Parsing**: Handles complex international formats, landmarks, PO Boxes, and transliteration (e.g., Arabic, Hangul, Cyrillic to Latin) with zero data loss.

👤 **Name Standardization**: Splits chaotic full names into distinct components (Prefix, First, Middle, Last, Suffix).

💰 **Amount Normalization**: Extracts clean numeric values and ISO currency codes from messy string inputs.

⚡ **Asynchronous Batch Processing**: Process 10,000+ records without blocking your server. The SDK handles the polling automatically.

🔍 **Accounting Mapping**: Automatically map transaction descriptions to standard accounting categories.

## Quick Start: The Magic Async Batch
Unlike traditional APIs that block your thread and timeout, ETL-D uses a queue-based system. You send thousands of records, and the SDK automatically polls the background worker until the job is done.

```python
from etld import ETLDClient

# Initialize the client
client = ETLDClient(api_key="YOUR_API_KEY")

# The SDK handles the task_id and polling automatically under the hood.
clean_addresses = client.batch_process(
    items=[
        "Calle 70A No. 11 - 12, Piso 4, Edificio Banco Ganadero, Bogotá", 
        "서울특별시 강남구 테헤란로 152 12층 우편번호 06236",
        "Hauptstraße 15a/b, Gebäude C, 3. OG, 10827 Berlin"
    ], 
    entity_type="address",
    context={"transliterate": True}
)

for result in clean_addresses:
    print(result['address_latin'])
```

## Synchronous Single Processing
If you only need to clean a single string in real-time, you can use the synchronous endpoints:

```python
# 1. Clean a Name
name = client.enrich_name("Dr. John Fitzgerald Kennedy Jr.")
print(name) # {'first_name': 'John', 'last_name': 'Kennedy', 'prefix': 'Dr.', ...}

# 2. Extract an Amount
amount = client.enrich_amount("Invoice total: USD 1,450.99 due tomorrow")
print(amount) # {'value': 1450.99, 'currency': 'USD'}

# 3. Categorize a Transaction
category = client.accounting_map("UBER *TRIP SAN FRANCISCO CA")
print(category) # {'category': 'Travel & Transportation', 'confidence': 0.98}
```

## Error Handling
The SDK provides custom exceptions to gracefully handle errors: `ETLDError`, `AuthenticationError`, `RateLimitError`, and `TaskFailedError`.

## Agentic Workflow: How to handle 402 errors and autonomous provisioning

ETL-D V1.0 introduces **Agentic Features** designed for autonomous systems that need to handle their own billing and provisioning.

### Handling 402 Payment Required

When an agent exhausts its credits, the SDK raises a `PaymentRequiredError` (HTTP 402). This error object contains everything an agent needs to recover:

```python
from etld.exceptions import PaymentRequiredError

try:
    client.enrich_address("...")
except PaymentRequiredError as e:
    print(f"Credits exhausted! {e.recovery_hint}")
    print(f"Please visit: {e.checkout_url}")
    # An autonomous agent can pass this URL to a human or use a provisioning session
```

### Autonomous Provisioning

Agents can trigger a provisioning session to refresh their credits:

```python
# 1. Start a provisioning session
session = client.create_provisioning_session()
poll_id = session['poll_id']

# 2. Poll for status (usually after redirecting a human to the checkout_url)
status = client.poll_provisioning_status(poll_id)
if status['status'] == 'completed':
    print("Provisioning successful!")
```
