Skip to content
imessageapi

Compliance

The rules you cannot design around.

Messaging is a permission channel. The requirements are not onerous, but they are load-bearing — and every one of them also happens to be good practice that improves your results.

Not legal advice. This is the operational shape of the problem so you know what to ask a lawyer about. Rules vary by jurisdiction and change over time.

The checklist

Ten things to have in place before your first customer send

If you can tick all ten, you are in better shape than most businesses many times your size.

  1. 01

    Capture consent explicitly

    Its own unticked checkbox, clear language beside it, never a condition of purchase, never buried in a terms link.

  2. 02

    Separate marketing from transactional

    Two scopes, stored separately. Someone who wants delivery updates has not agreed to a coupon blast.

  3. 03

    Store proof, not just a boolean

    Timestamp, exact disclosure wording, source form, IP or staff member, and every subsequent status change.

  4. 04

    Automate STOP before your first send

    STOP, UNSUBSCRIBE, CANCEL, END, QUIT — all of them, instantly, with no human in the loop.

  5. 05

    Answer HELP

    Business name, a way to reach a human, and opt-out instructions. It is required and it is cheap to build.

  6. 06

    Identify yourself

    Name the business in the first message of any conversation. An unidentified text is a deleted text.

  7. 07

    Respect local quiet hours

    8am to 9pm in the recipient's time zone, not your server's. Queue messages outside the window; never drop them.

  8. 08

    Cap frequency at the send layer

    Enforced centrally, not per campaign — otherwise three well-behaved campaigns become one bad week.

  9. 09

    Register your traffic

    US business SMS on 10-digit numbers needs carrier registration. Unregistered traffic gets filtered or blocked outright.

  10. 10

    Own the opt-out list

    In your database, not only in a vendor dashboard. Switching providers must not resurrect people who unsubscribed.

Consent

Two levels, and the gap between them is where trouble lives

Most compliance failures at small businesses are not deliberate. They are a marketing message sent to a list that only ever consented to transactional ones.

Transactional

Express consent

The customer is expecting this message because of something they did — booked, ordered, or asked. Appointment reminders, order confirmations, delivery notices, invoice due dates.

Generally sufficient: they gave you the number for this purpose.

Marketing

Express written consent

Offers, promotions, win-backs, announcements. In the US this requires an explicit, provable, written agreement to receive marketing texts at that number.

An existing business relationship is not consent. A number on an invoice is not consent.

The buried-checkbox trap

Consent to marketing texts cannot be a condition of buying something, cannot be pre-ticked, and cannot be hidden inside a terms link. It needs its own unticked checkbox with clear language next to it. This is the single most common way small businesses end up out of compliance without ever intending to.

In your codebase

Two things to build first

Opt-out handling and a consent record you own. Everything else can wait; these cannot.

opt-out — wire this before your first send
const STOP_WORDS = new Set([
"stop", "stopall", "unsubscribe", "cancel",
"end", "quit", "revoke", "optout",
]);
 
export async function handleInbound(from: string, text: string) {
const first = text.trim().toLowerCase().split(/\s+/)[0];
 
if (STOP_WORDS.has(first)) {
await optOut(from); // persist BEFORE replying
await send(from, "You're unsubscribed. No more messages from Acme.");
return;
}
 
if (first === "help") {
await send(from, "Acme support: (555) 010-0000. Reply STOP to unsubscribe.");
return;
}
 
await routeToInbox(from, text);
}
consent record — own this table
// This outlives every vendor you will ever use. Keep it yours.
type ConsentRecord = {
phone: string; // E.164, always
status: "opted_in" | "opted_out" | "unknown";
scope: "marketing" | "transactional" | "both";
capturedAt: string; // ISO 8601
source: string; // which form, which page, which staff member
disclosureText: string; // the exact words they agreed to
ip?: string;
history: {
at: string;
event: "opt_in" | "opt_out" | "scope_change";
channel: "web" | "sms" | "in_person";
}[];
};

The compliance dividend

Clean lists engage better, get fewer spam reports, and keep healthier sender reputation with carriers. Businesses that do this properly get better numbers, not just safer ones — a filtered message is worth exactly zero.

Carrier filtering

The rules nobody tells you about, enforced silently

SMS filtering happens at the carrier, before delivery, with no bounce and no appeal. Your API call returns success and the message simply never arrives.

Register your traffic

US business SMS on standard 10-digit numbers requires registration tying your traffic to a verified business. Unregistered traffic is heavily filtered. Start it early — approval is not instant.

Never use a public shortener

Shared shortener domains carry every spammer's reputation alongside yours. Use a branded short domain on a domain you own. This is the highest-impact single change available.

Write like a person

No ALL CAPS, no rows of exclamation marks, no $$$. One link per message. Identify your business. Vary at least the name across a bulk send.

Go deeper

Two guides cover the operational detail

Consent capture and opt-out handling in one; timing, frequency caps and the opt-out rate you should be watching in the other.