Frequently asked questions

How to check that verification codes actually arrive: email and SMS checks, the real UK number behind SMS, pricing, timeouts, CI usage and limits.

What is otp-watch?

Synthetic monitoring for verification codes. otp-watch hands you a real UK phone number or a real email inbox, you trigger your own OTP send to it, and it tells you whether the code arrived and how long it took. Uptime monitors check that your API answered; this checks that the message actually showed up.

How do I check that my verification emails are delivered?

Get a key once, then each check is two calls:

curl -X POST https://otpwatch.flo-voice1.com/keys \
  -H 'content-type: application/json' -d '{"email":"you@example.com"}'
# => {"key":"..."}

curl -X POST https://otpwatch.flo-voice1.com/checks \
  -H 'authorization: Bearer <key>' -H 'content-type: application/json' \
  -d '{"channel":"email"}'
# => {"id":"...","status":"pending","target":"a1b2c3d4e5f6@receivemail.dev",...}

Make your app send its verification email to target, then poll:

curl https://otpwatch.flo-voice1.com/checks/<id> -H 'authorization: Bearer <key>'
# => {"status":"received","latencyMs":4210,...}  or  {"status":"timed_out",...}

What kind of phone number do SMS checks use?

A real UK mobile number on a physical SIM (EE network), not a VoIP or virtual number, so it receives codes the way your users' phones do. SMS checks work the same way as email: {"channel":"sms"}, then send your code to the returned target.

How much does it cost?

How long does a check wait before timing out?

120 seconds by default. Pass timeoutSeconds anywhere from 10 to 600 when you create the check. A check that hasn't received anything by then becomes timed_out, which is the signal your pipeline should fail on.

How do I run it from CI or a cron job?

otp-watch has no scheduler of its own: your CI or cron calls it on whatever interval you want and fails on timed_out, so your existing alerting does the paging. A minimal shell step:

ID=$(curl -s -X POST https://otpwatch.flo-voice1.com/checks -H "authorization: Bearer $OTP_WATCH_KEY" \
  -H 'content-type: application/json' -d '{"channel":"email"}' | jq -r .id)
# ...trigger your app's verification email to the check's target here...
until S=$(curl -s https://otpwatch.flo-voice1.com/checks/$ID -H "authorization: Bearer $OTP_WATCH_KEY" | jq -r .status); [ "$S" != pending ]; do sleep 5; done
[ "$S" = received ] || exit 1

For frequent SMS checks use a monitor (POST /monitors/{id}/checks) so every run reuses the same number. To test an OTP integration without paying for a real SMS on every run, see testing OTP integrations without burning SMS credits.

What are the limits?

How is this different from an uptime monitor?

An uptime monitor tells you your API returned 200. It can't tell you whether your SMS provider or email sender actually delivered the code, which is what breaks logins in practice: an expired sender ID, a template flagged as spam, a provider outage that still returns 200. otp-watch checks that last step.