Paravane Python Library
The Paravane Python library provides convenient access to the Paravane API from applications written in Python.
The first supported product API is smtpRS, Paravane's email risk intelligence API.
smtpRS helps score email addresses for onboarding, trust, review, abuse-prevention, and operations workflows.
This SDK is intentionally small at the start. It provides a stable client entrypoint,
request serialization, response helpers, structured errors, examples, tests, and packaging
conventions that can grow as Paravane adds more APIs.
Documentation · Installation · Quickstart · Examples · Development
Contents
- Documentation
- Installation
- Requirements
- Quickstart
- Usage
- smtpRS
- Configuration
- Per-request options
- Custom HTTP sessions
- Retries
- Idempotency
- Errors
- Responses and raw data
- Types
- Logging
- Examples
- Development
- Repository layout
- Versioning
- Security
- Support
Documentation
This README is the canonical SDK reference. The hosted Paravane documentation portal may temporarily show an access-status page during capacity pauses.
- Product docs: https://paravane.io/pages/docs/index.html
- smtpRS docs: https://paravane.io/pages/docs/smtprs/index.html
- Authentication: https://paravane.io/pages/docs/smtprs/authentication.html
- Analyse endpoint: https://paravane.io/pages/docs/smtprs/analyse.html
- Plans and limits: https://paravane.io/pages/docs/smtprs/plans-limits.html
Installation
Install the latest release from PyPI:
python -m pip install --upgrade paravane
To install the current development version directly from GitHub:
python -m pip install "git+https://github.com/paravaneai/paravane-python.git"
For local development:
git clone git@github.com:paravaneai/paravane-python.git
cd paravane-python
python -m pip install -e ".[dev]"
Requirements
Python 3.10 or newer.
Runtime dependency:
requests>=2.33.0
Development dependencies are installed with:
python -m pip install -e ".[dev]"
Quickstart
Create an API key from the Paravane API keys page,
copy it when it is shown, and store it in your server-side environment. The production client
already defaults to https://api.paravane.io; do not append /v1 to the base URL.
Set your API key:
export PARAVANE_API_KEY="pvn_live_..."
On Windows PowerShell:
$env:PARAVANE_API_KEY = "pvn_live_..."
Call smtpRS:
from paravane import ParavaneClient
client = ParavaneClient()
result = client.smtprs.analyze("alice@example.com")
print(result.decision)
print(result.overall_risk)
print(result.credits_charged)
The SDK method is named analyze(...) for Python readability. The HTTP API endpoint remains:
POST /v1/analyse
Usage
Create a client with an API key:
from paravane import ParavaneClient
client = ParavaneClient(api_key="pvn_live_...")
Or use PARAVANE_API_KEY:
from paravane import ParavaneClient
client = ParavaneClient()
Run an email risk analysis:
result = client.smtprs.analyze("person@example.com")
if result.decision == "allow":
print("Continue")
else:
print("Review or block")
Inspect the normalized response:
print(result.email)
print(result.decision)
print(result.overall_risk)
print(result.analysis_profile)
print(result.credit_cost)
print(result.usage)
Access the original API response:
raw = result.to_dict()
print(raw)
smtpRS
smtpRS is available through:
client.smtprs
Analysis profiles
smtpRS provides named profiles so applications can choose the appropriate balance of coverage, latency, and credit usage without configuring individual checks.
| Profile | Credits | Availability | Intended use |
|---|---|---|---|
quick |
1 | All plans | Lightweight screening; this is the default. |
standard |
3 | Basic and above | Broader passive analysis. |
adaptive |
5 | Pro and above | Adds checks when the initial result needs more context. |
deep |
5 | Pro and above | Comprehensive analysis without catch-all probing. |
catch_all |
20 | Enterprise or entitled accounts | Deep analysis with catch-all probing. |
Use the default quick profile:
result = client.smtprs.analyze("person@example.com")
Or request another profile available to your account:
result = client.smtprs.analyze(
"person@example.com",
profile="standard",
)
Profile availability is enforced by the API. Requesting a profile that is not included
with the current plan raises PermissionDeniedError.
Legacy mode flags
The older disposable_only, strict_disposable, guess, and run_catch_all arguments
remain available for compatibility. New integrations should use profile instead. Do not
combine profile with an enabled legacy mode flag.
For example, replace:
result = client.smtprs.analyze(
"person@example.com",
strict_disposable=True,
)
with:
result = client.smtprs.analyze(
"person@example.com",
profile="deep",
)
Low-latency posture
Use the fast flag when your workflow favors lower latency:
result = client.smtprs.analyze(
"person@example.com",
fast=True,
)
Company Validity Beta
Paid smtpRS callers can explicitly request the optional Company Validity Beta:
result = client.smtprs.analyze(
"person@example.com",
profile="standard",
company_validity_beta=True,
)
beta = result.company_validity_beta
if beta is not None:
print(beta.status) # "beta"
print(beta.requested) # True
print(beta.enabled) # True when the feature was active for this request
print(beta.notes)
signal = result.domain_signal
if signal is not None:
print(signal.domain_status)
print(signal.mail_status)
print(signal.company_valid)
The option is omitted by default, so existing calls retain their current
behavior. It is available only to paid smtpRS plans and provides additive
company-domain context rather than an allowlist. It currently adds no credits
beyond the selected profile. Free-plan requests that explicitly enable it
receive PermissionDeniedError. Because the response contract is beta,
applications can use result.to_dict() to retain access to newly added fields.
Configuration
from paravane import ParavaneClient
client = ParavaneClient(
api_key="pvn_live_...",
base_url="https://api.paravane.io",
timeout=20.0,
max_network_retries=1,
)
Environment variables:
| Name | Purpose | Default |
|---|---|---|
PARAVANE_API_KEY |
API key used for requests. | None |
PARAVANE_BASE_URL |
API base URL. | https://api.paravane.io |
Most applications should leave PARAVANE_BASE_URL unset. If an approved alternate endpoint is
required, provide only its scheme and host; the SDK adds /v1/analyse itself.
Per-request options
You can set a timeout for one request:
result = client.smtprs.analyze(
"person@example.com",
timeout=5.0,
)
You can pass an idempotency key:
result = client.smtprs.analyze(
"person@example.com",
idempotency_key="signup-check-123",
)
You can pass future or preview query parameters without waiting for a new SDK release:
result = client.smtprs.analyze(
"person@example.com",
extra_params={"preview_flag": "enabled"},
)
Custom HTTP sessions
The SDK uses requests by default. If your environment needs custom connection pooling, proxies, certificates, or adapters, pass a configured requests.Session:
import requests
from paravane import ParavaneClient
session = requests.Session()
session.proxies.update(
{
"https": "https://proxy.example.com:8443",
}
)
client = ParavaneClient(
api_key="pvn_live_...",
session=session,
)
Retries
By default, the SDK does not retry network calls:
client = ParavaneClient(max_network_retries=0)
Enable limited retries for transient network failures, 429 rate limits, and 5xx API responses:
client = ParavaneClient(max_network_retries=2)
Billable POST requests are retried only when you supply an idempotency key. Without one,
analyze makes one attempt even when max_network_retries is greater than zero:
result = client.smtprs.analyze(
"person@example.com",
idempotency_key="customer-signup-456",
)
Idempotency
The SDK accepts an idempotency_key and sends it as:
Idempotency-Key: your-key
Use stable keys for requests that your application may retry after timeouts or transient failures.
Errors
Unsuccessful requests raise structured exceptions from paravane.errors.
from paravane import (
AuthenticationError,
ParavaneClient,
QuotaExceededError,
RateLimitError,
ValidationError,
)
client = ParavaneClient()
try:
result = client.smtprs.analyze("person@example.com")
except AuthenticationError:
print("Check your API key.")
except QuotaExceededError:
print("The workspace has exhausted its available credits.")
except RateLimitError:
print("Slow down and retry later.")
except ValidationError as exc:
print("Request was invalid:", exc)
Exception classes:
| Class | Typical cause |
|---|---|
ConfigurationError |
Missing API key or invalid client setup. |
APIConnectionError |
Network failure, timeout, DNS failure, or connection error. |
APIError |
Generic non-success API response. |
AuthenticationError |
Missing, invalid, or revoked API key. |
PermissionDeniedError |
API key lacks access to the requested resource. |
ValidationError |
Invalid request payload or parameters. |
QuotaExceededError |
Plan or credit quota has been exhausted. |
RateLimitError |
Too many requests. |
API errors include useful details when available:
try:
client.smtprs.analyze("not-an-email")
except ValidationError as exc:
print(exc.status_code)
print(exc.code)
print(exc.request_id)
print(exc.response)
Responses and raw data
The SDK returns SmtpRsAnalysis for smtpRS analysis requests.
result = client.smtprs.analyze("person@example.com")
Common fields:
| Field | Description |
|---|---|
email |
Email address represented by the response, when returned by the API. |
decision |
Customer-facing decision or recommendation, when returned by the API. |
overall_risk |
Overall risk score, when returned by the API. |
tier |
Workspace/API-key tier reflected by the response. |
analysis_profile |
Analysis path used by the API. |
response_profile |
Response shape, such as summary/full. |
credit_cost |
Planned credit cost for the selected profile. |
credits_charged |
Credits recorded for the request, when returned. |
company_validity_beta |
Typed beta status, opt-in state, availability, credit cost, and API notes. |
domain_signal |
Typed domain, mail, and company-context facts when returned. |
reasons |
Human-readable reason strings, when returned. |
usage |
Usage/quota snapshot, when returned. |
raw |
Original API payload. |
To avoid losing fields added by the API before the SDK is updated, the full payload is always preserved:
raw = result.to_dict()
print(raw["usage"])
Types
This package includes inline type hints and ships a py.typed marker.
The response helper is a dataclass:
from paravane import SmtpRsAnalysis
def handle_result(result: SmtpRsAnalysis) -> None:
print(result.decision)
signal = result.domain_signal
if signal is not None:
print(signal.mail_capable)
Type hints are intended to describe stable SDK behavior. The raw API response may include additional fields that are not represented as first-class dataclass attributes yet.
Logging
The SDK does not install or configure logging handlers. Applications should configure logging at the application boundary.
For now, request failures are surfaced through exceptions. If you need detailed HTTP logging during development, configure your own requests.Session or enable logging in your HTTP stack.
Examples
This repository includes small examples:
examples/basic_analyze.py
examples/strict_analyze.py
examples/batch_csv.py
Run one with:
PARAVANE_API_KEY="pvn_live_..." python examples/basic_analyze.py
Windows PowerShell:
$env:PARAVANE_API_KEY = "pvn_live_..."
python examples/basic_analyze.py
Development
Create an environment:
python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
Windows PowerShell:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
Run tests:
pytest
Run lint:
ruff check .
Build the package:
python -m build
Recommended pre-commit check:
pytest && ruff check . && python -m build
Repository layout
paravane-python/
.github/workflows/ GitHub Actions checks
examples/ Small runnable examples
src/paravane/ SDK package source
tests/ Unit tests
pyproject.toml Packaging metadata and tool config
RELEASING.md Maintainer release process
Versioning
Current package version:
1.0.2
Security
Do not put API keys in source code, client-side apps, mobile apps, screenshots, or public repositories.
Recommended handling:
- load API keys from environment variables or a secret manager
- rotate keys if they are exposed
- create separate keys for development, staging, and production
- revoke keys that are no longer needed
Report suspected vulnerabilities privately:
security@paravane.io
Support
For product or account support:
contact@paravane.io
For security reports:
security@paravane.io
Release files for paravane 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| paravane-1.0.2.tar.gz | 22.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| paravane-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.7 kB
Release files / paravane-1.0.2.tar.gz
| Download URL | paravane-1.0.2.tar.gz |
|---|---|
| Size | 22.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b09428ee72dc066a1e1f77d6917cf09c9e922aedff69408a328a3d33acec2110
|
|
BLAKE2b-256 checksum How to use checksums |
08bff3b788322bb9c0513ca50e5455b76eb93e2a0c57c77aa4ef959126dfb8a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 19, 2026.
Transparency logRelease files / paravane-1.0.2-py3-none-any.whl
| Download URL | paravane-1.0.2-py3-none-any.whl |
|---|---|
| Size | 16.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5601c1de1d467c721e6cf7fd9ad1a0f6ffa38e0b5fcc6e76233820e64e0cd988
|
|
BLAKE2b-256 checksum How to use checksums |
19b14b37790e259e7c8c3c87611dcd33853f82f9dd2e7a8ca7c38ebfb006e507
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 19, 2026.
Transparency log