Agent Wranglers

Text messages Required

Guard text sending against SMS pumping

Limit who can make you send a text, to which countries, and how often. SMS pumping fraud sends your codes to premium numbers and bills you.

How to do it

Allow only the countries where you have customers in the provider's geo settings. Rate-limit code requests per phone number, per number prefix, per IP address and per account, such as 3 per number per hour. Require a form check, such as a challenge, before the first text. Alert when sends to one country or prefix jump, or when the share of codes entered falls below a set line, such as 50 percent. Many providers offer pumping protection, such as Twilio Verify Fraud Guard. General limits live in limit requests per client.

Example

const MAX_CODES_PER_NUMBER_PER_HOUR = 3;
const ALLOWED_COUNTRIES = new Set(['SE', 'NO', 'DK', 'FI']);

export async function mayTextCode(phone, ip) {
  if (!ALLOWED_COUNTRIES.has(phone.country)) return false;
  const recent = await limiter.hits(`sms:${phone.e164}`, 3600);
  return recent < MAX_CODES_PER_NUMBER_PER_HOUR && (await limiter.hits(`sms-ip:${ip}`, 3600)) < 10;
}
MAX_CODES_PER_NUMBER_PER_HOUR = 3
ALLOWED_COUNTRIES = {"SE", "NO", "DK", "FI"}

def may_text_code(phone, ip: str) -> bool:
    if phone.country not in ALLOWED_COUNTRIES:
        return False
    return (limiter.hits(f"sms:{phone.e164}", 3600) < MAX_CODES_PER_NUMBER_PER_HOUR
            and limiter.hits(f"sms-ip:{ip}", 3600) < 10)

How to check

A test asks for a code to a number in a blocked country and expects a refusal. A script asks for 10 codes to one number in a minute and gets at most 3. An alert fires on a daily cost above budget.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers notifications playbook: https://agentwranglers.se/playbook/notifications/text-messages/sms-pumping.