Skip to main content

BillionVerify Python SDK - Official SDK for BillionVerify email verification API

Project description

BillionVerify Python SDK

Official Python SDK for the BillionVerify email verification API.

PyPI version Python Versions

PyPI: https://pypi.org/project/billionverify/ Documentation: https://billionverify.com/docs

Installation

pip install billionverify

Quick Start

from billionverify import BillionVerify

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

# Verify a single email
result = client.verify("user@example.com")
print(result.status)  # 'valid', 'invalid', 'unknown', 'risky', 'disposable', 'catchall', 'role'
print(result.is_deliverable)  # True or False

Configuration

client = BillionVerify(
    api_key="your-api-key",        # Required
    base_url="https://api.billionverify.com/v1",  # Optional
    timeout=30.0,                   # Optional: Request timeout in seconds (default: 30)
    retries=3,                      # Optional: Number of retries (default: 3)
)

Single Email Verification

Uses the /verify/single endpoint:

result = client.verify(
    email="user@example.com",
    check_smtp=True,  # Optional: Perform SMTP verification (default: True)
    force_refresh=False,  # Optional: Bypass cache and force live verification (default: False)
    include_domain_reputation=False,  # Optional: Include domain reputation details (default: False)
)

# Flat response structure
print(result.email)              # 'user@example.com'
print(result.status)             # 'valid', 'invalid', 'unknown', 'risky', 'disposable', 'catchall', 'role'
print(result.score)              # 0.95
print(result.is_deliverable)     # True
print(result.is_disposable)      # False
print(result.is_catchall)        # False
print(result.is_role)            # False
print(result.is_free)            # True
print(result.domain)             # 'example.com'
print(result.reason)             # 'Valid email address'
print(result.check_smtp)         # True (whether SMTP was performed)
print(result.domain_suggestion)  # None or suggested domain correction
print(result.credits_used)       # 1

# Response metadata for audit logs and throttled runners
print(result.response_metadata.request_id)             # Server X-Request-ID
print(result.response_metadata.rate_limit_remaining)   # Remaining requests in current window

Bulk Email Verification (Synchronous)

Verify up to 50 emails synchronously using verify_bulk():

# Synchronous bulk verification (max 50 emails)
response = client.verify_bulk(
    emails=["user1@example.com", "user2@example.com", "user3@example.com"],
    check_smtp=True,  # Optional
)

# Returns BulkVerifyResponse directly
print(f"Total: {response.total_emails}")
print(f"Credits used: {response.credits_used}")

for result in response.results:
    print(f"{result.email}: {result.status}")
    print(f"  Deliverable: {result.is_deliverable}")
    print(f"  Disposable: {result.is_disposable}")
    print(f"  Catchall: {result.is_catchall}")
    print(f"  Role: {result.is_role}")

File Upload (Async Verification)

For large lists, use upload_file() for asynchronous file verification:

# Upload a file for async verification
task = client.upload_file(
    file_path="emails.csv",
    check_smtp=True,
    email_column="email",        # Column name for CSV files
    preserve_original=True,      # Keep original columns in results
)

print(f"Task ID: {task.task_id}")
print(f"Status: {task.status}")
print(f"Estimated count: {task.estimated_count}")

# Get task status (with optional long-polling)
status = client.get_file_task_status(
    task_id=task.task_id,
    timeout=60,  # Long-poll for up to 60 seconds (0-300)
)
print(f"Progress: {status.progress}%")
print(f"Processed: {status.processed_emails}/{status.total_emails}")

# Wait for completion (polling)
completed = client.wait_for_file_task(
    task_id=task.task_id,
    poll_interval=5.0,  # seconds
    max_wait=600.0,     # seconds
)

# Download results as CSV with optional filters
output_file = client.download_file_results(
    task_id=task.task_id,
    output_path="results.csv",
    valid=True,       # Include valid emails
    invalid=True,     # Include invalid emails
    unknown=True,     # Include unknown emails
    risky=True,       # Include risky emails
    disposable=True,  # Include disposable emails
    catchall=True,    # Include catch-all emails
    role=True,        # Include role-based emails
)
print(f"Results saved to: {output_file}")

Async Support

import asyncio
from billionverify import AsyncBillionVerify

async def main():
    async with AsyncBillionVerify(api_key="your-api-key") as client:
        # Single verification
        result = await client.verify("user@example.com")
        print(result.status)

        # Bulk verification
        response = await client.verify_bulk([
            "user1@example.com",
            "user2@example.com"
        ])
        for r in response.results:
            print(f"{r.email}: {r.status}")

asyncio.run(main())

Health Check

Check API health status (no authentication required):

health = client.health_check()
print(health.status)   # 'ok'
print(health.version)  # API version

Credits

credits = client.get_credits()
print(credits.credits_balance)   # Available credits
print(credits.credits_consumed)  # Credits used
print(credits.credits_added)     # Total credits added
print(credits.api_key_name)      # API key name

Webhooks

Webhooks support events: file.completed, file.failed

# Create a webhook
webhook = client.create_webhook(
    url="https://your-app.com/webhooks/billionverify",
    events=["file.completed", "file.failed"],
)
print(f"Webhook ID: {webhook.id}")
print(f"Secret: {webhook.secret}")  # Save this for signature verification

# List webhooks
webhooks = client.list_webhooks()
for wh in webhooks:
    print(f"{wh.id}: {wh.url}")

# Delete a webhook
client.delete_webhook(webhook.id)

# Verify webhook signature
from billionverify import BillionVerify

is_valid = BillionVerify.verify_webhook_signature(
    payload=raw_body,
    signature=signature_header,
    secret="your-webhook-secret",
)

Error Handling

from billionverify import (
    BillionVerify,
    BillionVerifyError,
    AuthenticationError,
    RateLimitError,
    ValidationError,
    InsufficientCreditsError,
    NotFoundError,
    TimeoutError,
)

try:
    result = client.verify("user@example.com")
except AuthenticationError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds")
    print(f"Request ID: {e.response_metadata.request_id}")
except ValidationError as e:
    print(f"Invalid input: {e.message}")
except InsufficientCreditsError:
    print("Not enough credits")
except NotFoundError:
    print("Resource not found")
except TimeoutError:
    print("Request timed out")
except BillionVerifyError as e:
    # Catch-all for anything else, including the response-shape codes below.
    print(f"{e.code}: {e.message}")

Malformed or empty server responses

The SDK never lets a malformed API reply leak out as a raw KeyError, TypeError, or json.JSONDecodeError. Empty bodies, null payloads, non-JSON content, and responses missing required fields are all surfaced as a typed BillionVerifyError with response_metadata populated, so you can recover and log the request ID:

error.code When it fires
EMPTY_RESPONSE 2xx with no body, or envelope {"data": null}
INVALID_RESPONSE Non-JSON body, wrong top-level shape, or missing fields
try:
    result = client.verify("user@example.com")
except BillionVerifyError as e:
    if e.code in ("EMPTY_RESPONSE", "INVALID_RESPONSE"):
        log.error("bad upstream reply", extra={
            "request_id": e.response_metadata.request_id,
            "status": e.response_metadata.status_code,
            "details": e.details,
        })
    raise

Context Manager

with BillionVerify(api_key="your-api-key") as client:
    result = client.verify("user@example.com")
    print(result.status)
# Connection is automatically closed

Type Hints

This SDK includes full type annotations for IDE support and type checking.

from billionverify import (
    VerificationResult,
    BulkVerifyResponse,
    FileUploadResponse,
    FileTaskStatus,
    CreditsResponse,
    VerificationStatus,
)

def process_result(result: VerificationResult) -> None:
    if result.status == "valid":
        print(f"Email {result.email} is valid")

    if result.is_deliverable and not result.is_disposable:
        print("Safe to send to this email")

Status Values

The verification status can be one of:

  • valid - Email is valid and deliverable
  • invalid - Email is invalid or does not exist
  • unknown - Could not determine status
  • risky - Email exists but may have delivery issues
  • disposable - Temporary/disposable email address
  • catchall - Domain accepts all emails (catch-all)
  • role - Role-based email (e.g., info@, support@)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

billionverify-1.2.1.tar.gz (25.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

billionverify-1.2.1-py3-none-any.whl (15.0 kB view details)

Uploaded Python 3

File details

Details for the file billionverify-1.2.1.tar.gz.

File metadata

  • Download URL: billionverify-1.2.1.tar.gz
  • Upload date:
  • Size: 25.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for billionverify-1.2.1.tar.gz
Algorithm Hash digest
SHA256 6b18c6aad645f4e048b241e438f52ab83d211dffc34173fe40e3696702783c18
MD5 51e8e4463e0007d8e273726183fcde10
BLAKE2b-256 d4838b2c739f220f5acd8952d5f5a26b803c944f092cf0d245201d3020728404

See more details on using hashes here.

File details

Details for the file billionverify-1.2.1-py3-none-any.whl.

File metadata

  • Download URL: billionverify-1.2.1-py3-none-any.whl
  • Upload date:
  • Size: 15.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for billionverify-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0aa65b7ccd3e110334c1ba72ee52bffbb65138968f4e5584b98caf56f99d6223
MD5 4dd5d30d534413af71f179ced1837905
BLAKE2b-256 5192d41533e31f8aaf724bd4b99224551efb136caffb597ad61ffc2c55567dcc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page