Skip to content
Email OTP

Email OTP in two calls: send and verify.

SignOps makes the code, emails it and checks it. No code to store, no resend timer to build, no bounce to chase.

  • 500 codes free to try
  • 1,000 a month on Starter
  • From our domain or yours
The code

Send, then verify. That is all of it.

Send returns an otp_id. Verify answers true once, then the code is gone. Expiry, tries, resend waits and limits are handled before your server hears about it.

  • Codes stored only as a hash, compared in constant time.
  • Ten minutes, five tries, thirty seconds between resends.
  • Limits per address and per IP, with Turnstile on your form if you want it.
otp.ts
// Send: we make the code, hash it and email it.
const { otp_id } = await signops.otp.send({
  email: "ananya@example.in",
  app_name: "Kirana Express",
});

// Check: true once, then the code is gone.
const { valid } = await signops.otp.verify({
  otp_id,
  code: req.body.code,
});
Our domain or yours

Start on ours. Move to yours on Pro.

The shared domain works the minute you sign up. Your own domain takes three DNS records and sends from your address, in your template.

Every planShared domaincodes@mail.signops.dev
ProYour own domainnoreply@kiranaexpress.in
Hindi

The code in your user's language.

Pass language: "hi" and the email arrives in Hindi, subject and all. The code itself stays in digits anyone can type.

Deliverability

One bad sender cannot slow your codes.

Every SignOps customer sends under their own reputation in Amazon SES. Addresses that bounce or complain are suppressed for your app, and sending pauses before a problem reaches anyone else.

  • SPF, DKIM and DMARC set up on the shared domain, and checked on yours.
  • Bounces and complaints reach your webhook as they happen.
  • Disposable addresses blocked per app if you switch it on.
The numbers

Details and limits

Code
6 digits, made by SignOps, stored only as a hash.
Expiry
10 minutes.
Wrong tries
5, then the code is spent and a new one has to be sent.
Resend wait
30 seconds between codes to the same address.
Limits
5 codes an hour per email address and 20 an hour per IP address, both changeable per app.
Languages
English and Hindi.
Sent through
Amazon SES, with a separate sending reputation for every customer.
Shared domain
Codes from codes@mail.signops.dev with the locked template: the code and your app's name, no links.
Your own domain
On Pro: add the DKIM records we give you, send from your own address with your own template and logo.
Bounces and complaints
Bounced and complaining addresses are suppressed for your app. Sending pauses if bounces pass 5% or complaints pass 0.1%.
Price
Free plan: 500 codes once, to try. Starter and Pro: 1,000 codes a month included, then Rs 0.03 a code, Rs 0.025 above 1 lakh and Rs 0.02 above 10 lakh. A resend counts as a code.

Email OTP questions

More questions? Email us and the answer goes on this page.

hello@signops.dev
Why is there no link in the shared template?

The shared domain sends for every SignOps customer. Keeping it to a code and an app name means nobody can use it to send a phishing link with our reputation. On your own domain the template is yours.

Can I send other email, like receipts?

On your own domain, yes: receipts, password reset links and other email a user expects. Newsletters and offers are not sent through SignOps; that keeps every customer's codes arriving.

Do I need to store the code?

No. SignOps keeps a hash of it with its expiry and tries. Your server keeps only the otp_id and asks whether a code is valid.

How does it compare with MSG91 and SMS?

MSG91 charges Rs 0.03 for an email OTP too; SignOps adds push, Approve and passkeys on the same account. An SMS OTP costs Rs 0.13 to 0.15, five times an email code.

Can I verify a phone number?

Not with SignOps. It checks email addresses and trusted devices. For phone numbers, keep your SMS provider for the first verification and move the logins after it to Approve.

Send your first code in five minutes.

500 codes free to try on the shared domain. Starter includes 1,000 a month.