> ## Documentation Index
> Fetch the complete documentation index at: https://docs.easyotp.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK

> Official JavaScript/TypeScript SDK for EasyOTP

## Installation

Install the EasyOTP SDK using npm or your preferred package manager:

<CodeGroup>
  ```bash npm theme={null}
  npm install @easy-otp/sdk
  ```

  ```bash yarn theme={null}
  yarn add @easy-otp/sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @easy-otp/sdk
  ```
</CodeGroup>

## Quick Start

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { EasyOTP } from '@easy-otp/sdk';

  const client = new EasyOTP({
    apiKey: 'YOUR_API_KEY'
  });

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

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

  ```typescript TypeScript theme={null}
  import { EasyOTP } from '@easy-otp/sdk';

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

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

  console.log('Verification ID:', result.verification_id);
  ```
</CodeGroup>

## Initialization

Create a new EasyOTP client instance with your API key:

```javascript theme={null}
import { EasyOTP } from '@easy-otp/sdk';

const client = new EasyOTP({
  apiKey: 'YOUR_API_KEY',
  baseUrl: 'https://app.easyotp.dev/api/v1'
});
```

### Configuration Options

<ParamField body="apiKey" type="string" required>
  Your EasyOTP API key. Get it from your [dashboard](https://app.easyotp.dev/api-keys).
</ParamField>

<ParamField body="baseUrl" type="string">
  Base URL for the API. Defaults to `https://app.easyotp.dev/api/v1`.
</ParamField>

<Warning>
  Never expose your API key in client-side code. Always use the SDK from your backend server.
</Warning>

## Methods

### send()

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

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

#### Parameters

<ParamField body="channel" type="string" required>
  Communication channel. Must be one of: `sms`, `email`, or `voice`
</ParamField>

<ParamField body="recipient" type="string" required>
  Recipient address:

  * For SMS/Voice: E.164 formatted phone number (e.g., `+1234567890`)
  * For Email: Valid email address (e.g., `user@example.com`)
</ParamField>

<ParamField body="message" type="string">
  Custom message template. Use `{code}` as a placeholder for the verification code.

  Default: `"Your verification code is: {code}"`
</ParamField>

<ParamField body="subject" type="string">
  Email subject line (only used when `channel` is `email`)

  Default: `"Your Verification Code"`
</ParamField>

<ParamField body="expires_in" type="number">
  Code expiration time in seconds. Must be between 60 and 3600.

  Default: `300` (5 minutes)
</ParamField>

<ParamField body="code" type="string">
  Custom verification code. Must be a numeric string between 4-10 digits.

  If not provided, a code will be automatically generated.
</ParamField>

#### Returns

<ResponseField name="success" type="boolean">
  Always `true` for successful requests
</ResponseField>

<ResponseField name="verification_id" type="string">
  Unique identifier for this verification. Use this when calling `verify()`.
</ResponseField>

<ResponseField name="expires_at" type="string">
  ISO 8601 timestamp when the code expires
</ResponseField>

<ResponseField name="request_id" type="string">
  Unique request identifier for debugging
</ResponseField>

### verify()

Verify a code that was previously sent.

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

#### Parameters

<ParamField body="verification_id" type="string" required>
  The verification ID returned from the `send()` method
</ParamField>

<ParamField body="code" type="string" required>
  The verification code to check. Must be a numeric string between 4-10 digits.
</ParamField>

#### Returns

<ResponseField name="success" type="boolean">
  Always `true` for successful requests (even if the code is invalid)
</ResponseField>

<ResponseField name="verified" type="boolean">
  `true` if the code was correct and not expired, `false` otherwise
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable result message. Possible values:

  * `"Code verified successfully"`
  * `"Invalid code"`
  * `"Code expired"`
  * `"Code already used"`
</ResponseField>

<ResponseField name="request_id" type="string">
  Unique request identifier for debugging
</ResponseField>

## Examples

### Complete Verification Flow

<CodeGroup>
  ```javascript Node.js theme={null}
  import { EasyOTP } from '@easy-otp/sdk';

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

  async function verifyPhoneNumber(phoneNumber) {
    try {
      const sendResult = await client.send({
        channel: 'sms',
        recipient: phoneNumber,
        message: 'Your verification code is: {code}',
        expires_in: 300
      });
      
      console.log('Code sent! Verification ID:', sendResult.verification_id);
      
      return sendResult.verification_id;
    } catch (error) {
      console.error('Failed to send code:', error.message);
      throw error;
    }
  }

  async function checkVerificationCode(verificationId, code) {
    try {
      const verifyResult = await client.verify({
        verification_id: verificationId,
        code: code
      });
      
      if (verifyResult.verified) {
        console.log('Code verified successfully!');
        return true;
      } else {
        console.log('Verification failed:', verifyResult.message);
        return false;
      }
    } catch (error) {
      console.error('Failed to verify code:', error.message);
      throw error;
    }
  }

  const verificationId = await verifyPhoneNumber('+1234567890');
  const isValid = await checkVerificationCode(verificationId, '123456');
  ```

  ```typescript TypeScript theme={null}
  import { EasyOTP } from '@easy-otp/sdk';

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

  interface VerifyResult {
    success: boolean;
    verified: boolean;
    message: string;
    request_id: string;
  }

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

  async function verifyPhoneNumber(phoneNumber: string): Promise<string> {
    const result = await client.send({
      channel: 'sms',
      recipient: phoneNumber,
      message: 'Your verification code is: {code}',
      expires_in: 300
    }) as VerificationResult;
    
    return result.verification_id;
  }

  async function checkVerificationCode(
    verificationId: string,
    code: string
  ): Promise<boolean> {
    const result = await client.verify({
      verification_id: verificationId,
      code: code
    }) as VerifyResult;
    
    return result.verified;
  }
  ```
</CodeGroup>

### Sending via Different Channels

<CodeGroup>
  ```javascript SMS theme={null}
  const result = await client.send({
    channel: 'sms',
    recipient: '+1234567890',
    message: 'Your Acme Corp verification code is: {code}',
    expires_in: 300
  });
  ```

  ```javascript Email theme={null}
  const result = await client.send({
    channel: 'email',
    recipient: 'user@example.com',
    subject: 'Verify Your Acme Corp Account',
    message: 'Your verification code is: {code}. This code expires in 5 minutes.',
    expires_in: 600
  });
  ```

  ```javascript Voice theme={null}
  const result = await client.send({
    channel: 'voice',
    recipient: '+1234567890',
    message: 'Your verification code is: {code}',
    expires_in: 300
  });
  ```
</CodeGroup>

### Error Handling

The SDK throws errors for failed requests. Always wrap API calls in try-catch blocks:

```javascript theme={null}
import { EasyOTP } from '@easy-otp/sdk';

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

try {
  const result = await client.send({
    channel: 'sms',
    recipient: '+1234567890',
    message: 'Your verification code is: {code}'
  });
  
  console.log('Success:', result.verification_id);
} catch (error) {
  if (error.status === 401) {
    console.error('Invalid API key');
  } else if (error.status === 402) {
    console.error('Insufficient credits');
  } else if (error.status === 429) {
    console.error('Rate limit exceeded:', error.retry_after);
  } else {
    console.error('Error:', error.message);
  }
}
```

### Express.js Integration Example

```javascript theme={null}
import express from 'express';
import { EasyOTP } from '@easy-otp/sdk';

const app = express();
app.use(express.json());

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

const sessions = new Map();

app.post('/api/send-code', async (req, res) => {
  try {
    const { phoneNumber } = req.body;
    
    const result = await client.send({
      channel: 'sms',
      recipient: phoneNumber,
      message: 'Your verification code is: {code}',
      expires_in: 300
    });
    
    const sessionId = generateSessionId();
    sessions.set(sessionId, {
      phoneNumber,
      verificationId: result.verification_id
    });
    
    res.json({ sessionId });
  } catch (error) {
    res.status(error.status || 500).json({
      error: error.message
    });
  }
});

app.post('/api/verify-code', async (req, res) => {
  try {
    const { sessionId, code } = req.body;
    const session = sessions.get(sessionId);
    
    if (!session) {
      return res.status(400).json({ error: 'Invalid session' });
    }
    
    const result = await client.verify({
      verification_id: session.verificationId,
      code: code
    });
    
    if (result.verified) {
      sessions.delete(sessionId);
      res.json({ success: true });
    } else {
      res.json({ success: false, message: result.message });
    }
  } catch (error) {
    res.status(error.status || 500).json({
      error: error.message
    });
  }
});
```

## Error Handling

The SDK throws errors for failed API requests. Error objects include:

* `message`: Human-readable error message
* `status`: HTTP status code
* `request_id`: Unique request identifier for debugging
* `retry_after`: Seconds to wait before retrying (for rate limit errors)

### Common Error Codes

| Status Code | Meaning               | Solution                          |
| ----------- | --------------------- | --------------------------------- |
| `400`       | Bad Request           | Check your request parameters     |
| `401`       | Unauthorized          | Verify your API key is correct    |
| `402`       | Payment Required      | Add credits to your account       |
| `403`       | Forbidden             | API key is disabled               |
| `404`       | Not Found             | Verification ID doesn't exist     |
| `429`       | Rate Limit Exceeded   | Wait for `retry_after` seconds    |
| `500`       | Internal Server Error | Contact support with `request_id` |

## TypeScript Support

The SDK includes full TypeScript definitions. Import types as needed:

```typescript theme={null}
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}'
};

const result = await client.send(sendOptions);
```

## Best Practices

<Tip>
  **Store API keys securely**: Use environment variables and never commit them to version control.
</Tip>

<Tip>
  **Handle errors gracefully**: Always wrap SDK calls in try-catch blocks and provide meaningful error messages to users.
</Tip>

<Tip>
  **Use appropriate expiration times**:

  * SMS/Voice: 2-5 minutes
  * Email: 10-15 minutes
</Tip>

<Warning>
  **Keep verification IDs server-side**: Never expose verification IDs in URLs or client-side code. Store them server-side associated with user sessions.
</Warning>

<Note>
  **Rate limiting**: The SDK automatically handles rate limit responses. Check for `retry_after` in error responses to inform users when they can retry.
</Note>

## Additional Resources

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/api-reference/introduction">
    Complete REST API documentation
  </Card>

  <Card title="Quickstart Guide" icon="rocket" href="/quickstart">
    Get started in 5 minutes
  </Card>

  <Card title="NPM Package" icon="package" href="https://www.npmjs.com/package/@easy-otp/sdk">
    View on npm
  </Card>

  <Card title="Support" icon="life-ring" href="mailto:support@easyotp.dev">
    Get help from our team
  </Card>
</CardGroup>
