Skip to main content

Python SDK for ValidKit Email Verification API - Built for AI Agents

Project description

ValidKit Python SDK

PyPI version Python Versions License: MIT

Email validation for signup flows -- block junk without blocking test+staging@example.com. Sync and async clients, batch support up to 10K emails, automatic retries, and Pydantic models.

Installation

pip install validkit

Requires Python 3.8+.

Quick Start

from validkit import ValidKit

client = ValidKit("your_api_key")
result = client.verify("user@example.com")
print(result.v)  # True or False
client.close()

Or with a context manager:

from validkit import ValidKit

with ValidKit("your_api_key") as client:
    # Single email
    result = client.verify("user@example.com")
    print(result.v)

    # Batch -- compact format by default
    results = client.verify_batch([
        "alice@company.com",
        "bob@tempmail.com",
        "not-an-email",
    ])
    for email, r in results.items():
        print(f"{email}: valid={r.v}, disposable={r.d}")

Async usage

For high-throughput applications, use AsyncValidKit directly:

import asyncio
from validkit import AsyncValidKit

async def main():
    async with AsyncValidKit(api_key="your_api_key") as client:
        result = await client.verify_email("user@example.com")
        print(result.valid)

asyncio.run(main())

Features

  • Sync and async -- ValidKit for scripts, AsyncValidKit for high-throughput
  • Batch verification -- up to 10,000 emails per call, chunked automatically
  • Developer Pattern Intelligence -- understands test@, +addressing, disposable domains
  • Compact format -- token-efficient responses (v, d, r fields) enabled by default
  • Streaming -- async for results as they complete
  • Webhook delivery -- fire-and-forget async batch jobs with callback
  • Automatic retries -- exponential backoff, 3 retries default
  • Type-safe -- Pydantic v2 models with full type hints

Advanced Usage

Custom configuration

from validkit import AsyncValidKit, ValidKitConfig

config = ValidKitConfig(
    api_key="your_api_key",
    timeout=30,           # seconds
    max_retries=3,        # retry count
    max_connections=100,   # connection pool size
    rate_limit=10000,     # requests/min (None = unlimited)
    compact_format=True,  # smaller payloads
)

async with AsyncValidKit(config=config) as client:
    result = await client.verify_email("user@example.com")

Batch with progress tracking

def on_progress(processed, total):
    print(f"{processed}/{total} ({processed / total * 100:.1f}%)")

results = await client.verify_batch(
    emails,
    chunk_size=1000,
    progress_callback=on_progress,
)

Async batch with webhook

job = await client.verify_batch_async(
    emails=large_list,
    webhook_url="https://your-app.com/webhooks/validkit",
    webhook_headers={"Authorization": "Bearer token"},
)

# Poll until complete, or wait for webhook
job = await client.get_batch_status(job.id)
results = await client.get_batch_results(job.id)

# Cancel if needed
await client.cancel_batch(job.id)

Streaming

async for email, result in client.stream_verify(emails, batch_size=100):
    print(f"{email}: valid={result.v}")

Trace IDs

Attach a trace ID for cross-service debugging:

result = await client.verify_email("user@example.com", trace_id="req_abc123")

Error Handling

from validkit.exceptions import (
    ValidKitError,       # base -- catches everything
    ValidKitAPIError,    # API errors (4xx, 5xx)
    InvalidAPIKeyError,  # 401
    RateLimitError,      # 429, includes retry_after
    BatchSizeError,      # batch exceeds 10K
    TimeoutError,        # request timeout (inherits ValidKitError, not API)
    ConnectionError,     # network failure (inherits ValidKitError, not API)
)

try:
    result = await client.verify_email("user@example.com")
except RateLimitError as e:
    print(e.retry_after)  # seconds until retry
except InvalidAPIKeyError:
    print("Check your API key")
except ValidKitAPIError as e:
    print(e.message, e.status_code, e.code)
except ValidKitError as e:
    # Catches TimeoutError, ConnectionError, and any other non-API errors
    print(f"SDK error: {e}")

The SDK retries automatically on rate limits and transient errors (up to max_retries). Catch exceptions only if you need custom handling.

Compact Response Format

Default format. Smaller payloads, same information:

Field Type Meaning
v bool Email is valid
d bool | None Domain is disposable (None if not checked)
r str | None Reason (present only when invalid)
# Compact (default)
r = await client.verify_email("bad@example.com")
print(r.v, r.d, r.r)  # False, False, "invalid_format"

# Full format -- use when you need MX records, SMTP details
from validkit.models import ResponseFormat
full = await client.verify_email("user@example.com", format=ResponseFormat.FULL)
if full.mx:
    print(full.mx.records)  # ["mx1.example.com"]

Examples

See examples/:

Contributing

See CONTRIBUTING.md.

Support

Docs -- GitHub Issues -- developers@validkit.com

License

MIT -- see LICENSE.

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

validkit-1.2.0.tar.gz (20.5 kB view details)

Uploaded Source

Built Distribution

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

validkit-1.2.0-py3-none-any.whl (22.6 kB view details)

Uploaded Python 3

File details

Details for the file validkit-1.2.0.tar.gz.

File metadata

  • Download URL: validkit-1.2.0.tar.gz
  • Upload date:
  • Size: 20.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.6

File hashes

Hashes for validkit-1.2.0.tar.gz
Algorithm Hash digest
SHA256 97761d06dd09764589113ff3ac38a4c5e3c74fcc9034e539ae51a5d4594c7f03
MD5 a0c538ee8efcce2f5c9c23cbf252f934
BLAKE2b-256 94a60a7d669355774ac3700dbc42f6155f7281e57ddd24bf18d13a1b8ec02d01

See more details on using hashes here.

File details

Details for the file validkit-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: validkit-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.6

File hashes

Hashes for validkit-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 56152814cc8c73d2f0ae15fbcb54852eb51ca9a6a7b005ba409958ec8d1f8d48
MD5 d3557f5801fff769f6fbe194d1994f33
BLAKE2b-256 a2a3c18f4a2cdffb89522a8a482bee8a37d8cc4dc66557a8aaaedc3cc6ed7e4b

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