Quick take
Do not debug OTP delivery from the login screen alone. Debug each attempt as a message lifecycle with normalized phone numbers, sender identity, timestamps, provider IDs, delivery receipts, retry decisions, and support-visible failure reasons.
Common OTP delivery failure points
Use this table to turn a user complaint into a concrete investigation.
| Symptom | Likely area | What to check |
|---|---|---|
| Code never arrives | Number normalization or route | Confirm E.164 formatting, destination country, provider message ID, and initial accepted or queued state. |
| Code arrives late | Carrier route or handset availability | Compare accepted, sent, delivered, expired, and retry timestamps by country and carrier. |
| Resend makes things worse | Product logic | Check resend cooldown, duplicate sends, idempotency key behavior, and whether the old code remains valid. |
| Only some countries fail | Sender identity or country route | Review sender approval, 10DLC/toll-free/sender ID readiness, and country-specific errors. |
| Valid users are blocked | Fraud controls | Inspect rate limits, country rules, suspicious prefixes, spend caps, and SMS pumping protections. |
Debug sequence
Start with the exact attempt, not the user account in general. One user may have multiple sends, resends, expired codes, and provider callbacks.
The support view should show the recipient, normalized country, sender identity, template, provider message ID, current status, raw callback history, and the next recommended action.
- Find the most recent OTP attempt.
- Check whether the API request was accepted or rejected.
- Wait for a delivery signal before promising delivery.
- Separate delivery failure from code validation failure.
- Escalate only with message ID, country, carrier metadata, timestamps, and raw event evidence.
Make every OTP attempt traceable
Use Notilify to connect OTP attempts, delivery events, sender identity, and support timelines.