npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@easy-otp/sdk

v1.0.0

Published

Official Node.js SDK for EasyOTP API - Send and verify OTP codes via SMS, Email, and Voice

Readme

EasyOTP Node.js SDK

Official Node.js SDK for the EasyOTP API. Send and verify one-time passwords via SMS, Email, and Voice.

Installation

npm install @easy-otp/sdk

Quick Start

Setting Your API Key

You can provide your API key in several ways:

Option 1: Direct in code (for testing only)

const client = new EasyOTP({
  apiKey: 'your-api-key-here'
});

Option 2: Environment variable (recommended)

EASYOTP_API_KEY=your-api-key-here
const client = new EasyOTP({
  apiKey: process.env.EASYOTP_API_KEY
});

Option 3: Using dotenv package

npm install dotenv
require('dotenv').config();
const client = new EasyOTP({
  apiKey: process.env.EASYOTP_API_KEY
});

Basic Usage

const { EasyOTP } = require('@easy-otp/sdk');

const client = new EasyOTP({
  apiKey: process.env.EASYOTP_API_KEY || 'your-api-key-here'
});

async function main() {
  const result = await client.send({
    channel: 'sms',
    recipient: '+1234567890',
    message: 'Your verification code is: {code}'
  });

  console.log('Verification ID:', result.verification_id);

  const verification = await client.verify({
    verification_id: result.verification_id,
    code: '123456'
  });

  console.log('Verified:', verification.verified);
}

main();

TypeScript Support

The SDK is written in TypeScript and includes full type definitions:

import { EasyOTP, SendOptions, VerifyOptions } from '@easy-otp/sdk';

const client = new EasyOTP({
  apiKey: process.env.EASYOTP_API_KEY!
});

const sendOptions: SendOptions = {
  channel: 'sms',
  recipient: '+1234567890',
  message: 'Your code is: {code}',
  expiresIn: 300
};

const result = await client.send(sendOptions);

API Reference

Constructor

new EasyOTP(config: EasyOTPConfig)

Parameters:

  • config.apiKey (string, required): Your EasyOTP API key
  • config.baseURL (string, optional): Custom base URL (defaults to https://app.easyotp.dev/api/v1)

Methods

send(options: SendOptions): Promise<SendResponse>

Send a verification code via SMS, Email, or Voice.

Parameters:

  • options.channel (string, required): "sms", "email", or "voice"
  • options.recipient (string, required): Phone number (E.164 format) or email address
  • options.message (string, optional): Custom message template with {code} placeholder
  • options.subject (string, optional): Email subject (email channel only)
  • options.expiresIn (number, optional): Expiration time in seconds (60-3600, default: 300)
  • options.code (string, optional): Custom verification code (4-10 digits)

Returns:

{
  success: boolean;
  verification_id: string;
  expires_at: string;
  request_id: string;
}

Example:

const result = await client.send({
  channel: 'sms',
  recipient: '+1234567890',
  message: 'Your Acme Corp verification code is: {code}',
  expiresIn: 300
});

verify(options: VerifyOptions): Promise<VerifyResponse>

Verify a verification code.

Parameters:

  • options.verification_id (string, required): Verification ID from the send response
  • options.code (string, required): The verification code to check

Returns:

{
  success: boolean;
  verified: boolean;
  message?: string;
  request_id: string;
  retry_after?: number;
}

Example:

const result = await client.verify({
  verification_id: '11f951d5-32d1-4b49-bdda-7da248e2615c',
  code: '123456'
});

if (result.verified) {
  console.log('Code verified successfully!');
} else {
  console.log('Verification failed:', result.message);
}

Error Handling

The SDK throws specific error classes for different error scenarios:

import {
  EasyOTPError,
  AuthenticationError,
  InsufficientCreditsError,
  RateLimitError,
  ValidationError
} from '@easy-otp/sdk';

try {
  await client.send({ channel: 'sms', recipient: '+1234567890' });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof InsufficientCreditsError) {
    console.error('Not enough credits');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
  } else if (error instanceof ValidationError) {
    console.error('Invalid request:', error.message);
  } else if (error instanceof EasyOTPError) {
    console.error('API error:', error.message);
  }
}

Error Classes

  • EasyOTPError: Base error class
  • AuthenticationError (401): Invalid or missing API key
  • InsufficientCreditsError (402): Not enough credits
  • ForbiddenError (403): API key is disabled
  • NotFoundError (404): Verification not found
  • RateLimitError (429): Rate limit exceeded (includes retryAfter property)
  • ValidationError (400): Invalid request parameters
  • ServerError (500): Internal server error

Examples

Send SMS Verification

const result = await client.send({
  channel: 'sms',
  recipient: '+1234567890',
  message: 'Your verification code is: {code}',
  expiresIn: 300
});

Send Email Verification

const result = await client.send({
  channel: 'email',
  recipient: '[email protected]',
  subject: 'Your Verification Code',
  message: 'Your verification code is: {code}',
  expiresIn: 600
});

Send Voice Verification

const result = await client.send({
  channel: 'voice',
  recipient: '+1234567890',
  message: 'Your verification code is: {code}',
  expiresIn: 300
});

Complete Verification Flow

async function verifyUser(phoneNumber) {
  const sendResult = await client.send({
    channel: 'sms',
    recipient: phoneNumber,
    message: 'Your verification code is: {code}'
  });

  const verificationId = sendResult.verification_id;

  return {
    verificationId,
    verify: async (code) => {
      const result = await client.verify({
        verification_id: verificationId,
        code: code
      });
      return result.verified;
    }
  };
}

const verification = await verifyUser('+1234567890');
const isValid = await verification.verify('123456');

Handling Rate Limits

async function sendWithRetry(recipient, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await client.send({
        channel: 'sms',
        recipient: recipient
      });
    } catch (error) {
      if (error instanceof RateLimitError && error.retryAfter) {
        if (i < maxRetries - 1) {
          await new Promise(resolve => 
            setTimeout(resolve, error.retryAfter! * 1000)
          );
          continue;
        }
      }
      throw error;
    }
  }
}

Testing

The API supports test mode for development without consuming credits:

Test Phone Numbers

  • +15555550100: Always succeeds (use code 123456)
  • +15555550101: Always fails with "Invalid code"
  • +15555550102: Expires immediately

Test Email Addresses

const testResult = await client.send({
  channel: 'sms',
  recipient: '+15555550100',
  message: 'Test code: {code}'
});

const verifyResult = await client.verify({
  verification_id: testResult.verification_id,
  code: '123456'
});

console.log(verifyResult.verified); // true

Environment Variables

For testing and development, you can set the EASYOTP_API_KEY environment variable:

macOS/Linux:

export EASYOTP_API_KEY=your-api-key-here

Windows (PowerShell):

$env:EASYOTP_API_KEY="your-api-key-here"

Windows (Command Prompt):

set EASYOTP_API_KEY=your-api-key-here

Using .env file (with dotenv):

  1. Create a .env file in your project root:
    EASYOTP_API_KEY=your-api-key-here
  2. Install dotenv: npm install dotenv
  3. Load it in your code: require('dotenv').config()

Next.js Usage

The SDK works perfectly with Next.js! Here are examples for different Next.js patterns:

API Route (Recommended)

app/api/verify/route.ts:

import { NextRequest, NextResponse } from 'next/server';
import { EasyOTP } from '@easy-otp/sdk';

const client = new EasyOTP({
  apiKey: process.env.EASYOTP_API_KEY!
});

export async function POST(request: NextRequest) {
  try {
    const { channel, recipient } = await request.json();
    
    const result = await client.send({
      channel,
      recipient,
      message: 'Your verification code is: {code}',
    });
    
    return NextResponse.json(result);
  } catch (error: any) {
    return NextResponse.json(
      { error: error.message },
      { status: error.statusCode || 500 }
    );
  }
}

Server Actions

app/actions.ts:

'use server';

import { EasyOTP } from '@easy-otp/sdk';

const client = new EasyOTP({
  apiKey: process.env.EASYOTP_API_KEY!
});

export async function sendVerificationCode(recipient: string) {
  const result = await client.send({
    channel: 'sms',
    recipient,
    message: 'Your verification code is: {code}',
  });
  
  return result.verification_id;
}

Server Component

app/page.tsx:

import { EasyOTP } from '@easy-otp/sdk';

const client = new EasyOTP({
  apiKey: process.env.EASYOTP_API_KEY!
});

export default async function Page() {
  const result = await client.send({
    channel: 'sms',
    recipient: '+1234567890',
    message: 'Your code is: {code}',
  });
  
  return <div>Verification ID: {result.verification_id}</div>;
}

Environment Variables in Next.js

Create a .env.local file in your Next.js project root:

EASYOTP_API_KEY=your-api-key-here

Important: Never use the SDK in Client Components! Always use it in:

  • ✅ API Routes (app/api/**/route.ts)
  • ✅ Server Actions ('use server')
  • ✅ Server Components (app/**/page.tsx)

The API key should never be exposed to the browser. Always keep it server-side.

Requirements

  • Node.js 18.0.0 or higher
  • A valid EasyOTP API key (get one at app.easyotp.dev)

License

MIT

Support

For API documentation, visit https://docs.easyotp.dev

For support, email [email protected]