minimoth

Quickstart

Who this is for: MiniMoth is designed for indie developers, startups, and anyone building for Indian users who needs WhatsApp/SMS OTP without the overhead of a WhatsApp Business Account, DLT registration, or session management.

Delivery: Every OTP is sent over WhatsApp first, falling back to SMS automatically if WhatsApp delivery fails. Both channels run on MiniMoth's own infrastructure — a verified WhatsApp Business Account and a TRAI DLT-registered SMS sender — so you never set up a WABA, register a sender ID, or manage compliance for either one. You get one simple API; MiniMoth handles both channels behind it.

How it works
1

Your server calls POST /v1/otp/send

MiniMoth generates a 6-digit code and delivers it via WhatsApp first, falling back to SMS automatically if WhatsApp fails. You are charged ₹0.35 at this point.

~

Optionally check delivery status

Call GET /v1/otp/status/:otp_id using the otp_id from step 1. Tells you whether the code landed on WhatsApp or SMS. Useful for showing delivery confirmation in your UI before the user enters the code.

2

User enters the code in your app

You collect the 6-digit code from your UI and send it to your server.

3

Your server calls POST /v1/otp/verify

MiniMoth checks the code and returns an access_token and refresh_token on success.

Phone number verified — user is authenticated

Use the tokens to validate every subsequent request, or bring your own session system. See Sessions and Recipes.

1. Get an API key

Create a project in the dashboard. Every project gets an API key in the format mm_live_..., shown once on creation and available any time under Project Settings.

2. Send and verify an OTP with the Node.js SDK

@minimoth/sdk-node is the fastest way in — it handles phone normalisation, token management, and auto-refresh, so there's no boilerplate around the raw API.

npm install @minimoth/sdk-node
import { MiniMoth } from '@minimoth/sdk-node'

const mm = new MiniMoth({
  apiKey: process.env.MINIMOTH_API_KEY,  // mm_live_...
})

// 1. Send OTP — delivered via WhatsApp first, falls back to SMS automatically
const { otpId } = await mm.otp.send({ phone: '+919876543210' })

// 2. Verify the code — never throws, always returns a result
const result = await mm.otp.verify({ phone: '+919876543210', otp: '123456' })
if (!result.valid) {
  // result.code: 'INVALID_OTP' | 'OTP_NOT_FOUND' | 'VERIFY_RATE_LIMITED' | ...
} else {
  // Phone is verified — result.accessToken, result.refreshToken, result.sessionId
}

Accepted phone formats: +91XXXXXXXXXX or bare 10 digits XXXXXXXXXX. The 10-digit number must start with 6–9.

accessToken is valid for 5 minutes. refreshToken is valid for your project's configured refresh window (default 10 days, max 30 days). See the full Node.js SDK guide → for auto-refresh, session validation, and framework examples.

Using another language, or calling the API directly

Not on Node.js, or want to talk to the REST API yourself? Two endpoints, no SDK required:

Send an OTP

const res = await fetch('https://api.minimoth.dev/v1/otp/send', {
  method: 'POST',
  headers: { 'X-Api-Key': 'mm_live_...', 'Content-Type': 'application/json' },
  body: JSON.stringify({ phone: '+919876543210' }),
})
const { otp_id } = await res.json()
// otp_id can be used with GET /v1/otp/status/:otp_id to check delivery

The response includes an otp_id that can be used to poll delivery status.

Check delivery status (optional)

// Optional — poll delivery status before showing "OTP sent" in your UI
const res = await fetch(`https://api.minimoth.dev/v1/otp/status/${otp_id}`, {
  headers: { 'X-Api-Key': 'mm_live_...' },
})
const status = await res.json()
// { otp_id, channel: 'whatsapp' | 'sms', status: 'queued' | 'delivered' | 'failed', delivered_at }

MiniMoth first tries WhatsApp; if that fails, SMS is sent automatically. The channel field tells you which was used. This step is optional — you can call otp/verify directly without checking status first.

Verify the code

const res = await fetch('https://api.minimoth.dev/v1/otp/verify', {
  method: 'POST',
  headers: { 'X-Api-Key': 'mm_live_...', 'Content-Type': 'application/json' },
  body: JSON.stringify({ phone: '+919876543210', code: '123456' }),
})
const { access_token, refresh_token, expires_at } = await res.json()
// expires_at is the access_token expiry (ISO 8601)

access_token is valid for 5 minutes. refresh_token is valid for your project's configured refresh window (default 10 days, max 30 days). See Sessions for how to refresh and validate tokens.

Just need OTP delivery? You don't have to use MiniMoth's session tokens at all. If you already have your own auth system, call otp/send + otp/verify to confirm the phone number, then create a session in your own system. See the OTP-only recipe.

Try the full OTP flow interactively in the sandbox — no SMS sent, no credits consumed. The same Playground also has a live test to send a real OTP to your phone (uses your credits).

Test in Playground →