Skip to main content

JavaScript Examples

Complete code examples for integrating Status Check with Node.js and JavaScript applications.

Basic Setup

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

// Helper function for API calls
async function apiCall(endpoint, options = {}) {
const response = await fetch(`${BASE_URL}${endpoint}`, {
...options,
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json',
...options.headers,
},
});

if (!response.ok) {
if (response.status === 402) {
throw new Error('Insufficient credits');
}
throw new Error(`API Error: ${response.status} ${response.statusText}`);
}

return response.json();
}

Single Lead Validation

Create and Validate a Lead

async function validateLead(email, website) {
const result = await apiCall('/v1/leads', {
method: 'POST',
body: JSON.stringify({
email,
website,
validate: true,
validateDomain: true,
validateEmail: true,
}),
});

return result;
}

// Usage
validateLead('john@example.com', 'https://example.com')
.then(result => {
console.log('✓ Lead validated successfully');
console.log(` Lead ID: ${result.leadId}`);
console.log(` Score: ${result.leadDeliverabilityRating}/100`);
console.log(` Email Valid: ${result.emailValid}`);
console.log(` Domain Status: ${result.domainHttpStatus}`);
console.log(` Recommendation: ${result.leadRecommendation}`);
})
.catch(error => {
console.error('✗ Validation failed:', error.message);
});

Get Lead Details

async function getLead(leadId) {
return apiCall(`/v1/leads/${leadId}`, {
method: 'GET',
});
}

// Usage
const lead = await getLead('lead_abc123');
console.log(`Email: ${lead.email}`);
console.log(`Score: ${lead.leadDeliverabilityRating}`);

Bulk Lead Processing

Validate Multiple Leads

async function bulkValidateLeads(leads) {
return apiCall('/v1/leads/bulk', {
method: 'POST',
body: JSON.stringify({
leads,
validateDomain: true,
validateEmail: true,
}),
});
}

// Usage
const leads = [
{
email: 'alice@company.com',
website: 'https://company.com',
firstName: 'Alice',
lastName: 'Smith',
},
{
email: 'bob@startup.io',
website: 'https://startup.io',
firstName: 'Bob',
lastName: 'Jones',
},
];

bulkValidateLeads(leads)
.then(result => {
console.log(`Created: ${result.created} leads`);
console.log(`Skipped: ${result.skipped} duplicates`);
});

Query Leads with Filters

async function queryLeads(filters = {}) {
const params = new URLSearchParams();

if (filters.minScore) {
params.append('minDeliverabilityRating', filters.minScore);
}
if (filters.emailValid !== undefined) {
params.append('emailValid', filters.emailValid);
}
params.append('limit', filters.limit || 50);

const result = await apiCall(`/v1/leads?${params}`, {
method: 'GET',
});

return result.leads;
}

// Usage - Get high-quality leads
const highQualityLeads = await queryLeads({
minScore: 85,
emailValid: true,
});

console.log(`Found ${highQualityLeads.length} high-quality leads`);
highQualityLeads.forEach(lead => {
console.log(`${lead.email} - Score: ${lead.leadDeliverabilityRating}`);
});

CustomFields for Flexible Data

Use customFields for CSV imports, industry-specific data, or any custom properties.

Create Lead with CustomFields

async function createLeadWithCustomData(email, website, customData = {}) {
/**
* Create lead with custom fields for arbitrary data
*
* @param {string} email - Lead's email
* @param {string} website - Lead's website
* @param {object} customData - Custom key-value pairs (max 50 fields, 1KB/value)
* @returns {Promise<object>} Created lead with customFields
*/

const payload = {
email,
website,
firstName: customData.firstName || '',
lastName: customData.lastName || '',
company: customData.company || '',
title: customData.title || '',
validate: true,
validateDomain: true,
validateEmail: true,
customFields: {
// Industry-specific
industry: customData.industry,
vertical: customData.vertical,
employeeCount: customData.employeeCount,
annualRevenue: customData.annualRevenue,

// Sales tracking
leadSource: customData.leadSource,
leadScore: customData.leadScore,

// Any other custom data from CSV or forms
...Object.fromEntries(
Object.entries(customData).filter(
([key]) =>
![
'firstName',
'lastName',
'company',
'title',
'industry',
'vertical',
'employeeCount',
'annualRevenue',
'leadSource',
'leadScore',
].includes(key)
)
),
},
};

// Remove undefined/null values from customFields
payload.customFields = Object.fromEntries(
Object.entries(payload.customFields).filter(([_, v]) => v != null)
);

return apiCall('/v1/leads', {
method: 'POST',
body: JSON.stringify(payload),
});
}

// Usage - CSV Import Example
const csvRow = {
firstName: 'John',
lastName: 'Doe',
company: 'Acme Corp',
title: 'CTO',
industry: 'SaaS',
employeeCount: '50-100',
annualRevenue: '$5M-$10M',
leadSource: 'Trade Show',
customColumn1: 'Custom data from CSV',
importDate: '2025-01-15',
};

const lead = await createLeadWithCustomData(
'john@acme.com',
'https://acme.com',
csvRow
);

console.log(`Lead created: ${lead.id}`);
console.log(`CustomFields:`, lead.customFields);

Update Lead with CustomFields (Merge Behavior)

CustomFields merge with existing data instead of replacing.

async function updateLeadCustomFields(leadId, updates, customUpdates = null) {
/**
* Update lead with optional customFields merging
*
* CustomFields behavior:
* - Existing custom fields are preserved
* - New fields are added
* - Updated fields override existing values
*
* @param {string} leadId - Lead ID to update
* @param {object} updates - Standard field updates
* @param {object} customUpdates - Custom field updates (merged with existing)
* @returns {Promise<object>} Updated lead
*/

const payload = { ...updates };

if (customUpdates) {
payload.customFields = customUpdates;
}

return apiCall(`/v1/leads/${leadId}`, {
method: 'PUT',
body: JSON.stringify(payload),
});
}

// Usage Example 1: Initial customFields
let lead = await updateLeadCustomFields(
'lead_abc123',
{ notes: 'Initial contact' },
{
industry: 'SaaS',
employeeCount: '50-100',
timezone: 'America/Los_Angeles',
}
);

console.log('Added custom fields:', lead.customFields);

// Usage Example 2: Merge new customFields
lead = await updateLeadCustomFields(
'lead_abc123',
{ notes: 'Follow-up scheduled' },
{
industry: 'FinTech', // Override existing
lastContactDate: '2025-01-15', // Add new field
nextFollowUp: '2025-01-22', // Add new field
}
);

// Result:
// {
// "customFields": {
// "industry": "FinTech", ← Updated
// "employeeCount": "50-100", ← Preserved
// "timezone": "America/Los_Angeles", ← Preserved
// "lastContactDate": "2025-01-15", ← Added
// "nextFollowUp": "2025-01-22" ← Added
// }
// }
console.log('Merged custom fields:', lead.customFields);

TypeScript Types for CustomFields

interface CustomFields {
// Industry-specific
industry?: string;
vertical?: string;
employeeCount?: string;
annualRevenue?: string;

// Sales tracking
leadSource?: string;
leadScore?: number;
lastContactDate?: string;
nextFollowUp?: string;

// CSV import fields
[key: string]: string | number | boolean | null | undefined;
}

interface Lead {
id: string;
email: string;
website: string;
firstName: string;
lastName: string;
company: string;
title: string;
customFields: CustomFields;
// ... other fields
}

// Usage with TypeScript
const lead: Lead = await createLeadWithCustomData(
'john@acme.com',
'https://acme.com',
{
firstName: 'John',
company: 'Acme Corp',
industry: 'SaaS',
employeeCount: '50-100',
}
);

CustomFields Validation

CustomFields have limits to prevent abuse:

// ✅ Valid customFields
const validCustomFields = {
industry: 'SaaS',
employeeCount: '50-100',
// ... up to 50 total fields
};

// ❌ Invalid - Too many fields (> 50)
const tooManyFields = Object.fromEntries(
Array.from({ length: 51 }, (_, i) => [`field${i}`, `value${i}`])
);

// ❌ Invalid - Field name too long (> 100 chars)
const longFieldName = {
thisIsAVeryLongFieldNameThatExceedsTheMaximumAllowedLengthOf100CharactersAndShouldBeRejected:
'value',
};

// ❌ Invalid - Value too large (> 1KB)
const largeValue = {
largeField: 'x'.repeat(1500), // > 1KB
};

// Error handling for customFields validation
try {
await createLeadWithCustomData('test@example.com', 'example.com', {
customFields: tooManyFields,
});
} catch (error) {
if (error.response?.status === 422) {
console.error('CustomFields validation failed:', error.response.data);
// "customFields cannot exceed 50 fields"
}
}

React Hook for CustomFields

import { useState } from 'react';

function useLeadWithCustomFields() {
const [lead, setLead] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

const createLead = async (email, website, customData) => {
setLoading(true);
setError(null);

try {
const result = await createLeadWithCustomData(email, website, customData);
setLead(result);
return result;
} catch (err) {
setError(err.response?.data || err.message);
throw err;
} finally {
setLoading(false);
}
};

const updateCustomFields = async (leadId, customUpdates) => {
setLoading(true);
setError(null);

try {
const result = await updateLeadCustomFields(leadId, {}, customUpdates);
setLead(result);
return result;
} catch (err) {
setError(err.response?.data || err.message);
throw err;
} finally {
setLoading(false);
}
};

return { lead, loading, error, createLead, updateCustomFields };
}

// Usage in React component
function LeadForm() {
const { lead, loading, createLead } = useLeadWithCustomFields();

const handleSubmit = async (formData) => {
await createLead('john@acme.com', 'https://acme.com', {
firstName: formData.firstName,
company: formData.company,
industry: formData.industry,
employeeCount: formData.employeeCount,
});
};

return <div>{/* Form JSX */}</div>;
}

Webhook Integration

Register a Webhook

async function createWebhook(name, url, events) {
return apiCall('/v1/webhooks', {
method: 'POST',
body: JSON.stringify({
name,
url,
events,
active: true,
}),
});
}

// Usage
const webhook = await createWebhook(
'Production Webhook',
'https://your-app.com/webhooks/status-check',
['validation.complete', 'credits.low']
);

console.log(`Webhook ID: ${webhook.webhook_id}`);
console.log(`Secret: ${webhook.secret}`); // Save this securely!

Verify Webhook Signatures

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

// Timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(`sha256=${expected}`),
Buffer.from(signature)
);
}

Express.js Integration

Webhook Handler

const express = require('express');
const crypto = require('crypto');

const app = express();

// IMPORTANT: Use raw body parser for webhook signature verification
app.use('/webhooks', express.raw({ type: 'application/json' }));

const WEBHOOK_SECRET = 'whsec_your_secret_here';

app.post('/webhooks/status-check', (req, res) => {
// Get raw body and signature
const payload = req.body.toString();
const signature = req.headers['x-webhook-signature'];

// Verify signature
if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}

// Parse event
const event = JSON.parse(payload);

// Handle different event types
switch (event.event) {
case 'validation.complete':
console.log(`✓ Validation complete for batch ${event.batchId}`);
console.log(` Results: ${event.successfulValidations}/${event.totalLeads}`);
// Process validation results...
break;

case 'credits.low':
console.log(`⚠ Credit balance low: ${event.currentBalance} credits`);
// Send alert notification...
break;

default:
console.log(`Received unknown event: ${event.event}`);
}

// Always respond quickly (200 OK)
res.json({ status: 'received' });
});

// Regular JSON parser for other routes
app.use(express.json());

app.listen(3000, () => {
console.log('Webhook server listening on port 3000');
});

API Client Class

class StatusCheckClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.status-check.io';
}

async request(endpoint, options = {}) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json',
...options.headers,
},
});

if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.error || `HTTP ${response.status}`);
}

return response.json();
}

// Lead methods
async createLead(data) {
return this.request('/v1/leads', {
method: 'POST',
body: JSON.stringify(data),
});
}

async getLead(leadId) {
return this.request(`/v1/leads/${leadId}`);
}

async queryLeads(filters = {}) {
const params = new URLSearchParams(filters);
return this.request(`/v1/leads?${params}`);
}

async bulkCreateLeads(leads) {
return this.request('/v1/leads/bulk', {
method: 'POST',
body: JSON.stringify({ leads }),
});
}

// Webhook methods
async createWebhook(data) {
return this.request('/v1/webhooks', {
method: 'POST',
body: JSON.stringify(data),
});
}

async listWebhooks() {
return this.request('/v1/webhooks');
}

async deleteWebhook(webhookId) {
return this.request(`/v1/webhooks/${webhookId}`, {
method: 'DELETE',
});
}
}

// Usage
const client = new StatusCheckClient('sk_live_your_key');

// Create and validate a lead
const lead = await client.createLead({
email: 'test@example.com',
website: 'https://example.com',
validate: true,
});

console.log(`Score: ${lead.leadDeliverabilityRating}`);

Next.js Integration

API Route Handler

// pages/api/webhooks/status-check.js

import crypto from 'crypto';

function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

return signature === `sha256=${expected}`;
}

export const config = {
api: {
bodyParser: false, // Disable built-in parser for raw body
},
};

export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}

// Read raw body
const chunks = [];
for await (const chunk of req) {
chunks.push(chunk);
}
const payload = Buffer.concat(chunks).toString();

// Verify signature
const signature = req.headers['x-webhook-signature'];
const secret = process.env.STATUSCHECK_WEBHOOK_SECRET;

if (!verifySignature(payload, signature, secret)) {
return res.status(401).json({ error: 'Invalid signature' });
}

// Parse and handle event
const event = JSON.parse(payload);

switch (event.event) {
case 'validation.complete':
// Update database with results
console.log(`Validation complete: ${event.batchId}`);
break;

case 'credits.low':
// Send notification
console.log(`Credits low: ${event.currentBalance}`);
break;
}

res.json({ received: true });
}

Server-Side Lead Validation

// pages/api/validate-lead.js

export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}

const { email, website } = req.body;

try {
const response = await fetch('https://api.status-check.io/v1/leads', {
method: 'POST',
headers: {
'X-API-Key': process.env.STATUSCHECK_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
website,
validate: true,
validateDomain: true,
validateEmail: true,
}),
});

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

const result = await response.json();

res.json({
valid: result.leadDeliverabilityRating >= 70,
score: result.leadDeliverabilityRating,
recommendation: result.leadRecommendation,
});
} catch (error) {
res.status(500).json({ error: error.message });
}
}

React Hook

Custom Hook for Lead Validation

import { useState } from 'react';

function useLeadValidation() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [result, setResult] = useState(null);

const validateLead = async (email, website) => {
setLoading(true);
setError(null);

try {
const response = await fetch('/api/validate-lead', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, website }),
});

if (!response.ok) {
throw new Error('Validation failed');
}

const data = await response.json();
setResult(data);
return data;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
};

return {
validateLead,
loading,
error,
result,
};
}

// Usage in component
function LeadForm() {
const { validateLead, loading, result, error } = useLeadValidation();
const [email, setEmail] = useState('');
const [website, setWebsite] = useState('');

const handleSubmit = async (e) => {
e.preventDefault();

try {
const validation = await validateLead(email, website);

if (validation.valid) {
alert(`✓ Lead is valid! Score: ${validation.score}/100`);
} else {
alert(`✗ Lead quality is low. Score: ${validation.score}/100`);
}
} catch (err) {
alert(`Error: ${err.message}`);
}
};

return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
required
/>
<input
type="url"
value={website}
onChange={(e) => setWebsite(e.target.value)}
placeholder="Website"
required
/>
<button type="submit" disabled={loading}>
{loading ? 'Validating...' : 'Validate Lead'}
</button>

{error && <div className="error">{error}</div>}

{result && (
<div className="result">
<p>Score: {result.score}/100</p>
<p>Recommendation: {result.recommendation}</p>
</div>
)}
</form>
);
}

Advanced Examples

Batch Processing with Progress

async function processBatchWithProgress(leads, onProgress) {
// Start validation
const batch = await apiCall('/v1/leads/validate', {
method: 'POST',
body: JSON.stringify({
leadIds: leads.map(l => l.leadId),
validateDomain: true,
validateEmail: true,
}),
});

const batchId = batch.batchId;

// Poll for status (or use webhooks)
return new Promise((resolve, reject) => {
const interval = setInterval(async () => {
try {
const status = await apiCall(`/v1/batches/${batchId}`);

onProgress({
status: status.status,
progress: status.progress || 0,
});

if (status.status === 'complete') {
clearInterval(interval);
resolve(status);
} else if (status.status === 'failed') {
clearInterval(interval);
reject(new Error('Batch failed'));
}
} catch (error) {
clearInterval(interval);
reject(error);
}
}, 5000); // Check every 5 seconds
});
}

// Usage
processBatchWithProgress(leads, ({ status, progress }) => {
console.log(`Status: ${status}, Progress: ${progress}%`);
})
.then(result => {
console.log('✓ Batch complete!');
})
.catch(error => {
console.error('✗ Batch failed:', error);
});

Retry Logic with Exponential Backoff

async function retryWithBackoff(fn, maxRetries = 3, baseDelay = 1000) {
let lastError;

for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
lastError = error;

// Don't retry on client errors (4xx except 429)
if (error.message.includes('400') || error.message.includes('404')) {
throw error;
}

// Check for rate limit
if (error.message.includes('429')) {
const delay = baseDelay * Math.pow(2, i);
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}

// Last retry
if (i === maxRetries - 1) {
throw lastError;
}

// Exponential backoff
const delay = baseDelay * Math.pow(2, i);
console.log(`Request failed. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}

throw lastError;
}

// Usage
const result = await retryWithBackoff(() =>
validateLead('test@example.com', 'https://example.com')
);

Export Results to CSV

function exportToCSV(leads, filename = 'validated_leads.csv') {
const headers = [
'email',
'website',
'firstName',
'lastName',
'leadDeliverabilityRating',
'emailValid',
'domainHttpStatus',
'leadRecommendation',
];

const rows = leads.map(lead =>
headers.map(header => JSON.stringify(lead[header] || '')).join(',')
);

const csv = [headers.join(','), ...rows].join('\n');

// Browser download
const blob = new Blob([csv], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);

console.log(`✓ Exported ${leads.length} leads to ${filename}`);
}

// Usage
const leads = await queryLeads({ limit: 1000 });
exportToCSV(leads);

TypeScript Support

Type Definitions

interface Lead {
leadId: string;
email: string;
website?: string;
firstName?: string;
lastName?: string;
leadDeliverabilityRating: number;
emailValid: boolean;
emailScore: number;
domainHttpStatus: number;
domainScore: number;
leadRecommendation: 'high_priority' | 'validate' | 'research' | 'skip';
validationStatus: 'pending' | 'validating' | 'verified' | 'warning' | 'risky' | 'error';
createdAt: string;
updatedAt: string;
}

interface ValidationResult {
leadId: string;
status: string;
batchId?: string;
}

interface WebhookEvent {
event: string;
timestamp: string;
userId?: string;
batchId?: string;
totalLeads?: number;
successfulValidations?: number;
failedValidations?: number;
}

// Client class with types
class TypedStatusCheckClient {
constructor(private apiKey: string) {}

async createLead(data: Partial<Lead>): Promise<Lead> {
// Implementation...
}

async getLead(leadId: string): Promise<Lead> {
// Implementation...
}

async queryLeads(filters?: {
minScore?: number;
emailValid?: boolean;
limit?: number;
}): Promise<Lead[]> {
// Implementation...
}
}

Next Steps