Agent Wranglers

Recommended

Check that a number still belongs to the person

Before you text a number whose consent is older than the last check, confirm the number has not passed to someone else. Suppress it when it has.

How to do it

Carriers give disconnected numbers to new owners, and a text to the old owner's number then reaches a stranger. In the US, query the FCC's Reassigned Numbers Database with the number and the date consent was given. Under 47 CFR 64.1200(m), a sender who queried it and got "no" is not liable when that answer was wrong. Store each query's date and answer next to the consent row. Elsewhere, suppress a number on a carrier's "unknown subscriber" error, as Track what happened to each text says. Ask people to confirm their number with a code when it has been unused for a long time, such as 12 months. Keep the proof of consent as the consent records rule shows.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

SQL example

-- Must return 0 rows: US texts sent with no reassigned-number check after the consent date
SELECT s.id FROM sends s
JOIN consents c ON c.user_id = s.user_id AND c.channel = 'sms'
LEFT JOIN number_checks n ON n.phone = s.phone AND n.checked_at > c.given_at AND n.checked_at <= s.sent_at
WHERE s.channel = 'sms' AND s.phone LIKE '+1%' AND n.phone IS NULL;

JavaScript example

export async function mayTextUsNumber(phone, consentGivenAt) {
  const answer = await reassignedNumbers.query({ number: phone, date: consentGivenAt }); // 'yes' means the number changed hands
  await db.numberChecks.insert({ phone, answer, checkedAt: new Date() });
  if (answer === 'yes') await db.smsSuppressions.add(phone);
  return answer === 'no';
}

Python example

from datetime import UTC, datetime

def may_text_us_number(phone: str, consent_given_at: datetime) -> bool:
    answer = reassigned_numbers.query(number=phone, date=consent_given_at)  # "yes" means the number changed hands
    db.number_checks.insert(phone=phone, answer=answer, checked_at=datetime.now(UTC))
    if answer == "yes":
        db.sms_suppressions.add(phone)
    return answer == "no"

How to check

A test feeds the send job a US number that the database stub marks as reassigned. No text is sent, and the number is suppressed. A query finds no US text sent without a database check dated after the consent.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/notifications/text-messages/reassigned-numbers">Agent Wranglers notifications playbook</a>. In code you write, add a comment next to it with the same link.