One-time confirmation codes
without SMS gateways

A 6-digit code lands in Telegram or Max in milliseconds. Zero cost per send, atomic verification, protection from race conditions and brute-force — built in.

· TTL 5 min, up to 5 attempts, 1 active code per user

@zapnotybot
OTP code
→ Press "Send code"
POST /v1/otp/send TTL 5 min · 5 attempts
≈ $0
per OTP vs $0.05-0.10 per SMS
< 2 s
from send to read
100%
delivery vs ~95% for SMS
6
digits, FOR UPDATE against races

Why SMS no longer works

Classic SMS gateway problems

$0.05-0.10 per code

At 10,000 signups/month — $500-1000 just for SMS. Scales linearly with audience, crushes unit economics.

Doesn't always arrive

Carriers filter promotional traffic, codes disappear in roaming, delays of 30-60 seconds. Users bounce before completing signup.

Fraud and SIM-swap

SMS is intercepted via social engineering and SIM swapping. Telegram and Max are secured by their own 2FA.

What's inside

Everything for production-grade OTP

Atomic verification

SQL query with FOR UPDATE and CTE checks the code and increments attempts in a single transaction. Race conditions are impossible.

Custom template

Variables {{code}}, {{minutes}}, HTML formatting, multilingual. Your brand in the message, not Zapnoty.

Brute-force protection

Max 5 verification attempts, one active code per subscriber, TTL 5 minutes. On exhaustion — automatic invalidation.

Rate limit on sending

300 requests/min per project, built-in sliding window via Redis. No need to build your own counters.

Test UUID support

subscriber_id = 00000000-... — test OTP without a real user. Handy for automated tests and CI.

Send webhook

delivery.success / delivery.failed with a reason. Log OTP flows on your side without separate tracking.

How it works

Two endpoints and all the OTP logic

01

POST /v1/otp/send

Pass subscriber_id. Zapnoty generates a 6-digit code, stores a SHA-256 hash, sends via your template.

02

User receives the code

The code arrives in Telegram or Max in milliseconds. HTML format — <code>482916</code> — one-tap copy.

03

POST /v1/otp/verify

Submit subscriber_id + code. Zapnoty atomically compares hashes, bumps attempt counter, returns verified: true/false.

FAQ

Frequently asked

We recommend a fallback — offer Telegram or Max at signup. Whoever doesn't use messengers — fall back to SMS via your existing gateway. Zapnoty doesn't remove SMS, it cuts its share to 10-15%.

Yes. Verification is an atomic CTE with FOR UPDATE: checking the code and incrementing attempts happen in one transaction. Two concurrent requests with different codes are handled correctly.

Currently — 6 digits, the OTP standard. If you need 4 or 8 digits — ping support, we'll add a setting.

Subscription auto-deactivates. You get a delivery.failed webhook — show the user "unblock @zapnotybot and try again".

No. Only SHA-256 hash is stored. The code itself exists in memory during send and in the user's chat.

1 credit per OTP code. On the "Basic" plan (700 credits for 590 ₽/month) that's ≈ 0.84 ₽ per code — 5-7× cheaper than SMS. On larger plans — down to 0.14 ₽.

Free to start

Hook up in 5 minutes

No credit card. 100 free credits per month — enough to try every feature.