On this page
When an identity or messaging provider blocks a voice or SMS code as suspected toll fraud, it has refused to send it because the request looked like revenue-share fraud: someone triggering paid calls to numbers they profit from. The block protects your bill. To keep real users flowing, limit destinations, check numbers before calling, and offer factors that don't use the phone network.
What does a suspected toll fraud block actually mean?
It means a telephony request was denied by a fraud filter. The wording varies by provider, but the idea is the same: the destination, the pattern or the volume matched what fraudsters do when they abuse verification features to generate paid traffic.
Okta documents this behaviour publicly in its developer release notes. In October 2022 it announced measures "to block suspicious SMS and Voice traffic from countries that are typically at risk of toll fraud attacks", with blocked transactions shown with a deny status in the System Log. In January 2023 it added an internal "machine-learning-based toll fraud and abuse-detection model" that blocks unusual SMS or voice requests, and in May 2023 further measures to "counter phone number-based toll fraud" (Okta, 2022; Okta, 2023).
Other identity platforms and messaging providers may run similar filters. Developers usually meet them through a support ticket: a user abroad didn't get a code, and the log says the request was denied.
Why do attackers target voice OTP?
Because it pays. Toll fraud here is a form of international revenue share fraud: the attacker controls, or shares revenue with, the numbers being called. Every call your app places to them earns them money. Our IRSF guide explains the money trail. OWASP lists "toll fraud" and "SMS pumping" as other names for cost-inflation fraud, the "mass use of functionality to illegitimately profit from chargeable supporting services" (OWASP).
Voice codes have properties attackers like:
| Property | Why it helps the attacker |
|---|---|
| Billed per minute | A longer call earns more than one text |
| Reaches more number types | Fixed, premium-rate and some special ranges can take calls but not texts |
| Often a fallback | "Call me instead" appears after SMS "fails", which bots can trigger on purpose |
| Less monitored | Teams watch SMS volumes more closely than call minutes |
| Automated end to end | A bot submits the form. Your system places the call |
OWASP's MFA guidance names the cost side directly: calls and SMS "may cost money to send", so you "need to protect against attackers requesting a large number of messages to exhaust funds" (OWASP).
What typically triggers a block?
Providers don't publish their exact rules, and they shouldn't. The public descriptions and common sense point to the same signals:
- Destination country. Traffic to countries associated with toll fraud, especially where you have little history.
- Number-range bursts. Many requests to numbers sharing the first digits.
- No completion. Codes sent or calls placed, but never entered.
- Velocity. Many requests per IP, device or session, or a sudden jump in a quiet hour.
- Special line types. Premium-rate, shared-cost or global-service numbers.
A real user abroad can match the first signal alone. That is the false positive you will hear about.
How do you keep real users from being blocked?
Don't fight the filter. Make legitimate traffic look like what it is, and give users a way around the phone network.
- Know your countries. Allow codes only to the countries where you have customers. Ask your provider how its country rules work and whether you can adjust them for markets you serve.
- Offer a non-phone factor. Passkeys and authenticator apps don't depend on telephony and aren't affected by these filters. NIST requires services that accept phone-based codes, a restricted authenticator, to offer at least one alternative that isn't restricted (NIST, 2025).
- Check before you call. Clean input and sensible line types reduce requests that look odd.
- Throttle your own endpoint. If your limits catch the bot, your provider's filter never has to.
- Explain the fallback. When a code can't be sent, tell the user what else they can do instead of showing a generic error.
What does a pre-call check look like?
Put it between "user asked for a call" and "call placed". Each step is cheap, and the paid check runs last:
| Step | Rule | Cost |
|---|---|---|
| 1. Throttle | Per number, prefix, IP, device and country; resend delay | Free |
| 2. Normalize | E.164; reject impossible numbers | Free |
| 3. Country gate | Only countries you serve; block global-service codes | Free |
| 4. Line-type check | Refuse premium-rate, shared-cost and UAN; decide on toll-free | Per conclusive check |
| 5. Call with limits | Short message, hang up after it plays, cap retries | Your telephony cost |
Step 4 with MobileValidate's carrier lookup, as a real test-mode request:
curl https://api.mobilevalidate.com/v1/lookup \
-H "Authorization: Bearer $MOBILEVALIDATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"numbers": ["+447700900001"], "checks": ["carrier"], "wait": 3}'Response (excerpt of results[0], test mode):
{"e164": "+447700900001", "country": "GB", "number_status": "valid",
"checks": {"network.carrier": {"status": "completed", "registered": true,
"attributes": {"line_type": "mobile", "carrier": "Test Carrier", "country": "GB"},
"billed": false, "reason": null}}}And the decision:
const REFUSE = new Set(["premium_rate", "shared_cost", "uan"]);
const GLOBAL_CODES = ["+881", "+882", "+883", "+979"];
function preCallDecision(r, allowedCountries) {
if (r.number_status !== "valid") return "ask_correction";
if (GLOBAL_CODES.some((p) => r.e164.startsWith(p))) return "refuse";
if (!allowedCountries.has(r.country)) return "offer_other_factor";
const line = r.checks?.["network.carrier"]?.attributes?.line_type; // undefined when unknown
if (REFUSE.has(line)) return "refuse";
return "call"; // unknown falls through to your limits
}An unknown carrier answer is free and means "no data". It shouldn't block a user on its own. Your rate limits and spend caps still apply.
Should voice be the fallback for SMS?
It can be, with conditions. Automatic fallback from SMS to voice doubles the attack surface: a bot that can make SMS "fail" gets a call for free. Safer patterns:
- Make voice an explicit choice the user makes after a delay, not an automatic retry.
- Require the SMS attempt to look genuine first: a real session, a valid mobile number, no burst on the prefix.
- Cap voice harder than SMS: fewer calls per number per day, and a lower per-country ceiling.
- Prefer a channel the user already has. A code in a messaging app the user chose doesn't create a call charge. Check that the number has an account first, as described in our WhatsApp check API guide.
What should you monitor?
Treat call minutes like money, because they are:
- Call minutes and calls per destination country, per hour, against last week.
- Average and maximum call duration for verification calls. They should be short and uniform.
- Verification rate per country: codes entered ÷ codes sent or calls placed.
- Denied requests from your provider's fraud filter, by country. A rise means either an attack or a new market with real users. Both need a decision.
- Spend against a daily cap, with an alert well below it.
If you see blocks for a country where you do have customers, collect examples and talk to your provider. That is more reliable than switching protections off.
How do you investigate a blocked request?
When a user reports that no code arrived and your logs show a fraud denial, work through it the same way every time. It keeps support answers consistent and gives your provider useful evidence.
- Find the event. Look up the denied request in your provider's log and note the destination country, the number (masked), the time and the channel.
- Check the number. Is it valid E.164? What line type and country does a lookup return? A premium-rate or global-service number explains the block by itself.
- Check the session. Did the request come from a real session with normal behaviour, or from a burst of requests from one IP or device?
- Look for neighbours. Were there other requests to numbers with the same first digits in the same hour? A cluster points to an attack, not to one unlucky user.
- Decide. For a genuine user, offer another factor right away. If you see the same false positive repeatedly for a market you serve, send the examples to your provider and ask how to adjust the rule for that country.
- Record the outcome, so you can see whether blocks in a country are mostly attacks or mostly customers.
If deliveries fail for reasons other than a fraud filter, the cause tree in why SMS messages aren't delivered covers invalid numbers, unreachable phones and carrier filtering.
What are the key takeaways?
- A suspected toll fraud block is a provider's fraud filter denying a voice or SMS code that looked like revenue-share fraud.
- Voice is attractive to attackers because it is billed per minute and often triggered automatically as a fallback.
- Keep real users flowing with a country allow-list, a non-phone factor, clean inputs and your own rate limits.
- A pre-call check (normalize, country gate, line type) removes special-rate numbers before you pay. Unknown answers are free and shouldn't block.
- Make voice an explicit, capped choice, and watch minutes, durations and verification rates per country.
For the wider fraud picture behind these calls, read IRSF: international revenue share fraud, explained. For the text-message side, see SMS pumping: how it works and how to stop it.
Sources
- Okta Developer release notes (2022): Additional measures for suspicious SMS and Voice requests — Okta, 2022
- Okta Developer release notes (2023): toll fraud and abuse-detection measures — Okta, 2023
- OAT-003 Cost-Inflation Fraud (OWASP Automated Threats to Web Applications) — OWASP, 2026
- Multifactor Authentication Cheat Sheet — OWASP
- NIST SP 800-63B-4: Digital Identity Guidelines — Authentication and Authenticator Management — NIST, 2025
Frequently asked questions
Why did my identity provider block a voice or SMS code as toll fraud?
Providers watch telephony traffic for patterns that look like revenue-share fraud: unusual destination countries, bursts to one number range, many requests with no completed verification. When a request matches, it is denied and usually logged as such, even if a real user sent it.
Is voice OTP riskier than SMS OTP?
For cost fraud, often yes. A call is billed by duration and can reach number types that can't receive texts, so a single abused call can cost more than a text. Voice also tends to be the fallback that attackers trigger after SMS fails.
How do I stop real users being blocked?
Allow codes only to the countries you serve, give users a non-phone factor such as a passkey or authenticator app, and check the number before you call so that legitimate traffic looks normal. Talk to your provider before loosening its protections.
Does a number check stop toll fraud on its own?
No. It removes special-rate line types and impossible numbers before you pay. Country limits, per-prefix rate limits, call-duration caps and spend caps do the rest.
Related services and guides
More from the blog
All articlesFraud prevention
IRSF: international revenue share fraud, explained
How international revenue share fraud turns your calls and texts into someone else's income, how it differs from SMS pumping, and how to cap your exposure.
7 min read
Fraud prevention
OTP fraud prevention: the checks to run before you send a code
A practical pre-send pipeline for one-time passcodes: normalize, check line type, messenger presence and reputation in one request, then decide.
8 min read
Fraud prevention
SMS pumping: how it works and how to stop it
How SMS pumping (artificially inflated traffic) drains OTP budgets, the signals that give it away, and a layered checklist to stop it before you pay.
8 min read

