Metadata-Version: 2.4
Name: apiddress
Version: 0.1.0
Summary: Official Python SDK for the APIddress email validation API
Project-URL: Homepage, https://api.apiddress.com
Author: APIddress
License-Expression: MIT
License-File: LICENSE
Keywords: apiddress,email,email-verification,validation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Communications :: Email
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# apiddress

Official Python SDK for the [APIddress](https://api.apiddress.com) email validation API.

- Zero runtime dependencies (stdlib `urllib` only)
- Python 3.9+, fully type-hinted, frozen dataclass responses
- Automatic retry with backoff on `429` and `5xx` (batch creation is never retried)

## Install

```bash
pip install apiddress
```

## Quickstart

```python
from apiddress import Client

client = Client("YOUR_API_KEY")

result = client.validate_email("ada@stripe.com")
print(result.status)  # "valid"
print(result.score)   # 0.98
```

## Configuration

```python
client = Client(
    "YOUR_API_KEY",
    base_url="https://api.apiddress.com",  # default
    timeout=10.0,                          # per-request timeout (seconds), default 10
    max_retries=2,                         # retries on 429/5xx, default 2
)
```

## Usage

### Validate one email

```python
result = client.validate_email(
    "john@company.com",
    check_smtp=False,        # default
    allow_role_based=True,   # server default
)
# result.status: "valid" | "invalid" | "risky" | "disposable" | "unknown"
# result.suggestion: "john@gmail.com" for typo-like addresses, else None
# result.checks: ValidationChecks(syntax, domain_exists, mx, smtp, disposable, ...)
```

A malformed value (e.g. `"not-an-email"`) is a verdict, not an error: you get
`status == "invalid"` with `reason == "invalid_syntax"`.

### Validate up to 100 emails synchronously

```python
response = client.validate_emails(["a@example.com", "b@example.com"])
print(response.count, [r.status for r in response.results])
```

### Batch jobs (up to 5000 emails)

```python
batch = client.create_batch(
    emails,
    callback_url="https://yourapp.com/webhooks/apiddress",  # optional
)

done = client.wait_for_batch(
    batch.batch_id,
    poll_interval=1.0,  # default
    timeout=60.0,       # default
)
print(done.status, len(done.results))

# Or poll yourself:
status = client.get_batch(batch.batch_id)
```

`wait_for_batch` returns the terminal state (`"completed"` or `"failed"`) —
check `status` before using `results`.

### Account

```python
profile = client.me()         # plan, limits, usage
usage = client.usage()        # current month
may = client.usage("2026-05") # specific month
health = client.health()      # no auth required
```

## Error handling

Every failed request raises an `APIddressError`:

```python
from apiddress import APIddressError, Client

try:
    client.validate_email("john@company.com")
except APIddressError as err:
    print(err.status, err.code, err.message, err.details)
    # 429 quota_exceeded "Monthly request limit exceeded." {"requests_used": ..., "requests_limit": ...}
```

| `status` | `code` |
| -------- | ------------------ |
| 400 | `invalid_request` |
| 401 | `unauthorized` |
| 404 | `not_found` |
| 429 | `quota_exceeded` |
| 500 | `internal_error` |
| 0 | `timeout` (request or `wait_for_batch` timeout) |

## Development

```bash
python3 -m venv .venv
.venv/bin/pip install -e . pytest

# Integration tests need a live backend:
APIDDRESS_BASE_URL=http://localhost:3000 APIDDRESS_API_KEY=test_key_local_dev \
  .venv/bin/pytest
```

## License

MIT
