Documentation Index Fetch the complete documentation index at: https://docs.fraudiant.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Follow these best practices to maximize the value of Fraudiant while optimizing performance, cost, and user experience.
Implement Caching
Caching validation results can reduce API calls by 70-90% and dramatically improve response times.
Recommended caching strategy:
const cache = new Map ();
const CACHE_TTL = 24 * 60 * 60 * 1000 ; // 24 hours
async function validateEmailCached ( email ) {
const cacheKey = email . toLowerCase ();
const cached = cache . get ( cacheKey );
// Check if cache exists and is not expired
if ( cached && Date . now () - cached . timestamp < CACHE_TTL ) {
return cached . data ;
}
// Fetch from API
const validation = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
). then ( r => r . json ());
// Store in cache
cache . set ( cacheKey , {
data: validation ,
timestamp: Date . now ()
});
return validation ;
}
Cache duration recommendations:
Email validation : 24-48 hours
Domain validation : 48-72 hours (domains change less frequently)
Blocklist checks : No caching (real-time updates needed)
Use Redis for Distributed Caching
const redis = require ( 'redis' );
const client = redis . createClient ();
async function validateWithRedis ( email ) {
const cacheKey = `email_validation: ${ email . toLowerCase () } ` ;
// Try cache first
const cached = await client . get ( cacheKey );
if ( cached ) {
return JSON . parse ( cached );
}
// Call API
const validation = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
). then ( r => r . json ());
// Cache for 24 hours
await client . setEx ( cacheKey , 86400 , JSON . stringify ( validation ));
return validation ;
}
Error Handling
Fail Open Strategy
If the Fraudiant API is unavailable, allow users to proceed rather than blocking legitimate signups.
async function validateEmailSafe ( email ) {
try {
const response = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` },
timeout: 5000 // 5 second timeout
}
);
if ( ! response . ok ) {
// Service error - fail open
console . warn ( 'Fraudiant service unavailable, allowing signup' );
return { valid: true , failedOpen: true };
}
const validation = await response . json ();
return {
valid: ! validation . disposable && ! validation . spam && validation . mx ,
data: validation
};
} catch ( error ) {
console . error ( 'Email validation error:' , error );
// Fail open - don't block users due to service issues
return { valid: true , failedOpen: true };
}
}
Implement Retry Logic with Exponential Backoff
async function validateWithRetry ( email , maxRetries = 3 ) {
for ( let attempt = 0 ; attempt < maxRetries ; attempt ++ ) {
try {
const response = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
);
if ( response . status === 429 ) {
// Rate limited - wait and retry
const retryAfter = response . headers . get ( 'Retry-After' ) || Math . pow ( 2 , attempt );
await new Promise ( resolve => setTimeout ( resolve , retryAfter * 1000 ));
continue ;
}
return await response . json ();
} catch ( error ) {
if ( attempt === maxRetries - 1 ) {
// Last attempt failed - fail open
return { disposable: false , spam: false , mx: true };
}
// Wait before retrying
await new Promise ( resolve => setTimeout ( resolve , Math . pow ( 2 , attempt ) * 1000 ));
}
}
}
Rate Limit Management
async function validateWithRateLimitCheck ( email ) {
const response = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
);
// Check rate limit headers
const remaining = parseInt ( response . headers . get ( 'X-RateLimit-Remaining' ) || '0' );
const limit = parseInt ( response . headers . get ( 'X-RateLimit-Limit' ) || '0' );
const reset = parseInt ( response . headers . get ( 'X-RateLimit-Reset' ) || '0' );
// Warn if approaching limit
if ( remaining < limit * 0.1 ) {
console . warn ( `Approaching rate limit: ${ remaining } / ${ limit } remaining` );
// Consider implementing queue or backoff strategy
}
return response . json ();
}
Implement Request Queuing
class RateLimitedValidator {
constructor ( requestsPerSecond = 10 ) {
this . queue = [];
this . processing = false ;
this . interval = 1000 / requestsPerSecond ;
}
async validate ( email ) {
return new Promise (( resolve , reject ) => {
this . queue . push ({ email , resolve , reject });
this . processQueue ();
});
}
async processQueue () {
if ( this . processing || this . queue . length === 0 ) return ;
this . processing = true ;
while ( this . queue . length > 0 ) {
const { email , resolve , reject } = this . queue . shift ();
try {
const validation = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
). then ( r => r . json ());
resolve ( validation );
} catch ( error ) {
reject ( error );
}
// Wait before processing next request
await new Promise ( r => setTimeout ( r , this . interval ));
}
this . processing = false ;
}
}
// Usage
const validator = new RateLimitedValidator ( 10 ); // 10 requests per second
Security Best Practices
Protect API Keys
Never expose API keys in client-side code, public repositories, or logs.
DO:
Store keys in environment variables
Use secret management systems (AWS Secrets Manager, HashiCorp Vault)
Rotate keys regularly
Use separate keys for each environment
DON’T:
Hardcode keys in source code
Commit keys to version control
Share keys via email or chat
Use production keys in development
Validate Server-Side Only
// ❌ BAD: Client-side validation only
async function clientSideValidation ( email ) {
// API key exposed in client code!
const response = await fetch ( `https://api.fraudiant.com/email/ ${ email } ` , {
headers: { 'Authorization' : 'Bearer YOUR_API_KEY' } // Never do this!
});
return response . json ();
}
// ✅ GOOD: Server-side validation
// Frontend
async function validateEmail ( email ) {
const response = await fetch ( '/api/validate' , {
method: 'POST' ,
body: JSON . stringify ({ email })
});
return response . json ();
}
// Backend
app . post ( '/api/validate' , async ( req , res ) => {
const { email } = req . body ;
const validation = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
). then ( r => r . json ());
res . json ({ valid: ! validation . disposable && ! validation . spam });
});
User Experience
Provide Clear Feedback
function getErrorMessage ( validation ) {
if ( validation . disposable ) {
return 'Temporary email addresses are not allowed. Please use a permanent email.' ;
}
if ( validation . spam ) {
return 'This email domain is associated with spam. Please use a different email.' ;
}
if ( ! validation . mx ) {
return 'This email address cannot receive emails. Please check for typos.' ;
}
if ( validation . did_you_mean ) {
return `Did you mean ${ validation . did_you_mean } ?` ;
}
return 'Please provide a valid email address.' ;
}
Implement Progressive Validation
// Validate as user types (with debouncing)
let validationTimeout ;
function onEmailInput ( email ) {
clearTimeout ( validationTimeout );
validationTimeout = setTimeout ( async () => {
const validation = await validateEmail ( email );
if ( validation . did_you_mean ) {
showSuggestion ( validation . did_you_mean );
}
if ( ! validation . valid ) {
showError ( getErrorMessage ( validation . data ));
} else {
clearError ();
}
}, 500 ); // Wait 500ms after user stops typing
}
Handle Typos Gracefully
async function validateWithTypoCorrection ( email ) {
const validation = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
). then ( r => r . json ());
if ( validation . did_you_mean ) {
return {
valid: true ,
suggestion: validation . did_you_mean ,
message: `Did you mean ${ validation . did_you_mean } ? Click to use this instead.` ,
autoCorrect: true
};
}
return {
valid: ! validation . disposable && ! validation . spam && validation . mx ,
data: validation
};
}
Cost Optimization
Batch Validation
// Instead of validating each email immediately
async function processBulkEmails ( emails ) {
// Deduplicate emails
const uniqueEmails = [ ... new Set ( emails . map ( e => e . toLowerCase ()))];
// Check cache first
const uncachedEmails = uniqueEmails . filter ( email => ! cache . has ( email ));
// Validate only uncached emails with rate limiting
const results = [];
for ( const email of uncachedEmails ) {
const validation = await validateEmail ( email );
cache . set ( email , validation );
results . push ({ email , validation });
// Rate limit: wait between requests
await new Promise ( r => setTimeout ( r , 100 )); // 10 requests per second
}
return results ;
}
Use Domain Validation for Pre-filtering
// Validate domain first (cheaper), then email if needed
async function efficientValidation ( email ) {
const domain = email . split ( '@' )[ 1 ];
// Check domain first
const domainValidation = await fetch (
`https://api.fraudiant.com/domain/ ${ domain } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
). then ( r => r . json ());
// If domain is clearly bad, no need to validate full email
if ( domainValidation . disposable || domainValidation . spam || ! domainValidation . mx ) {
return { valid: false , reason: 'Invalid domain' };
}
// Only validate full email if domain passed
const emailValidation = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
). then ( r => r . json ());
return { valid: true , data: emailValidation };
}
Testing
Create Test Helpers
// Mock validator for testing
class MockEmailValidator {
validate ( email ) {
// Return fake validation for testing
if ( email . includes ( 'disposable' )) {
return Promise . resolve ({
disposable: true ,
spam: false ,
mx: true
});
}
return Promise . resolve ({
disposable: false ,
spam: false ,
mx: true
});
}
}
// Use in tests
describe ( 'User Registration' , () => {
it ( 'should reject disposable emails' , async () => {
const validator = new MockEmailValidator ();
const result = await validator . validate ( '[email protected]' );
expect ( result . disposable ). toBe ( true );
});
});
Test with Different Environments
// config/fraudiant.js
module . exports = {
development: {
apiKey: process . env . FRAUDIANT_DEV_API_KEY ,
strictMode: false , // Allow more emails in dev
},
staging: {
apiKey: process . env . FRAUDIANT_STAGING_API_KEY ,
strictMode: true ,
},
production: {
apiKey: process . env . FRAUDIANT_PROD_API_KEY ,
strictMode: true ,
}
};
Monitoring & Observability
Log Validation Results
async function validateWithLogging ( email ) {
const startTime = Date . now ();
try {
const validation = await fetch (
`https://api.fraudiant.com/email/ ${ email } ` ,
{
headers: { 'Authorization' : `Bearer ${ process . env . FRAUDIANT_API_KEY } ` }
}
). then ( r => r . json ());
const duration = Date . now () - startTime ;
// Log metrics
console . log ({
action: 'email_validation' ,
email: email . split ( '@' )[ 1 ], // Log domain only for privacy
disposable: validation . disposable ,
spam: validation . spam ,
duration ,
timestamp: new Date (). toISOString ()
});
return validation ;
} catch ( error ) {
console . error ({
action: 'email_validation_error' ,
error: error . message ,
duration: Date . now () - startTime
});
throw error ;
}
}
Track Rejection Rates
const metrics = {
total: 0 ,
rejected: 0 ,
disposable: 0 ,
spam: 0
};
async function validateWithMetrics ( email ) {
metrics . total ++ ;
const validation = await validateEmail ( email );
if ( validation . disposable ) {
metrics . rejected ++ ;
metrics . disposable ++ ;
}
if ( validation . spam ) {
metrics . rejected ++ ;
metrics . spam ++ ;
}
// Log metrics periodically
if ( metrics . total % 100 === 0 ) {
console . log ({
rejectionRate: ( metrics . rejected / metrics . total * 100 ). toFixed ( 2 ) + '%' ,
disposableRate: ( metrics . disposable / metrics . total * 100 ). toFixed ( 2 ) + '%' ,
spamRate: ( metrics . spam / metrics . total * 100 ). toFixed ( 2 ) + '%'
});
}
return validation ;
}
Summary
Cache aggressively Reduce API calls by 70-90% with proper caching
Fail open gracefully Don’t block users when service is unavailable
Monitor rate limits Track usage and implement queuing strategies
Validate server-side Never expose API keys in client code
Provide clear feedback Help users understand validation failures
Test thoroughly Use separate environments and mock validators