Skip to main content

Validation API

Standalone website and email validation without creating leads. Perfect for quick checks, integrations, and automated verification workflows.

Overview

The Validation API provides three endpoints for on-demand validation:

  • Check Website - Validate website accessibility (synchronous)
  • Check Email - Validate email deliverability (hybrid sync/async)
  • Poll Job Status - Retrieve results for async validations

Pricing

OperationCost (Stored)Cost (Display)
Check Website0.001 credits1 credit
Check Email0.001 credits1 credit
Lead Validation0.002 credits2 credits

New Users: Get 2,000 display credits (2.0 stored credits) on signup!

Rate Limits

EndpointRate Limit
/check-website10 requests/minute
/check-email10 requests/minute
/leads/validate5 requests/minute

Check Website

Validate website HTTP status and accessibility with intelligent retry logic.

Endpoint: POST /v1/check-website

Authentication: API Key or OAuth 2.0 Bearer Token

Processing: Synchronous - returns results immediately (max ~30s)

Features

  • ✅ Intelligent retry with progressive timeouts (10s → 20s → 15s)
  • ✅ Smart fallbacks (HTTPS→HTTP, www variants)
  • ✅ SSL validation
  • ✅ Parked domain detection
  • ✅ Redirect chain tracking
  • ✅ Response time measurement

Request

curl -X POST https://api.status-check.io/v1/check-website \
-H "X-API-Key: sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"website": "example.com",
"returnDetails": true
}'

Request Body

FieldTypeRequiredDescription
websitestringYesWebsite URL to validate (1-255 chars)
returnDetailsbooleanNoReturn full details vs simple status (default: true)

Response (Success)

{
"website": "https://example.com",
"status": "active",
"valid": true,
"httpStatus": 200,
"finalUrl": "https://example.com/",
"sslValid": true,
"isParked": false,
"responseTimeMs": 245.67,
"redirectChain": [
"https://example.com",
"https://example.com/"
],
"error": null,
"creditsDeducted": 0.001,
"creditsRemaining": 1.999
}

Response Fields

FieldTypeDescription
websitestringValidated website URL
statusstringValidation status: active, inactive, error
validbooleanTrue if website is accessible (status == "active")
httpStatusnumberHTTP response code (200, 404, etc.)
finalUrlstringFinal URL after following redirects
sslValidbooleanWhether SSL certificate is valid
isParkedbooleanDomain appears to be parked
responseTimeMsnumberTotal response time in milliseconds
redirectChainarrayFull redirect chain (if any)
errorstringError message (if status is error)
creditsDeductednumberCredits charged (0.001 stored credits)
creditsRemainingnumberYour remaining credit balance

Response (Error)

{
"website": "invalid-domain.xyz",
"status": "error",
"valid": false,
"error": "DNS resolution failed: domain not found",
"creditsDeducted": 0.001,
"creditsRemaining": 1.999
}
Credit Policy

Credits are deducted upfront and not refunded on failures. This is standard practice to prevent abuse.

Status Values

StatusDescription
activeWebsite is accessible (HTTP 2xx-3xx)
inactiveWebsite returned 4xx/5xx or timeout
errorDNS failure, network error, or other issues

Validation Strategy

The endpoint uses a three-tier validation approach:

  1. Initial Check (10s timeout)

    • Try HTTPS with original URL
    • If successful → return immediately
  2. Retry on Soft Failures (20s timeout)

    • Retry if: timeout, 5xx error, or SSL issue
    • If successful → return immediately
  3. Smart Fallbacks (15s timeout)

    • SSL error → try HTTP instead
    • DNS/404 error → try www variant
    • Return final result

Total maximum time: ~30 seconds

Hard failures (fast fail ~2-3s):

  • DNS resolution errors
  • Connection refused
  • Network unreachable

Check Email

Validate email deliverability with SMTP verification (no email sent).

Endpoint: POST /v1/check-email

Authentication: API Key or OAuth 2.0 Bearer Token

Processing: Hybrid sync/async

Hybrid Processing Model

The endpoint intelligently handles email validation:

  1. Submit validation to XOR API
  2. Poll internally for up to timeout seconds (default 30s)
  3. If completes within timeout: Return full results synchronously
  4. If timeout expires: Return jobId for polling
  5. Background task continues polling until complete

Success rate: ~60-70% of validations complete within 30 seconds

Features

  • ✅ SMTP verification (no email sent)
  • ✅ Disposable email detection
  • ✅ Catch-all domain detection
  • ✅ Email type classification (corporate, personal, role)
  • ✅ Risk scoring (0-100)
  • ✅ Service provider identification
  • ✅ Optional webhook callback

Request

curl -X POST https://api.status-check.io/v1/check-email \
-H "X-API-Key: sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"timeout": 30,
"returnDetails": true,
"webhookUrl": "https://yourapp.com/webhook"
}'

Request Body

FieldTypeRequiredDescription
emailstringYesEmail address to validate (must be valid format)
timeoutnumberNoMax seconds to wait (5-60, default: 30)
returnDetailsbooleanNoReturn full details vs simple status (default: true)
webhookUrlstringNoOptional webhook for async completion

Response (Completed Synchronously)

{
"email": "user@example.com",
"status": "valid",
"valid": true,
"catchAll": false,
"disposable": false,
"service": "Google",
"domain": "gmail-smtp-in.l.google.com",
"emailType": "personal",
"emailRisk": "low",
"emailScore": 95,
"waitTime": "12.5s",
"creditsDeducted": 0.001,
"creditsRemaining": 1.999
}

Response (Timeout - Async)

{
"email": "user@example.com",
"status": "processing",
"jobId": "val_abc123def456",
"pollUrl": "/v1/validation-jobs/val_abc123def456",
"estimatedCompletion": "2025-01-15T10:35:00Z",
"message": "Email validation is processing. Poll the provided URL for results or wait for webhook notification.",
"creditsDeducted": 0.001,
"creditsRemaining": 1.999
}

Response Fields (Completed)

FieldTypeDescription
emailstringValidated email address
statusstringValidation status: valid, invalid, risky, unknown, processing
validbooleanWhether email is deliverable
catchAllbooleanDomain accepts all emails (risky)
disposablebooleanDisposable/temporary email service
servicestringEmail service provider (e.g., "Google", "Microsoft")
domainstringSMTP server domain
emailTypestringEmail type: corporate, personal, role
emailRiskstringRisk level: low, medium, high
emailScorenumberQuality score (0-100)
waitTimestringTime waited for results (e.g., "12.5s")
creditsDeductednumberCredits charged (0.001)
creditsRemainingnumberYour remaining balance

Status Values

StatusDescription
validEmail is deliverable
invalidEmail is not deliverable
riskyEmail might be deliverable (catch-all)
unknownValidation inconclusive
processingStill validating (async)

Webhook Callback

If you provide a webhookUrl, you'll receive a POST request when validation completes:

{
"event": "validation.complete",
"jobId": "val_abc123def456",
"email": "user@example.com",
"result": {
"valid": true,
"catch_all": false,
"service": "Google"
},
"timestamp": "2025-01-15T10:35:00Z"
}
Webhook Security

Ad-hoc webhooks (via webhookUrl parameter) are:

  • ✅ Authenticated (must be logged in)
  • ❌ Not signed (no HMAC signature)
  • ❌ No retries (one-time delivery)

For production webhooks, use the Webhooks API.


Poll Job Status

Retrieve status and results for an async validation job.

Endpoint: GET /v1/validation-jobs/{jobId}

Authentication: API Key or OAuth 2.0 Bearer Token

Use Case

When check-email returns status: "processing" due to timeout, use this endpoint to poll for results.

Request

curl -X GET https://api.status-check.io/v1/validation-jobs/val_abc123def456 \
-H "X-API-Key: sk_your_api_key"

Response (Completed)

{
"jobId": "val_abc123def456",
"type": "email",
"input": "user@example.com",
"status": "completed",
"result": {
"email": "user@example.com",
"valid": true,
"catch_all": false,
"service": "Google",
"domain": "gmail-smtp-in.l.google.com",
"email_type": "personal",
"email_risk": "low",
"email_score": 95
},
"createdAt": "2025-01-15T10:30:00Z",
"completedAt": "2025-01-15T10:30:45Z",
"elapsedTime": "45s"
}

Response (Still Processing)

{
"jobId": "val_abc123def456",
"type": "email",
"input": "user@example.com",
"status": "processing",
"createdAt": "2025-01-15T10:30:00Z",
"elapsedTime": "12s"
}

Response (Failed)

{
"jobId": "val_abc123def456",
"type": "email",
"input": "user@example.com",
"status": "failed",
"error": "SMTP connection timeout",
"createdAt": "2025-01-15T10:30:00Z",
"completedAt": "2025-01-15T10:31:30Z",
"elapsedTime": "1m 30s"
}

Response Fields

FieldTypeDescription
jobIdstringValidation job identifier
typestringJob type: email or website
inputstringEmail or website being validated
statusstringJob status: processing, completed, failed, timeout
resultobjectValidation results (if completed)
errorstringError message (if failed)
createdAtdatetimeWhen job was created
completedAtdatetimeWhen job finished (if completed)
elapsedTimestringTotal time elapsed (human-readable)

Job Lifecycle

processing → completed | failed | timeout
  • processing: Validation in progress
  • completed: Results available in result field
  • failed: Validation failed (see error field)
  • timeout: Exceeded max validation time (5 minutes)

Job TTL

Validation jobs auto-delete after 24 hours. Poll results will return 404 after expiration.

Polling Strategy

async function pollForResults(jobId) {
const maxAttempts = 30; // 1 minute total
const pollInterval = 2000; // 2 seconds

for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(`/v1/validation-jobs/${jobId}`, {
headers: { 'X-API-Key': apiKey }
});

const job = await response.json();

if (job.status === 'completed') {
return job.result;
} else if (job.status === 'failed') {
throw new Error(job.error);
}

// Still processing, wait and retry
await new Promise(resolve => setTimeout(resolve, pollInterval));
}

throw new Error('Polling timeout');
}

Error Responses

All validation endpoints follow consistent error formatting:

401 Unauthorized

{
"error": "Unauthorized",
"error_code": "INVALID_API_KEY",
"details": {
"message": "Invalid or missing API key"
}
}

402 Payment Required

{
"error": "Insufficient credits",
"required": 0.001,
"available": 0.0,
"displayCreditsRequired": 1,
"displayCreditsAvailable": 0
}

404 Not Found

{
"detail": "Validation job not found or expired"
}

422 Validation Error

{
"error": "Validation Error",
"error_code": "VALIDATION_ERROR",
"details": {
"errors": [
{
"field": "email",
"message": "Invalid email format",
"type": "value_error"
}
]
}
}

429 Rate Limit Exceeded

{
"error": "Rate limit exceeded",
"message": "10 per 1 minute",
"error_code": "RATE_LIMIT_EXCEEDED"
}

Code Examples

Python

import requests

API_KEY = "sk_your_api_key"
BASE_URL = "https://api.status-check.io/v1"

# Check website
response = requests.post(
f"{BASE_URL}/check-website",
headers={"X-API-Key": API_KEY},
json={"website": "example.com", "returnDetails": True}
)

result = response.json()
print(f"Status: {result['status']}, HTTP: {result.get('httpStatus')}")

# Check email (with polling)
response = requests.post(
f"{BASE_URL}/check-email",
headers={"X-API-Key": API_KEY},
json={"email": "user@example.com", "timeout": 30}
)

result = response.json()

if result['status'] == 'processing':
# Poll for results
job_id = result['jobId']

import time
for _ in range(30):
response = requests.get(
f"{BASE_URL}/validation-jobs/{job_id}",
headers={"X-API-Key": API_KEY}
)
job = response.json()

if job['status'] == 'completed':
print(f"Valid: {job['result']['valid']}")
break

time.sleep(2)
else:
print(f"Valid: {result.get('valid')}")

JavaScript/Node.js

const API_KEY = 'sk_your_api_key';
const BASE_URL = 'https://api.status-check.io/v1';

// Check website
async function checkWebsite(website) {
const response = await fetch(`${BASE_URL}/check-website`, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ website, returnDetails: true }),
});

const result = await response.json();
console.log(`Status: ${result.status}, HTTP: ${result.httpStatus}`);
return result;
}

// Check email with webhook
async function checkEmail(email, webhookUrl) {
const response = await fetch(`${BASE_URL}/check-email`, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
timeout: 30,
returnDetails: true,
webhookUrl,
}),
});

const result = await response.json();

if (result.status === 'processing') {
console.log(`Check ${result.pollUrl} for results`);
} else {
console.log(`Valid: ${result.valid}`);
}

return result;
}

// Usage
await checkWebsite('example.com');
await checkEmail('user@example.com', 'https://yourapp.com/webhook');

cURL

# Check website
curl -X POST https://api.status-check.io/v1/check-website \
-H "X-API-Key: sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{"website": "example.com", "returnDetails": true}'

# Check email
curl -X POST https://api.status-check.io/v1/check-email \
-H "X-API-Key: sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"timeout": 30,
"returnDetails": true
}'

# Poll job status
curl -X GET https://api.status-check.io/v1/validation-jobs/val_abc123def456 \
-H "X-API-Key: sk_your_api_key"

Best Practices

1. Handle Async Gracefully

async function checkEmailWithRetry(email) {
const response = await checkEmail(email);

if (response.status === 'processing') {
// Set up background polling or webhook listener
return { status: 'pending', jobId: response.jobId };
}

return response;
}

2. Use Webhooks for Large Batches

// For bulk validation, use webhooks instead of polling
const emails = [...]; // Large list

for (const email of emails) {
await checkEmail(email, 'https://yourapp.com/webhook');
// Don't poll - webhook will notify you
}

3. Implement Exponential Backoff

async function pollWithBackoff(jobId) {
let delay = 2000; // Start with 2s
const maxDelay = 30000; // Max 30s

while (true) {
const job = await getJob(jobId);

if (job.status !== 'processing') {
return job;
}

await sleep(delay);
delay = Math.min(delay * 1.5, maxDelay);
}
}

4. Monitor Credits

async function checkWithCreditMonitoring(email) {
const result = await checkEmail(email);

if (result.creditsRemaining < 100) {
console.warn('Low credits!', result.creditsRemaining);
// Trigger notification or purchase flow
}

return result;
}

FAQ

Q: Why are credits deducted even on failures?

A: This prevents abuse and is industry standard. Validation costs (API calls, SMTP connections) occur regardless of the result.

Q: How long do validation jobs stay available?

A: Jobs auto-delete after 24 hours. Poll results shortly after receiving a jobId.

Q: Can I validate without an API key?

A: No. All validation endpoints require authentication. Create an account to get your API key.

Q: What happens if my webhook fails?

A: Ad-hoc webhooks (via webhookUrl parameter) are not retried. For reliable webhooks, use the Webhooks API with automatic retries.

Q: How accurate is email validation?

A: We use SMTP verification which is ~95% accurate. False positives/negatives can occur with catch-all domains or aggressive spam filters.

Q: Can I validate domains without HTTP/HTTPS?

A: The endpoint normalizes URLs automatically. Submit example.com and we'll try https://example.com, http://example.com, and https://www.example.com.



Support

Questions about the Validation API?