Getting Started with checkboxHQ API Suite

checkboxHQ Team
email-verification crm-integration lead-validation form-spam-prevention b2b-marketing marketing-automation contact-form api-integration

checkboxHQ is an email verification API suite that helps you detect disposable, public, and invalid email addresses. This guide will walk you through integrating checkboxHQ into your application.

Overview

checkboxHQ provides three specialized verification endpoints:

  1. Disposable Email Verification - Detect temporary/disposable email addresses (1 credit)
  2. DNS Verification - Check if domains have valid MX and A records (2 credits)
  3. Public Provider Verification - Identify emails from well-known providers like Gmail, Yahoo, etc. (1 credit)

Each verification type serves different use cases and consumes credits from your quota based on the depth of validation performed.

Quick Start

1. Create Your Account

Register for a checkboxHQ account at https://checkboxhq.com/register.

2. Generate Your API Token

After logging in, you need to create an API token to authenticate your requests.

Using the Dashboard: Navigate to your dashboard and create a new API token with a descriptive name.

Using the API:

Terminal window
# First, login to get your access token
curl -X POST "https://api.checkboxhq.com/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "your-password"
}'
# Response includes access_token
# {
# "access_token": "eyJhbGc...",
# "token_type": "bearer"
# }
# Then create an API token
curl -X POST "https://api.checkboxhq.com/api/v1/tokens/" \
-H "Authorization: Bearer eyJhbGc..." \
-H "Content-Type: application/json" \
-d '{
"name": "Production API Token"
}'
# Response includes the API token
# {
# "id": 1,
# "name": "Production API Token",
# "token": "cbhq_abc123...",
# "is_active": true,
# "created_at": "2024-01-15T10:30:00Z",
# "last_used_at": null
# }

Security Note: Save the token from the response immediately - you won’t be able to see it again. Store it securely in your environment variables.

3. Make Your First Verification

checkboxHQ offers three verification endpoints. Choose based on your needs:

Verification Endpoints

1. Disposable Email Verification (1 Credit)

Detects if an email domain is from a disposable/temporary email service. Use this to block throwaway emails during registration.

Endpoint: POST /api/v1/verify_disposable/

Example Request:

Terminal window
curl -X POST "https://api.checkboxhq.com/api/v1/verify_disposable/" \
-H "x-api-key: cbhq_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]"
}'

Response:

{
"email": "[email protected]",
"is_disposable": true,
"is_valid_format": true,
"domain": "tempmail.com",
"provider": null
}

Response Fields:

  • is_disposable - Whether the domain is a known disposable email provider
  • is_valid_format - Whether the email format is syntactically valid
  • domain - The extracted domain from the email
  • provider - Email provider name if recognized (null otherwise)

Python Example:

import requests
def verify_disposable(email, api_key):
"""Check if email is from a disposable provider"""
response = requests.post(
"https://api.checkboxhq.com/api/v1/verify_disposable/",
headers={
"x-api-key": api_key,
"Content-Type": "application/json"
},
json={"email": email}
)
return response.json()
result = verify_disposable("[email protected]", "cbhq_your_token")
print(f"Disposable: {result['is_disposable']}")

2. DNS Verification (2 Credits)

Verifies that the email domain has valid MX records (can receive email) and A records (has an IP address). This is a deeper validation that confirms the domain is properly configured.

Endpoint: POST /api/v1/verify_dns/

Example Request:

Terminal window
curl -X POST "https://api.checkboxhq.com/api/v1/verify_dns/" \
-H "x-api-key: cbhq_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]"
}'

Response:

{
"email": "[email protected]",
"has_mx_record": true,
"mx_records": [
"mx1.example.com",
"mx2.example.com"
],
"has_a_record": true,
"a_records": [
"93.184.216.34"
],
"provider": "Example Provider"
}

Response Fields:

  • has_mx_record - Whether the domain has MX records configured
  • mx_records - List of MX record hostnames (null if none found)
  • has_a_record - Whether the domain has A records
  • a_records - List of IP addresses (null if none found)
  • provider - Email provider name if recognized

Python Example:

def verify_dns(email, api_key):
"""Verify email domain DNS configuration"""
response = requests.post(
"https://api.checkboxhq.com/api/v1/verify_dns/",
headers={
"x-api-key": api_key,
"Content-Type": "application/json"
},
json={"email": email}
)
return response.json()
result = verify_dns("[email protected]", "cbhq_your_token")
if result['has_mx_record'] and result['has_a_record']:
print("Domain is properly configured for email")
else:
print("Domain cannot receive email")

3. Public Provider Verification (1 Credit)

Identifies if an email is from a well-known public email service (Gmail, Yahoo, Outlook, etc.). Useful for identifying personal vs. business emails.

Endpoint: POST /api/v1/verify_public_provider/

Example Request:

Terminal window
curl -X POST "https://api.checkboxhq.com/api/v1/verify_public_provider/" \
-H "x-api-key: cbhq_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]"
}'

Response:

{
"email": "[email protected]",
"is_public_provider": true,
"provider": "Gmail"
}

Response Fields:

  • is_public_provider - Whether the email is from a known public provider
  • provider - Name of the public provider (null if not recognized)

Python Example:

def verify_public_provider(email, api_key):
"""Check if email is from a public provider"""
response = requests.post(
"https://api.checkboxhq.com/api/v1/verify_public_provider/",
headers={
"x-api-key": api_key,
"Content-Type": "application/json"
},
json={"email": email}
)
return response.json()
result = verify_public_provider("[email protected]", "cbhq_your_token")
if result['is_public_provider']:
print(f"Personal email from {result['provider']}")
else:
print("Business or private email domain")

Production Integration Patterns

Comprehensive Email Validation Function

Combine multiple endpoints for thorough validation:

import requests
from typing import Dict, Tuple
class CheckboxHQClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.checkboxhq.com"
self.headers = {
"x-api-key": api_key,
"Content-Type": "application/json"
}
def verify_disposable(self, email: str) -> Dict:
"""Check if email is disposable (1 credit)"""
response = requests.post(
f"{self.base_url}/api/v1/verify_disposable/",
headers=self.headers,
json={"email": email},
timeout=10
)
response.raise_for_status()
return response.json()
def verify_dns(self, email: str) -> Dict:
"""Verify DNS records (2 credits)"""
response = requests.post(
f"{self.base_url}/api/v1/verify_dns/",
headers=self.headers,
json={"email": email},
timeout=10
)
response.raise_for_status()
return response.json()
def verify_public_provider(self, email: str) -> Dict:
"""Check if public provider (1 credit)"""
response = requests.post(
f"{self.base_url}/api/v1/verify_public_provider/",
headers=self.headers,
json={"email": email},
timeout=10
)
response.raise_for_status()
return response.json()
def comprehensive_verify(self, email: str,
check_disposable: bool = True,
check_dns: bool = True,
check_public: bool = False) -> Tuple[bool, Dict, str]:
"""
Comprehensive email validation with configurable checks.
Returns: (is_valid, results_dict, reason_if_invalid)
"""
results = {"email": email}
try:
# Basic disposable check (1 credit)
if check_disposable:
disp_result = self.verify_disposable(email)
results['disposable_check'] = disp_result
if not disp_result['is_valid_format']:
return (False, results, "Invalid email format")
if disp_result['is_disposable']:
return (False, results, "Disposable email not allowed")
# DNS validation (2 credits)
if check_dns:
dns_result = self.verify_dns(email)
results['dns_check'] = dns_result
if not dns_result['has_mx_record']:
return (False, results, "Domain cannot receive email (no MX records)")
if not dns_result['has_a_record']:
return (False, results, "Domain does not exist (no A records)")
# Public provider check (1 credit)
if check_public:
public_result = self.verify_public_provider(email)
results['public_check'] = public_result
return (True, results, "")
except requests.exceptions.RequestException as e:
return (False, results, f"Verification failed: {str(e)}")
# Usage
client = CheckboxHQClient("cbhq_your_token")
# Quick validation (3 credits total: 1 for disposable + 2 for DNS)
is_valid, results, reason = client.comprehensive_verify("[email protected]")
if is_valid:
print("Email passed all validations")
else:
print(f"Email rejected: {reason}")
# Custom validation (only check disposable - 1 credit)
is_valid, results, reason = client.comprehensive_verify(
check_dns=False,
check_public=False
)

Error Handling

Always implement proper error handling:

def safe_verify(email, api_key):
"""Verify email with comprehensive error handling"""
try:
response = requests.post(
"https://api.checkboxhq.com/api/v1/verify_disposable/",
headers={
"x-api-key": api_key,
"Content-Type": "application/json"
},
json={"email": email},
timeout=10
)
# Handle specific HTTP errors
if response.status_code == 401:
return {"error": "Invalid API key"}
elif response.status_code == 403:
return {"error": "API key revoked or inactive"}
elif response.status_code == 429:
return {"error": "Rate limit exceeded"}
elif response.status_code == 402:
return {"error": "Insufficient credits"}
elif response.status_code == 422:
error_detail = response.json()
return {"error": f"Validation error: {error_detail}"}
response.raise_for_status()
return response.json()
except requests.exceptions.Timeout:
return {"error": "Request timeout"}
except requests.exceptions.ConnectionError:
return {"error": "Connection failed"}
except requests.exceptions.RequestException as e:
return {"error": f"Request failed: {str(e)}"}

Usage Monitoring

Monitor your credit usage to avoid unexpected service interruptions:

def get_usage_stats(access_token: str) -> Dict:
"""Get current billing period usage statistics"""
response = requests.get(
"https://api.checkboxhq.com/api/v1/billing/usage",
headers={"Authorization": f"Bearer {access_token}"}
)
response.raise_for_status()
return response.json()
# Example usage
usage = get_usage_stats("your_jwt_access_token")
print(f"Credits used: {usage['credits_used']} / {usage['credits_limit']}")
print(f"Usage: {usage['percentage_used']:.1f}%")
print(f"Period: {usage['period']}")
# Alert if approaching limit
if usage['percentage_used'] > 80:
print("WARNING: Approaching credit limit!")

Token Management

List All API Tokens

def list_tokens(access_token: str):
"""List all API tokens for your account"""
response = requests.get(
"https://api.checkboxhq.com/api/v1/tokens/",
headers={"Authorization": f"Bearer {access_token}"}
)
return response.json()
tokens = list_tokens("your_jwt_access_token")
for token in tokens:
print(f"ID: {token['id']}, Name: {token['name']}, Active: {token['is_active']}")

Regenerate Token

If a token is compromised, regenerate it:

def regenerate_token(access_token: str, token_id: int):
"""Regenerate an existing API token"""
response = requests.post(
f"https://api.checkboxhq.com/api/v1/tokens/{token_id}/regenerate",
headers={"Authorization": f"Bearer {access_token}"}
)
return response.json()
# Returns new token - update your environment variables immediately
new_token_data = regenerate_token("your_jwt_access_token", 1)
print(f"New token: {new_token_data['token']}")

Revoke Token

def revoke_token(access_token: str, token_id: int):
"""Revoke/delete an API token"""
response = requests.delete(
f"https://api.checkboxhq.com/api/v1/tokens/{token_id}",
headers={"Authorization": f"Bearer {access_token}"}
)
return response.status_code == 200

Common Use Cases

1. User Registration - Block Disposable Emails

def validate_registration_email(email: str, api_key: str) -> Dict:
"""Validate email during user registration"""
client = CheckboxHQClient(api_key)
# Check if disposable (1 credit)
result = client.verify_disposable(email)
if not result['is_valid_format']:
return {
"valid": False,
"message": "Please enter a valid email address"
}
if result['is_disposable']:
return {
"valid": False,
"message": "Temporary/disposable email addresses are not allowed"
}
return {
"valid": True,
"message": "Email validated successfully"
}

2. B2B SaaS - Require Business Emails

def validate_business_email(email: str, api_key: str) -> Dict:
"""Ensure users register with business emails, not personal"""
client = CheckboxHQClient(api_key)
# Check if public provider (1 credit)
result = client.verify_public_provider(email)
if result['is_public_provider']:
return {
"valid": False,
"message": f"Please use your business email. {result['provider']} addresses are not allowed."
}
# Verify DNS to ensure domain exists (2 credits)
dns_result = client.verify_dns(email)
if not dns_result['has_mx_record']:
return {
"valid": False,
"message": "This domain cannot receive emails"
}
return {
"valid": True,
"message": "Business email verified"
}

3. Email List Cleaning

def clean_email_list(emails: list, api_key: str) -> Dict:
"""Clean a list of emails before sending campaigns"""
client = CheckboxHQClient(api_key)
valid_emails = []
invalid_emails = []
for email in emails:
try:
# Use DNS check for deliverability (2 credits per email)
dns_result = client.verify_dns(email)
if dns_result['has_mx_record'] and dns_result['has_a_record']:
valid_emails.append(email)
else:
invalid_emails.append({
"email": email,
"reason": "Cannot receive email"
})
except Exception as e:
invalid_emails.append({
"email": email,
"reason": str(e)
})
return {
"valid": valid_emails,
"invalid": invalid_emails,
"valid_count": len(valid_emails),
"invalid_count": len(invalid_emails),
"credits_used": len(emails) * 2 # DNS check costs 2 credits
}

4. Real-time Form Validation (Frontend + Backend)

Backend API Endpoint:

from flask import Flask, request, jsonify
app = Flask(__name__)
CHECKBOX_API_KEY = "cbhq_your_token"
@app.route('/api/validate-email', methods=['POST'])
def validate_email():
"""Backend endpoint for frontend email validation"""
email = request.json.get('email')
if not email:
return jsonify({"valid": False, "message": "Email required"}), 400
client = CheckboxHQClient(CHECKBOX_API_KEY)
# Quick disposable check (1 credit)
result = client.verify_disposable(email)
return jsonify({
"valid": result['is_valid_format'] and not result['is_disposable'],
"is_disposable": result['is_disposable'],
"message": "Disposable email not allowed" if result['is_disposable'] else ""
})

Frontend JavaScript:

async function validateEmail(email) {
try {
const response = await fetch('/api/validate-email', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ email: email })
});
const result = await response.json();
return result;
} catch (error) {
console.error('Validation error:', error);
return { valid: false, message: 'Validation service unavailable' };
}
}
// Use in form
document.getElementById('email').addEventListener('blur', async function() {
const result = await validateEmail(this.value);
if (!result.valid) {
showError(result.message || 'Invalid email');
} else {
clearError();
}
});

Credit Costs Summary

EndpointCreditsUse Case
/api/v1/verify_disposable/1Block temporary emails
/api/v1/verify_dns/2Verify domain can receive email
/api/v1/verify_public_provider/1Identify personal vs. business emails

Optimization Tips:

  • Use disposable check (1 credit) for basic user registration
  • Add DNS check (2 credits) for critical flows like password reset
  • Use public provider check (1 credit) only when you need to distinguish business emails
  • Cache results to avoid redundant API calls for the same email

Best Practices

1. Environment Variables

Store your API key securely:

Terminal window
# .env file
CHECKBOXHQ_API_KEY=cbhq_your_token_here
import os
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv('CHECKBOXHQ_API_KEY')

2. Caching

Implement caching to reduce API costs:

from datetime import datetime, timedelta
import hashlib
class EmailVerificationCache:
def __init__(self, ttl_days=30):
self.cache = {}
self.ttl = timedelta(days=ttl_days)
def _get_key(self, email: str) -> str:
return hashlib.sha256(email.lower().encode()).hexdigest()
def get(self, email: str):
key = self._get_key(email)
if key in self.cache:
result, timestamp = self.cache[key]
if datetime.now() - timestamp < self.ttl:
return result
return None
def set(self, email: str, result: dict):
key = self._get_key(email)
self.cache[key] = (result, datetime.now())
# Usage
cache = EmailVerificationCache(ttl_days=30)
def verify_with_cache(email: str, api_key: str):
# Check cache first
cached = cache.get(email)
if cached:
return cached
# Make API call
client = CheckboxHQClient(api_key)
result = client.verify_disposable(email)
# Cache result
cache.set(email, result)
return result

3. Async/Bulk Processing

For bulk email validation:

import asyncio
import aiohttp
async def verify_email_async(session, email, api_key):
"""Async email verification"""
async with session.post(
"https://api.checkboxhq.com/api/v1/verify_disposable/",
headers={
"x-api-key": api_key,
"Content-Type": "application/json"
},
json={"email": email}
) as response:
return await response.json()
async def verify_bulk(emails, api_key):
"""Verify multiple emails concurrently"""
async with aiohttp.ClientSession() as session:
tasks = [verify_email_async(session, email, api_key) for email in emails]
results = await asyncio.gather(*tasks, return_exceptions=True)
return results
# Usage
results = asyncio.run(verify_bulk(emails, "cbhq_your_token"))

4. Rate Limiting

Implement client-side rate limiting to prevent overwhelming the API:

import time
from collections import deque
class RateLimiter:
def __init__(self, max_requests=100, time_window=60):
"""
max_requests: Maximum requests allowed
time_window: Time window in seconds
"""
self.max_requests = max_requests
self.time_window = time_window
self.requests = deque()
def wait_if_needed(self):
now = time.time()
# Remove old requests outside time window
while self.requests and self.requests[0] < now - self.time_window:
self.requests.popleft()
# If at limit, wait
if len(self.requests) >= self.max_requests:
sleep_time = self.requests[0] + self.time_window - now
if sleep_time > 0:
time.sleep(sleep_time)
self.wait_if_needed()
self.requests.append(now)
# Usage
limiter = RateLimiter(max_requests=100, time_window=60)
for email in email_list:
limiter.wait_if_needed()
result = verify_disposable(email, api_key)

Next Steps

  1. Complete API Documentation: Visit https://api.checkboxhq.com/docs for the interactive API reference
  2. Choose Your Plan: Check https://checkboxhq.com/pricing for credit packages and pricing
  3. Monitor Usage: Regularly check your credit usage via the billing endpoint
  4. Integrate: Start with the disposable check endpoint and add DNS verification for critical flows

Support

For questions or issues:

Security Checklist

  • ✅ Store API tokens in environment variables, never in code
  • ✅ Use HTTPS for all API calls (enforced by checkboxHQ)
  • ✅ Implement proper error handling for all API calls
  • ✅ Set reasonable timeout values (10 seconds recommended)
  • ✅ Monitor credit usage to avoid service interruptions
  • ✅ Rotate API tokens regularly (use regenerate endpoint)
  • ✅ Revoke unused tokens
  • ✅ Cache validation results to reduce costs
  • ✅ Implement rate limiting on your end

You’re now ready to integrate checkboxHQ and start validating emails effectively!