Skip to main content

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.

Metadata

Release files for validkit 1.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for validkit 1.2.1
File Size Uploaded
validkit-1.2.1.tar.gz 20.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for validkit 1.2.1
File Interpreter ABI Platform
validkit-1.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 43.1 kB

Release files / validkit-1.2.1.tar.gz

Download URL validkit-1.2.1.tar.gz
Size 20.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8853d09988c18273f1a71b92a7fc46682d5879ad822e5041f22c6f492a725688
BLAKE2b-256 checksum
How to use checksums
dcca48dedbac9eff816288de4d1bc1356b5fd49c6cddbd6a692efd199a940199
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.6

Release files / validkit-1.2.1-py3-none-any.whl

Download URL validkit-1.2.1-py3-none-any.whl
Size 22.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e57635e94654657ab4549b357ade9de4c710f2a83c53c72c8056f279975af2d4
BLAKE2b-256 checksum
How to use checksums
6f934bf17fe7cd713d407884d6283c8c1c546f1e8a755d63a75b2a5a519c0fb7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.6

Release history Release notifications | RSS feed

This release

1.2.1 This release

2 release files

1.2.0

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page