If your login uses a one-time code sent by SMS or email, there is a failure
mode that almost nothing in a normal monitoring stack catches: the code is
generated, your auth provider returns 200, your status page stays
green — and the message never reaches the user. A carrier starts filtering your
sender, a bounce gets your domain blocked, an SMS route silently degrades, a
template trips a spam rule. Nobody can log in, and the first signal you get is a
support ticket hours later.
| What it checks | What it can't tell you |
|---|---|
| HTTP uptime check (Pingdom, UptimeRobot, Better Stack) | Only that your endpoint answered. A 200 from "send code" says nothing about delivery. |
| Your SMS/email provider's own dashboard | Their send stats. "Sent" or even "delivered to carrier" is not "landed in the user's inbox / phone". And it can't see a problem that starts one hop downstream. |
| Browser synthetic checks (Checkly, Playwright in CI) | They can drive your login form, but they can't actually receive a real SMS or read a real external inbox to confirm the code arrived. |
| Status pages | Aggregate, lagging, and usually only updated once humans already know something broke. |
The only reliable check is an end-to-end one: hold a real target, trigger your real verification send to it on a schedule, and confirm the message shows up within a few seconds.
You can build this with a rented number or a disposable inbox plus a cron job. The shape:
# pseudo-cron, every 15 min
target=$(rent_a_number_or_inbox)
trigger_your_app_verification_send "$target"
sleep 60
got_code=$(poll_target_for_new_message "$target")
[ -z "$got_code" ] && alert "OTP delivery check FAILED for $target"
The fiddly parts are renting a real number programmatically, matching the inbound message to the right check, and keeping the whole thing cheap if you run it often.
otp-watch is that check as a small API. Email checks are free; SMS monitors are €29/month for a dedicated number with unlimited checks.
# one-off email check
curl -X POST https://otpwatch.flo-voice1.com/checks \
-H 'authorization: Bearer ow_...' \
-H 'content-type: application/json' -d '{"channel":"email"}'
# => {"id":"chk_...","target":"a1b2c3@receivemail.dev","status":"pending"}
# trigger your app's verification email to that address, then:
curl https://otpwatch.flo-voice1.com/checks/chk_... -H 'authorization: Bearer ow_...'
# => {"status":"received","latencyMs":4200} (or "timed_out")
Point your CI or cron at it, fail the job on timed_out, and your
existing alerting does the rest. See the endpoints and pricing on
the front page. If you're testing an OTP integration in CI rather than
monitoring it in production, see
testing your OTP integration without burning SMS credits.
Every 15–30 minutes is enough to catch a delivery outage well before your users flood support, without generating meaningful cost or load.
Yes — to a throwaway target you own, not to a real user. The codes are discarded; only "did it arrive, and how fast" matters.
otp-watch uses UK numbers today. Multi-country delivery testing (across carriers and regions) is a different, heavier category — enterprise telecom testing services do that. otp-watch is the lightweight "is my flow working at all, right now" check.