> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracklysms.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Compliance & TCPA

> Handle opt-outs and stay compliant with regulations

Compliance is critical in SMS marketing. Trackly SMS provides tools to manage opt-outs and stay within regulations.

## Opt-Out Handling

Trackly evaluates **every inbound message** for opt-out intent before it reaches your inbox. A matched opt-out takes effect immediately — the contact is unsubscribed and every future send to that number is blocked automatically.

### Detection layers

Opt-out intent is matched in priority order; the first layer to match wins. Opt-out, spam, complaint, and abuse signals always take precedence over re-subscribe (START) and HELP keywords, and are evaluated before any custom keyword auto-responses.

<Steps>
  <Step title="Exact keywords">
    A message that is *only* a recognized keyword (after normalization) is an instant opt-out.

    | Category             | Keywords                                                              |
    | -------------------- | --------------------------------------------------------------------- |
    | Stop                 | `STOP` `STOPALL` `STOP ALL` `END` `QUIT` `CANCEL` `REVOKE`            |
    | Unsubscribe / remove | `UNSUBSCRIBE` `UNSUB` `OPT OUT` `OPTOUT` `REMOVE` `REMOVE ME`         |
    | Strong intent        | `BLOCK` `BLOCKED` `WRONG` `DO NOT TEXT` `DO NOT CONTACT` `DON'T CALL` |

    All seven per-se revocation keywords from the FCC's 2025 revocation rule (47 CFR § 64.1200(a)(10)) — stop, quit, end, revoke, opt out, cancel, unsubscribe — are honored.
  </Step>

  <Step title="Glued STOP variants">
    Any single-word message that *starts with* `stop` is an instant opt-out — `STOP2END`, `STOPEND`, `STOP2`, `STOPTEXTING`. This catches recipients who run the words together and campaigns whose copy instructs a nonstandard keyword. (Longer sentences are not affected: "stopwatch sale today" does not opt out.)
  </Step>

  <Step title="Common misspellings">
    Fat-finger and autocorrect variants of STOP are caught — `STPO`, `STORP`, `STTOP`, `STP`, `STIP`, `SUTOP`, `ETOP`, and \~15 more.
  </Step>

  <Step title="Natural-language phrases">
    Free-text opt-outs are matched by pattern: "stop texting me", "do not text", "no more texts", "take me off your list", "remove me from your list", "why are you texting me", "you keep texting me".
  </Step>

  <Step title="Obfuscated variants">
    Character-swapped and spaced evasions such as `st0p` and `sto p` are normalized and caught.
  </Step>

  <Step title="Spam, complaint & abuse">
    "spam", "scam", "junk", "stop spamming", "reporting you", "do not call", "speak to a representative", and profanity are treated as opt-outs by default and labeled for reporting.
  </Step>
</Steps>

### Matching rules

<AccordionGroup>
  <Accordion title="Case, spacing & punctuation are ignored">
    Text is Unicode-normalized, lowercased, trimmed, and stripped of surrounding punctuation before matching. `STOP`, `Stop!`, and `stop` all match.
  </Accordion>

  <Accordion title="Emoji reactions & iPhone tapbacks are NOT opt-outs">
    Emoji-only replies and iPhone tapbacks (e.g. `Loved "…"`, `👍 to "…"`) are ignored — even when they quote one of your messages that contains the word STOP. Only text the recipient actually types is evaluated.
  </Accordion>

  <Accordion title="Quoted & forwarded text is stripped">
    If a reply quotes a previous message (lines beginning with `>`, "On … wrote:", email headers), the quoted block is removed before matching, so a quoted "Reply STOP to opt out" does not cause a false opt-out. The recipient's own added text is still checked.
  </Accordion>

  <Accordion title="Compliance-first on ambiguous phrases">
    To stay on the safe side of TCPA, any message containing the word "stop" is treated as an opt-out — including phrases like "stop by", "stop in", or "stop over". Trackly always errs toward honoring the opt-out.
  </Accordion>

  <Accordion title="HELP is exact-match only">
    `HELP` and `INFO` trigger the help auto-response only when sent on their own. Conversational phrases like "please help" or "help me" are treated as normal replies.
  </Accordion>
</AccordionGroup>

### What happens on opt-out

1. The inbound message is classified as an opt-out.
2. The contact is marked unsubscribed (`active = false`, `consent_status = opted_out`) with the reason and timestamp recorded.
3. Trackly sends the carrier-mandated opt-out confirmation reply.
4. The number is added to the suppression list — **all** future sends are blocked, and an `unsubscribe` webhook fires.

### Re-Subscription

A previously unsubscribed contact can opt back in by texting a START keyword: `START`, `UNSTOP`, `SUBSCRIBE`, `RESUBSCRIBE`, `OPTIN`, or `OPT IN`. This reactivates the contact (`consent_status = re_opted_in`) and clears the suppression entry.

<Note>
  `YES` is intentionally **not** a re-subscribe keyword — it's too common in normal conversation to safely treat as renewed consent. Re-subscription requires an explicit START-family keyword.
</Note>

Contacts can also re-subscribe by signing up again through your opt-in forms, or by an admin re-adding them with documented consent.

<Accordion title="Full opt-out & keyword reference">
  **Opt-out (exact):** STOP, STOPALL, STOP ALL, END, QUIT, CANCEL, UNSUBSCRIBE, UNSUB, OPT OUT, OPTOUT, REMOVE, REMOVE ME, STOPPED, STOPS, STOPPING, BLOCK, BLOCKED, BS, BULLSHIT, WRONG, DO NOT TEXT, DONT TEXT, DO NOT CONTACT, DONT CONTACT, DON'T CALL, DON'T CARE, DON'T SEND, DON'T BOTHER

  **Opt-out (misspellings):** ETOP, DTOP, STPO, STORP, STOD, STOL, STOLP, STOM, STON, STOO, STOOP, STOT, STP, STTOP, STUP, STIP, SUTOP

  **Spam / abuse:** SPAM, SCAM, JUNK (plus profanity, "reporting you", "do not call", "speak to a representative")

  **Re-subscribe (START):** START, UNSTOP, SUBSCRIBE, RESUBSCRIBE, OPTIN, OPT IN

  **Help:** HELP, INFO
</Accordion>

## Unsubscribe Reasons

Every unsubscribe records why it happened:

| Reason         | Source                                                                         |
| -------------- | ------------------------------------------------------------------------------ |
| `replied stop` | Contact replied STOP / an opt-out keyword                                      |
| `manual`       | Admin unsubscribed the contact                                                 |
| `api`          | Unsubscribe via API                                                            |
| `complaint`    | Spam complaint                                                                 |
| `gdpr_erasure` | GDPR erasure request                                                           |
| `bad_response` | Carrier delivery error (see [DLR Error Auto-Removal](#dlr-error-auto-removal)) |

## Message Requirements

### Required Elements

Every message should include:

* Clear sender identification
* Opt-out instructions

Example:

```
[Brand]: Your message here. Reply STOP to opt out.
```

### Account Settings

Configure account-wide compliance text:

1. Go to **Account Settings > Messaging**
2. Set **Prepend text** (added to start of message)
3. Set **Append text** (added to end of message)

Example:

```
Prepend: "[BrandName] "
Append: " Reply STOP to opt out"
```

Prepend and append text is **only applied to US numbers** (phone numbers with `+1` prefix). Non-US sending lists receive the raw message without auto-applied compliance text.

## TCPA Quiet Hours

Trackly enforces TCPA quiet hours for US phone numbers:

* **Allowed hours**: 8:00 AM - 9:00 PM in the contact's local time
* **Timezone fallback chain**: Contact timezone → Account default timezone → Eastern Time
* Messages scheduled outside the window are **delayed** to the next valid send time (not dropped)
* **Transactional messages** (e.g., OTP codes) can be configured as exempt from TCPA restrictions

## Consent Management

### Types of Consent

| Type    | Description           | Use Case           |
| ------- | --------------------- | ------------------ |
| Express | Explicit opt-in       | Marketing messages |
| Implied | Existing relationship | Transactional      |

### Documenting Consent

For each contact, track:

* When they opted in
* How they opted in (web form, API, etc.)
* What they consented to

This is stored in `signup_method` and `signup_date`.

## Regulations

### TCPA (US)

The Telephone Consumer Protection Act requires:

* Prior express consent for marketing
* Identification of sender
* Opt-out mechanism

<Note>
  TCPA quiet hours and automatic opt-out text (message prepend/append) are **only enforced for US phone numbers** (+1 prefix). For international numbers, these restrictions do not apply — add appropriate opt-out instructions for your target market directly in your message creatives.
</Note>

### Setting Up TCPA Compliance

<Steps>
  <Step title="Configure Quiet Hours">
    Set TCPA quiet hours (8 AM–9 PM) in your list settings. Trackly automatically checks each contact's timezone before sending.
  </Step>

  <Step title="Enable Opt-Out Keywords">
    Verify STOP, STOPALL, UNSUBSCRIBE, QUIT, and CANCEL keywords are active. These are enabled by default on all lists.
  </Step>

  <Step title="Set Cooldown Periods">
    Configure minimum time between messages to the same contact. This prevents over-messaging and reduces opt-outs.
  </Step>

  <Step title="Record Consent">
    Use the `ip_address` and `url` fields when creating contacts via API to record where and when consent was given.
  </Step>

  <Step title="Test Your Setup">
    Send a test message to your own number, reply STOP, and verify the unsubscribe is processed. Then verify future sends are blocked.
  </Step>
</Steps>

### International Sending

When sending to non-US numbers:

* TCPA quiet hours are **not enforced** — messages send at any time
* Message prepend/append text is **not auto-applied** — add opt-out instructions in your creatives
* STOP word auto-removal, spam complaint removal, and DLR error removal remain active globally as carrier best practice

Research the regulations for your target countries and include appropriate opt-out language.

### CTIA Guidelines

Carrier guidelines recommend:

* Clear opt-out in every message
* Immediate opt-out processing
* No messages to opted-out numbers

### CAN-SPAM (Email-Adjacent)

While for email, principles apply:

* Honest identification
* Clear opt-out
* Honor requests promptly

## DLR Error Auto-Removal

Trackly automatically removes contacts from sending lists based on delivery report (DLR) error codes from SMS providers. This prevents repeated sends to unreachable numbers and protects your sender reputation.

### Immediate Removal

These error codes trigger **immediate** contact removal (unsubscribed with reason `bad_response`):

| Error Code | Name                                   | Description                    |
| ---------- | -------------------------------------- | ------------------------------ |
| 603        | `REJECTED_ABSENT_SUBSCRIBER_PERMANENT` | Number permanently unreachable |
| 351        | `REJECTED_DESTINATION_NOT_REACHABLE`   | Destination not reachable      |

### Threshold Removal

These error codes trigger removal after **2 failures within 30 days**:

| Error Code | Name                      | Description              |
| ---------- | ------------------------- | ------------------------ |
| 32         | `REJECTED_NETWORK_ERROR`  | Network-level rejection  |
| 1281       | `REJECTED_OPERATOR_ERROR` | Operator-level rejection |

DLR auto-removal is enforced by default on all accounts. Contact support if you need to adjust thresholds for your use case.

## TCPA Quiet Hours

Trackly enforces TCPA quiet hours for **US phone numbers only** to ensure messages are sent during legal hours in the recipient's local time.

### Rules

* **Applies to**: US sending list numbers only (+1 prefix)
* **Allowed window**: 8:00 AM – 9:00 PM in the contact's local timezone
* **Timezone source**: Determined from carrier lookup at contact creation, or from click IP geolocation
* **Transactional messages**: Exempt from quiet hours
* **No timezone data**: If a contact's timezone is unknown, messages are sent without quiet hour restrictions
* **International numbers**: Not subject to TCPA — messages send at any time

### How It Works

1. When a scheduled send is queued, the system checks if the sending list uses a US number
2. For US numbers, it checks each contact's timezone against the 8 AM – 9 PM window
3. Messages outside the window are held and sent at the next valid window (8 AM in the contact's local time)
4. Non-US sending lists skip this check entirely

TCPA quiet hours are enforced by default for US numbers. International sending lists are not subject to TCPA restrictions.

### Toll-Free Verification

<Steps>
  <Step title="Submit Verification Request">
    In the dashboard, navigate to your toll-free number and submit a verification request with your business details and use case.
  </Step>

  <Step title="Provide Sample Messages">
    Include 2-3 example messages that represent your typical sending content.
  </Step>

  <Step title="Confirm Opt-In Method">
    Describe how contacts consent to receive messages (web form, keyword opt-in, etc.).
  </Step>

  <Step title="Wait for Review">
    Toll-free verification typically takes 1-3 business days. You will receive an email notification when complete.
  </Step>
</Steps>

## Spam Auto-Removal

Contacts are automatically removed when SMS providers report spam-related delivery failures. This protects your account from carrier penalties.

### Carrier Spam Codes

| Error Name              | Description                        |
| ----------------------- | ---------------------------------- |
| `REJECTED_SPAM`         | Message flagged as spam by carrier |
| `REJECTED_SPAM_CONTENT` | Content identified as spam         |
| `REJECTED_BLACKLISTED`  | Number is on a carrier blacklist   |

### CM Spam Codes

| Error Code | Description                |
| ---------- | -------------------------- |
| `2005`     | Spam filter triggered      |
| `2006`     | Content blocked by carrier |

<Warning>
  Spam auto-removal is permanent. Contacts removed for spam cannot be re-enrolled via API — they must re-subscribe through opt-in forms.
</Warning>

## Content Filtering

Trackly automatically blocks messages containing prohibited content at send time. Messages that match blocked patterns receive a status of `BLOCKED_CONTENT` with the matched word and category.

### Blocked Categories

<AccordionGroup>
  <Accordion title="Cryptocurrency Terms">
    Messages containing cryptocurrency-related terms are blocked. This includes direct terms and common variations.

    | Blocked Term   |
    | -------------- |
    | bitcoin        |
    | btc            |
    | ethereum       |
    | eth            |
    | crypto         |
    | cryptocurrency |
    | blockchain     |
    | wallet         |
    | coinbase       |
    | binance        |
    | kraken         |
    | dogecoin       |
    | doge           |
    | litecoin       |
    | ltc            |
    | ripple         |
    | xrp            |
    | solana         |
    | sol            |
    | cardano        |
    | ada            |
    | polkadot       |
    | dot            |
    | avalanche      |
    | avax           |
    | nft            |
    | defi           |
    | altcoin        |
    | stablecoin     |
    | usdt           |
    | usdc           |
    | tether         |
  </Accordion>

  <Accordion title="Account Verification Phrases">
    Phishing-style phrases commonly used in fraud attempts are blocked.

    | Blocked Phrase    |
    | ----------------- |
    | your bank         |
    | verify your       |
    | confirm your      |
    | unlock your       |
    | verify account    |
    | confirm account   |
    | unlock account    |
    | suspended account |
    | account suspended |
    | account locked    |
    | verify identity   |
    | confirm identity  |
    | ssn               |
    | social security   |
    | update payment    |
    | verify payment    |
    | confirm payment   |
  </Accordion>

  <Accordion title="Financial Institution Names — US">
    Major US bank and financial institution names are blocked to prevent impersonation.

    | Blocked Term     |
    | ---------------- |
    | chase            |
    | wells fargo      |
    | bank of america  |
    | citibank         |
    | citi bank        |
    | us bank          |
    | usbank           |
    | pnc              |
    | truist           |
    | capital one      |
    | capitalone       |
    | td bank          |
    | tdbank           |
    | fifth third      |
    | citizens bank    |
    | keybank          |
    | huntington bank  |
    | regions bank     |
    | ally bank        |
    | discover bank    |
    | synchrony        |
    | american express |
    | amex             |
    | goldman sachs    |
    | morgan stanley   |
    | charles schwab   |
    | fidelity         |
    | merrill lynch    |
    | bank account     |
    | bank accounts    |
  </Accordion>

  <Accordion title="Financial Institution Names — International">
    International bank names are also blocked.

    | Blocked Term       |
    | ------------------ |
    | hsbc               |
    | barclays           |
    | deutsche bank      |
    | ubs                |
    | credit suisse      |
    | bnp paribas        |
    | societe generale   |
    | santander          |
    | ing bank           |
    | royal bank         |
    | rbc                |
    | scotiabank         |
    | bmo                |
    | cibc               |
    | td canada          |
    | natwest            |
    | lloyds             |
    | standard chartered |
    | commerzbank        |
  </Accordion>
</AccordionGroup>

### Leet-Speak Detection

The content filter detects common character substitutions used to evade filtering:

| Character | Detected As |
| --------- | ----------- |
| `1`       | i, l        |
| `0`       | o           |
| `3`       | e           |
| `4`       | a           |
| `5`       | s           |
| `@`       | a           |
| `$`       | s           |
| `7`       | t           |

For example, `b1tc0in`, `cr4pt0`, and `3th3r3um` are all caught.

### When Filtering Applies

* Content filtering is enforced **at send time**, not at creative creation
* Blocked messages are not sent and receive `BLOCKED_CONTENT` status
* The API response includes the matched word and category for debugging
* Filtering applies to the final message text (after template substitution and prepend/append)

Content filtering cannot be disabled. If you believe a message was incorrectly blocked, contact support with the blocked word and category.

## Spam Prevention

### Content Guidelines

Avoid:

* Misleading claims
* Excessive caps/punctuation
* Shortened URLs from unknown shorteners
* Adult content

### Volume Guidelines

* Don't send too frequently
* Respect quiet hours
* Use frequency capping

### List Hygiene

* Remove invalid numbers
* Honor opt-outs immediately
* Don't purchase lists

## Handling Complaints

If a carrier flags you:

1. Review the flagged content
2. Identify the issue
3. Update messaging practices
4. Contact carrier if needed

Discord alerts notify you of spam complaints in real-time.

## Audit Trail

Trackly maintains:

* When contacts subscribed
* When/why they unsubscribed
* All messages sent
* Opt-out requests received

This data helps demonstrate compliance.

For opt-ins captured through the opt-in tool (widgets, hosted pages, keyword flows, subscribe links, QR codes, or the opt-in webhook), Trackly additionally records a frozen verbatim copy of the consent-disclosure text shown to the visitor, the creative they saw, their IP, user agent, page URL, and the consent timestamp. These consent records are retained indefinitely as TCPA evidence. See [Opt-In Tool Data & Retention](/concepts/optin-tool-data-retention) for the full field list, retention rules, webhook behavior, and export paths.

### 10DLC Registration Checklist

<Steps>
  <Step title="Register Your Brand">
    Submit your business details (legal name, EIN, website) for brand verification through the dashboard.
  </Step>

  <Step title="Create a Campaign">
    Register your messaging use case (marketing, notifications, etc.) with a description of your message content.
  </Step>

  <Step title="Assign Numbers">
    Associate your 10DLC phone numbers with the registered campaign.
  </Step>

  <Step title="Wait for Approval">
    Brand verification typically takes 1-5 business days. Campaign approval may take an additional 1-3 days.
  </Step>

  <Step title="Monitor Throughput">
    After approval, your sending throughput is set based on your brand trust score. Higher scores unlock higher volumes.
  </Step>
</Steps>

## Best Practices

<AccordionGroup>
  <Accordion title="Always include opt-out">
    Every marketing message should have "Reply STOP to opt out" or similar.
  </Accordion>

  <Accordion title="Document consent">
    Know where each contact came from and what they consented to.
  </Accordion>

  <Accordion title="Honor opt-outs immediately">
    Never send to unsubscribed contacts. The system blocks this automatically.
  </Accordion>

  <Accordion title="Use clear identification">
    Recipients should know who's messaging them immediately.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Phone Numbers" icon="phone" href="/concepts/phone-numbers">
    Number provisioning
  </Card>

  <Card title="Discord Alerts" icon="bell" href="/integrations/discord-alerts">
    Compliance monitoring
  </Card>
</CardGroup>
