Metadata-Version: 2.4
Name: revenuebase-sdk
Version: 0.2.0
Summary: Python SDK for the Revenuebase Email Verification and Company Resolver API.
Project-URL: Homepage, https://revenuebase.ai
Project-URL: Documentation, https://docs.revenuebase.ai
Project-URL: Repository, https://github.com/revenuebase/revenuebase-sdk
Project-URL: Bug Tracker, https://github.com/revenuebase/revenuebase-sdk/issues
Project-URL: Changelog, https://github.com/revenuebase/revenuebase-sdk/blob/main/CHANGELOG.md
License: MIT
License-File: LICENSE
Keywords: api,email,revenuebase,sdk,validation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
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: Typing :: Typed
Requires-Python: >=3.8
Requires-Dist: httpx>=0.24.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Requires-Dist: ruff>=0.4.0; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

# Revenuebase Python SDK

Python SDK for the [Revenuebase API](https://api.revenuebase.ai) — email verification, organization resolution, and batch job management.

## Requirements

- Python ≥ 3.8

## Install

```bash
pip install revenuebase-sdk
```

## Quickstart

```python
from revenuebase_sdk import RevenuebaseClient

client = RevenuebaseClient(api_key="your-api-key")
# Or set REVENUEBASE_API_KEY in your environment and call RevenuebaseClient()

# Verify a single email
result = client.email.verify(email="user@acme.com")
print(result.status)  # "Valid", "Invalid", or "Unknown"

# With full metadata
result = client.email.verify(email="user@acme.com", metadata=True)
print(result.mx_record_present, result.email_provider)

# Check your credit balance
usage = client.account.balance()
print(usage.credits)
```

## Authentication

Pass your API key via the `api_key` parameter or the `REVENUEBASE_API_KEY` environment variable. The key is sent as the `x-key` header on every request.

```bash
export REVENUEBASE_API_KEY="your-api-key"
```

## Resources

### `account`

| Method | Description |
|---|---|
| `balance()` | Get your remaining credit balance. |
| `rotate_api_key()` | Generate a new API key (invalidates the previous one immediately). |

### `email`

| Method | Description |
|---|---|
| `verify(*, email, metadata=False)` | Verify a single email. Returns `Valid`, `Invalid`, or `Unknown`. Rate limited to 5 req/s. |
| `batch_upload(*, file, filename, metadata=False)` | Upload a `.csv` or `.json` file for async batch verification. |

### `jobs`

| Method | Description |
|---|---|
| `list()` | List all active (queued or processing) batch jobs. |
| `get(*, process_id)` | Get the status of a batch job. |
| `cancel(*, process_id)` | Cancel a queued or in-progress batch job. |
| `download(*, process_id)` | Download the results of a completed job as bytes. |

### `organization`

| Method | Description |
|---|---|
| `resolve(*, company_name, result_count=3, ...)` | Match an organization name to verified records using semantic search. |
| `discover(*, keyword, result_count=1000, ...)` | Discover organizations matching a keyword or description. |

Both methods accept optional headquarter filters: `headquarters_country`, `headquarters_state`, `headquarters_city`, `headquarters_street`, `headquarters_zip`.

## Batch verification workflow

```python
import time

# 1. Upload the file
with open("emails.csv", "rb") as f:
    job = client.email.batch_upload(file=f, filename="emails.csv")

print(f"Job {job.process_id} queued")

# 2. Poll until complete
while True:
    status = client.jobs.get(process_id=job.process_id)
    print(status.current_status)
    if status.current_status in ("COMPLETED", "ERROR", "CANCELLED"):
        break
    time.sleep(5)

# 3. Download results
if status.current_status == "COMPLETED":
    data = client.jobs.download(process_id=job.process_id)
    with open("results.csv", "wb") as f:
        f.write(data)
```

## Organization resolution

```python
# Match by name
result = client.organization.resolve(
    company_name="Stripe",
    result_count=3,
    headquarters_country="US",
)
for org in result.companies:
    print(org.company_name, org.similar_score, org.headquarters_city)

# Discover by keyword
result = client.organization.discover(
    keyword="enterprise cybersecurity SaaS",
    result_count=100,
    headquarters_country="US",
)
```

## Async usage

```python
import asyncio
from revenuebase_sdk import AsyncRevenuebaseClient

async def main():
    async with AsyncRevenuebaseClient(api_key="your-api-key") as client:
        result = await client.email.verify(email="user@acme.com")
        print(result.status)

asyncio.run(main())
```

## Error handling

```python
from revenuebase_sdk import (
    AuthenticationError,
    BadRequestError,
    RateLimitError,
    APIConnectionError,
)

try:
    result = client.email.verify(email="user@acme.com")
except AuthenticationError:
    print("Invalid API key")
except BadRequestError as e:
    print(f"Bad request: {e.message}")
except RateLimitError:
    print("Rate limited — slow down requests")
except APIConnectionError as e:
    print(f"Network error: {e.message}")
```

## Per-request options

```python
# Override timeout for a single call
result = (
    client
    .with_options(timeout=5.0, max_retries=0)
    .email.verify(email="user@acme.com")
)
```

## Migrating from v1

All v1 endpoints are still accessible under `client.v1` but are **deprecated** and will be **retired on July 7, 2026**. Every call emits a `DeprecationWarning` at runtime.

| v1 (deprecated) | v2 replacement |
|---|---|
| `client.user_operations.get_credits()` | `client.account.balance()` |
| `client.user_operations.rotate_api_key()` | `client.account.rotate_api_key()` |
| `client.email_processing.validate_email(email=...)` | `client.email.verify(email=...)` |
| `client.email_processing.batch_upload(...)` | `client.email.batch_upload(...)` |
| `client.email_processing.get_batch_status(process_id=...)` | `client.jobs.get(process_id=...)` |
| `client.email_processing.list_queued()` | `client.jobs.list()` |
| `client.email_processing.cancel_batch(process_id=...)` | `client.jobs.cancel(process_id=...)` |
| `client.email_processing.download_batch(process_id=...)` | `client.jobs.download(process_id=...)` |
| `client.company_resolver.resolve(...)` | `client.organization.resolve(...)` |
| `client.company_resolver.discover(...)` | `client.organization.discover(...)` |

## Development

```bash
pip install -e ".[dev]"
pytest
mypy src
ruff check src
```
