Metadata-Version: 2.4
Name: neivi-iqx-lookup
Version: 0.2.1
Summary: IQX Lookup API client for Python
Author-email: Neivi IT <dev@neivi.es>
License: Apache-2.0
Project-URL: Homepage, https://github.com/Neivi-IT/iqx-lookup-python
Project-URL: Repository, https://github.com/Neivi-IT/iqx-lookup-python
Keywords: lookup,validation,email,phone,iban,vat
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Dynamic: license-file

# neivi-iqx-lookup

Official Python client for the [IQX Lookup](https://api.iqxlookup.neivi.es) validation and geolocation APIs. Validate emails, phone numbers, VAT IDs, IBANs, BICs, DNS records, SSL certificates, passwords, and credit cards -- with zero external dependencies.

## Installation

```bash
pip install neivi-iqx-lookup
```

Or install from source:

```bash
git clone https://github.com/Neivi-IT/iqx-lookup-python.git
cd iqx-lookup-python
pip install .
```

## Quick Start

```python
from iqx_lookup import IqxLookup

client = IqxLookup(api_key="your-api-key")

# Validate an email address
email = client.validate_email("user@example.com")
print(email.valid_format)      # True
print(email.disposable_email)  # False

# Geolocate an IP address
geo = client.geolocate_ip("8.8.8.8")
print(geo.country_name)  # "United States"
print(geo.city_name)     # "Mountain View"

# Validate an IBAN
iban = client.validate_iban("DE89370400440532013000")
print(iban.valid)         # True
print(iban.bank_code)     # "37040044"
```

## API Reference

| Method | Description | Returns |
|--------|-------------|---------|
| `validate_email(address)` | Validate an email address (format, MX, disposable, role) | `EmailValidationResult` |
| `validate_phone(number, country_code=None)` | Validate a phone number | `PhoneValidationResult` |
| `geolocate_ip(ip=None)` | Geolocate an IP address (omit for caller's IP) | `IpGeolocation` |
| `validate_vat(country_code, number)` | Validate an EU VAT number via VIES | `VatValidationResult` |
| `parse_user_agent(ua=None)` | Parse a user-agent string (omit for SDK's own UA) | `UserAgentResult` |
| `validate_iban(iban)` | Validate an IBAN | `IbanValidationResult` |
| `validate_bic(bic)` | Validate a BIC/SWIFT code | `BicValidationResult` |
| `lookup_dns(domain, types=None)` | Look up DNS records (optionally filter by type, e.g. `"A,MX"`) | `DnsLookupResult` |
| `check_ssl(domain)` | Check an SSL/TLS certificate | `SslCertificateResult` |
| `analyze_password(password)` | Analyze password strength | `PasswordStrengthResult` |
| `validate_credit_card(card_number)` | Validate a credit card number | `CreditCardValidationResult` |
| `last_rate_limit_info` | Rate limit info from the most recent response (property) | `RateLimitInfo | None` |

## Configuration

```python
from iqx_lookup import IqxLookup

client = IqxLookup(api_key="your-api-key")
```

| Parameter | Default | Description |
|-----------|---------|-------------|
| `api_key` | *(required)* | API key sent as `X-Api-Key` header |
| `base_url` | `https://api.iqxlookup.neivi.es` | API base URL |
| `timeout` | `10` | Request timeout in seconds |

The base URL is resolved with priority: **explicit parameter > `LOOKUP_BASE_URL` env var > default**. Useful for local development:

```bash
export LOOKUP_BASE_URL=http://localhost:8081
```

## Error Handling

The SDK maps HTTP error responses to typed exceptions:

```python
from iqx_lookup import (
    IqxLookup,
    IqxLookupException,
    UnauthorizedException,
    ForbiddenException,
    NotFoundException,
    RateLimitException,
    ServiceUnavailableException,
)

client = IqxLookup(api_key="your-api-key")

try:
    result = client.validate_email("user@example.com")
except UnauthorizedException:
    print("Invalid API key")
except ForbiddenException:
    print("Access denied")
except NotFoundException:
    print("Resource not found")
except RateLimitException as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
    print(f"Limit: {e.limit}, Remaining: {e.remaining}, Reset: {e.reset}")
except ServiceUnavailableException:
    print("Service temporarily unavailable")
except IqxLookupException as e:
    print(f"API error {e.status_code}: {e.error_message}")
```

| Exception | HTTP Status | Attributes |
|-----------|-------------|------------|
| `UnauthorizedException` | 401 | `status_code`, `error_message` |
| `ForbiddenException` | 403 | `status_code`, `error_message` |
| `NotFoundException` | 404 | `status_code`, `error_message` |
| `RateLimitException` | 429 | `status_code`, `error_message`, `retry_after`, `limit`, `remaining`, `reset` |
| `ServiceUnavailableException` | 503 | `status_code`, `error_message` |
| `IqxLookupException` | any | `status_code`, `error_message` |

## Rate Limit Information

After each API call, rate limit headers are captured automatically:

```python
result = client.validate_email("user@example.com")

info = client.last_rate_limit_info
if info is not None:
    print(info.limit)      # e.g. 1000
    print(info.remaining)  # e.g. 999
    print(info.reset)      # Unix timestamp
```

## Requirements

- Python 3.9 or later
- No external dependencies (stdlib only: `urllib`, `json`, `dataclasses`)

## Testing

```bash
pip install pytest
pytest
```

## License

Apache License 2.0. See [LICENSE](LICENSE) for details.
