Docs / Use-case guides
SMS fraud prevention
Stop fake and premium-rate numbers from draining your SMS and OTP budget.
The problem#
SMS pumping, also called artificially inflated traffic, makes your app send one-time codes to numbers an attacker controls, often in expensive destinations, and you pay for every message. Fake and disposable numbers also bypass phone-based sign-up limits.
Signals to combine#
- Phone validation:
isValid,carrier,disposableandblacklisted. - IP reputation for the requester: bots and hosting networks are common sources.
- Country lookup when you want to enforce a list of destination countries.
- Blacklists of phone numbers and IPs that already abused you.
Integration flow#
- Before sending an OTP, normalise the number and call phone validation with
countryCodewhen you know it. - Reject numbers that are not valid, are disposable or are blacklisted.
- Check the requesting IP. Bots and Tor sources should get a CAPTCHA or be refused.
- Apply your own limits per phone, per IP and per destination country per hour.
- Send the SMS only when all checks pass, and add numbers from confirmed abuse to a phone blacklist.
<?php
function canSendOtp(string $phone, string $country, string $ip): bool {
$headers = 'Authorization: Bearer ' . getenv('GURDX_KEY');
$get = fn ($path, $q) => json_decode(file_get_contents(
'https://gurdx.cretip.com/api/' . $path . '?' . http_build_query($q), false,
stream_context_create(['http' => ['header' => $headers, 'timeout' => 4]])
), true);
$p = $get('scoring/phone', ['phone' => $phone, 'countryCode' => $country, 'userID' => $phone]);
if (($p['status'] ?? '') !== 'success') return false; // fail closed
if (! $p['data']['isValid'] || ($p['data']['disposable'] ?? false) || $p['data']['blacklisted']) {
return false;
}
$i = $get('lookup/ip/threats', ['ip' => $ip]);
return ! ($i['data']['threats']['isBot'] ?? false) && ! ($i['data']['threats']['isTor'] ?? false);
}
Suggested decisions#
| Result | Action |
|---|---|
| Valid mobile number, clean IP | Send |
| Valid but hosting or proxy IP | Add a CAPTCHA before sending |
| Invalid, disposable or blacklisted number | Do not send |
| Many requests for one prefix in a short time | Pause that destination and alert |
Failing closed on an API error protects your budget, but a short retry or a CAPTCHA fallback keeps genuine users moving.
Note: Phone validity does not prove ownership. Keep the OTP itself, and consider reduced limits for countries you rarely serve.
Use custom rules to mark whole prefixes or carriers invalid, and enable alerts for spam_phone events. Related: Fake account prevention.
Found a mistake? Tell us on the contact page. Contact