Skip to content
Gurdx

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, disposable and blacklisted.
  • 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#

  1. Before sending an OTP, normalise the number and call phone validation with countryCode when you know it.
  2. Reject numbers that are not valid, are disposable or are blacklisted.
  3. Check the requesting IP. Bots and Tor sources should get a CAPTCHA or be refused.
  4. Apply your own limits per phone, per IP and per destination country per hour.
  5. 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