Skip to main content

Overview

The Vouch Node.js SDK enables server-side email validation with higher rate limits and no domain restrictions. Perfect for backend APIs, serverless functions, and batch processing.
Package: @vouch-in/node Node Version: 18+ required TypeScript: Full type definitions included

Installation

npm install @vouch-in/node

Quick Start

import { Vouch } from '@vouch-in/node';

// Initialize with server API key
const vouch = new Vouch(
  process.env.VOUCH_PROJECT_ID,
  process.env.VOUCH_SERVER_KEY
);

// Validate an email
const result = await vouch.validate('[email protected]');

// Check the recommendation
if (result.recommendation === 'allow') {
  console.log('Email is valid!');
} else {
  // Check specific validations
  if (!result.checks.syntax?.pass) {
    throw new Error('Invalid email format');
  }
  if (!result.checks.disposable?.pass) {
    throw new Error('Disposable email not allowed');
  }
}

Validate with Request Context

Pass IP and User-Agent for better fraud detection:
const result = await vouch.validate('[email protected]', {
  ip: req.ip,
  userAgent: req.headers['user-agent'],
  fingerprintHash: req.body.fingerprintHash, // From client SDK
});

Express.js Integration

import express from 'express';
import { Vouch } from '@vouch-in/node';

const app = express();
const vouch = new Vouch(PROJECT_ID, SERVER_KEY);

app.post('/api/signup', async (req, res) => {
  const { email, fingerprintHash } = req.body;

  try {
    const result = await vouch.validate(email, {
      ip: req.ip,
      userAgent: req.get('user-agent'),
      fingerprintHash, // Optional: from client SDK
    });

    const { checks, metadata, recommendation } = result;

    // Check critical validations
    if (!checks.syntax?.pass) {
      return res.status(400).json({
        error: 'Invalid email format'
      });
    }

    if (!checks.disposable?.pass) {
      return res.status(400).json({
        error: 'Disposable emails not allowed'
      });
    }

    // Check for suspicious activity
    if (recommendation === 'block') {
      return res.status(400).json({
        error: 'This email cannot be used'
      });
    }

    if (metadata.previousSignups > 10) {
      return res.status(400).json({
        error: 'Too many accounts from this device'
      });
    }

    // Create user
    const user = await createUser(email);

    res.json({ success: true, user });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Serverless Functions

AWS Lambda

import { Vouch } from '@vouch-in/node';

const vouch = new Vouch(
  process.env.VOUCH_PROJECT_ID,
  process.env.VOUCH_SERVER_KEY
);

export const handler = async (event) => {
  const { email } = JSON.parse(event.body);

  const result = await vouch.validate(email, {
    ip: event.requestContext?.identity?.sourceIp,
    userAgent: event.headers?.['user-agent'],
  });

  if (result.recommendation !== 'allow') {
    return {
      statusCode: 400,
      body: JSON.stringify({
        error: 'Email validation failed',
        recommendation: result.recommendation
      })
    };
  }

  return {
    statusCode: 200,
    body: JSON.stringify({ success: true })
  };
};

Vercel

import { Vouch } from '@vouch-in/node';

const vouch = new Vouch(
  process.env.VOUCH_PROJECT_ID,
  process.env.VOUCH_SERVER_KEY
);

export default async function handler(req, res) {
  const { email } = req.body;

  const result = await vouch.validate(email, {
    ip: req.headers['x-forwarded-for'] || req.socket.remoteAddress,
    userAgent: req.headers['user-agent'],
  });

  if (result.recommendation !== 'allow') {
    return res.status(400).json({
      error: 'Email validation failed'
    });
  }

  res.status(200).json({ success: true });
}

Cloudflare Workers

import { Vouch } from '@vouch-in/node';

export default {
  async fetch(request, env) {
    const vouch = new Vouch(env.VOUCH_PROJECT_ID, env.VOUCH_SERVER_KEY);

    const { email } = await request.json();

    const result = await vouch.validate(email, {
      ip: request.headers.get('cf-connecting-ip'),
      userAgent: request.headers.get('user-agent'),
    });

    if (result.recommendation !== 'allow') {
      return new Response(JSON.stringify({ error: 'Validation failed' }), {
        status: 400,
        headers: { 'Content-Type': 'application/json' }
      });
    }

    return new Response(JSON.stringify({ success: true }), {
      headers: { 'Content-Type': 'application/json' }
    });
  }
};

API Reference

Constructor

new Vouch(projectId: string, apiKey: string, options?: VouchOptions)
Parameters:
projectId
string
required
Your Vouch project ID
apiKey
string
required
Your server API key
options
VouchOptions
Optional configuration:
  • endpoint - API endpoint URL (default: “https://api.vouch.expert”)
  • apiVersion - API version number or “latest” (default: “latest”)

validate()

vouch.validate(email: string, options?: ValidationRequestOptions): Promise<ValidationResponse>
Parameters:
email
string
required
Email address to validate
options
object
Optional request options:
  • ip - Client IP address for IP reputation checks
  • userAgent - Client user agent
  • fingerprintHash - Device fingerprint hash from client SDK
Returns: Promise<ValidationResponse>
interface ValidationResponse {
  checks: Record<string, CheckResult>;
  metadata: {
    fingerprintHash: string | null;
    previousSignups: number;
    totalLatency: number;
  };
  recommendation: 'allow' | 'block' | 'flag';
  signals: string[];
}

interface CheckResult {
  pass: boolean;
  error?: string;
  latency: number;
  metadata?: Record<string, unknown>;
}

Server vs Client Keys

Always use server keys on the backend. Never expose server keys in client-side code!
FeatureClient KeyServer Key
Domain RestrictionsYesNo
Rate Limits1,000/hour5,000/hour
Override IP/UANoYes
Use CaseBrowser appsBackend APIs

TypeScript Support

import { Vouch, ValidationResponse, CheckResult } from '@vouch-in/node';

const vouch = new Vouch(projectId, apiKey);

const result: ValidationResponse = await vouch.validate('[email protected]', {
  ip: '192.168.1.1',
  userAgent: 'Mozilla/5.0...'
});

// Type-safe access
const { checks, metadata, recommendation } = result;

if (recommendation === 'block') {
  throw new Error('Email blocked');
}

const syntaxCheck: CheckResult | undefined = checks.syntax;
if (syntaxCheck && !syntaxCheck.pass) {
  throw new Error('Invalid email format');
}

Error Handling

try {
  const result = await vouch.validate(email, { ip, userAgent });

  if (result.recommendation === 'block') {
    throw new Error('Email blocked by policy');
  }

  // Process valid email
} catch (error) {
  if (error.message === 'Invalid email format') {
    // Client-side validation failed before API call
    return res.status(400).json({ error: 'Invalid email format' });
  }

  // Network or API error
  console.error('Validation error:', error);
  return res.status(500).json({ error: 'Validation service unavailable' });
}

Next Steps