Suppressions
Manage SMS opt-out lists and suppressed phone numbers.
Overview
Suppressions are phone numbers that should not receive SMS messages. This includes users who have opted out, invalid numbers, and manually blocked numbers.
How Suppressions Work
When you send an SMS:
- We check if the recipient is on your suppression list
- If suppressed, the message is blocked and not sent
- API returns error code 1006 (recipient opted out)
const result = await client.sms.send({
to: '+14155551234',
templateAlias: 'otp-verification',
templateModel: { code: '123456' },
});
if (result.errorCode === 1006) {
console.log('Recipient has opted out');
}Suppression Reasons
| Reason | Description |
|---|---|
OPT_OUT | User replied STOP or similar keyword |
MANUAL | Manually added by your team |
CARRIER_BLOCK | Carrier rejected the number |
INVALID_NUMBER | Number is not a valid mobile |
Automatic Opt-Out Handling
We automatically process opt-out keywords and add numbers to your suppression list:
Opt-Out Keywords
- STOP
- UNSUBSCRIBE
- CANCEL
- END
- QUIT
Opt-In Keywords
- START
- YES
- UNSTOP
When a user opts out:
- They're added to your suppression list
- They receive a confirmation message
- Future messages are blocked
When a user opts back in:
- They're removed from your suppression list
- They receive a confirmation message
- They can receive messages again
Managing Suppressions
List Suppressions
TypeScript:
const suppressions = await client.sms.suppressions.list({
count: 100,
offset: 0,
});
for (const suppression of suppressions) {
console.log(`${suppression.phoneNumber}: ${suppression.reason}`);
}Python:
suppressions = client.sms.suppressions.list(count=100, offset=0)
for suppression in suppressions.suppressions:
print(f"{suppression.phone_number}: {suppression.reason}")Check If Suppressed
TypeScript:
const result = await client.sms.suppressions.check('+14155551234');
if (result.suppressed) {
console.log('This number is suppressed');
}Python:
result = client.sms.suppressions.check("+14155551234")
if result.suppressed:
print("This number is suppressed")Add Suppression Manually
TypeScript:
await client.sms.suppressions.add({
phoneNumber: '+14155551234',
reason: 'MANUAL',
notes: 'User requested via email',
});Python:
client.sms.suppressions.add(
phone_number="+14155551234",
reason="MANUAL",
notes="User requested via email",
)Remove Suppression
TypeScript:
await client.sms.suppressions.remove('+14155551234');Python:
client.sms.suppressions.remove("+14155551234")Note: Only remove suppressions if you have valid re-consent from the user.
Dashboard Management
Viewing Suppressions
- Go to SMS > Opt-Outs in your dashboard
- View all suppressed numbers
- Filter by reason or date
Bulk Import
Import suppressions from CSV:
- Go to SMS > Opt-Outs
- Click Import
- Upload CSV with phone numbers
- Select suppression reason
- Import
CSV format:
phone_number,reason,notes
+14155551234,MANUAL,User requested removal
+14155555678,MANUAL,Do not contactBulk Export
Export your suppression list:
- Go to SMS > Opt-Outs
- Click Export
- Download CSV file
API Reference
List Suppressions
GET /sms/suppressionsQuery parameters:
count- Number to return (default: 100, max: 500)offset- Pagination offsetreason- Filter by reasonfromDate- Filter by date rangetoDate- Filter by date range
Response:
{
"totalCount": 150,
"suppressions": [
{
"phoneNumber": "+14155551234",
"phoneNumberHash": "abc123...",
"reason": "OPT_OUT",
"optedOutAt": "2024-01-01T12:00:00.000Z",
"notes": null
}
]
}Add Suppression
POST /sms/suppressionsBody:
{
"phoneNumber": "+14155551234",
"reason": "MANUAL",
"notes": "User requested via support ticket"
}Remove Suppression
DELETE /sms/suppressions/{phoneNumber}Check Suppression
GET /sms/suppressions/check/{phoneNumber}Response:
{
"suppressed": true,
"reason": "OPT_OUT",
"optedOutAt": "2024-01-01T12:00:00.000Z"
}Webhook Events
Receive notifications when suppressions change:
Opt-Out Event
{
"event": "sms.opt_out",
"timestamp": "2024-01-01T12:00:00.000Z",
"data": {
"phoneNumber": "+14155551234",
"keyword": "STOP",
"optedOutAt": "2024-01-01T12:00:00.000Z"
}
}Opt-In Event
{
"event": "sms.opt_in",
"timestamp": "2024-01-01T12:00:00.000Z",
"data": {
"phoneNumber": "+14155551234",
"keyword": "START",
"optedInAt": "2024-01-01T12:00:00.000Z"
}
}Privacy Considerations
Phone Number Hashing
Phone numbers in suppressions are stored as SHA-256 hashes:
- Original number:
+14155551234 - Stored hash:
abc123def456...
This protects user privacy while allowing lookup and deduplication.
Data Retention
Suppressions are retained indefinitely to ensure compliance. Contact support if you need to delete suppression data under privacy regulations.
Best Practices
1. Check Before Sending
Always check suppressions before important sends:
async function sendSmsIfAllowed(phone: string, template: string, model: object) {
const isSuppressed = await client.sms.suppressions.check(phone);
if (isSuppressed) {
console.log(`Skipping ${phone} - suppressed`);
return;
}
return client.sms.send({
to: phone,
templateAlias: template,
templateModel: model,
});
}2. Honor Opt-Outs Immediately
Never send to opted-out users, even for transactional messages.
3. Sync with Your Systems
Keep your internal suppression lists in sync:
// Listen for opt-out webhooks
app.post('/webhooks/sms', (req, res) => {
const { event, data } = req.body;
if (event === 'sms.opt_out') {
// Update your database
db.users.update({
where: { phone: data.phoneNumber },
data: { smsOptedOut: true },
});
}
res.status(200).send('OK');
});4. Import Existing Lists
If you have existing suppression lists from other providers, import them:
const existingSuppressions = [
{ phone: '+14155551234', reason: 'MANUAL' },
{ phone: '+14155555678', reason: 'OPT_OUT' },
];
for (const s of existingSuppressions) {
await client.sms.suppressions.add({
phoneNumber: s.phone,
reason: s.reason,
});
}Troubleshooting
Message Blocked Unexpectedly
If a message was blocked but shouldn't have been:
- Check if number is on suppression list
- Verify the suppression reason
- If manually added in error, remove it
- If user opted out, get re-consent before removing
User Says They Didn't Opt Out
This can happen if:
- Someone else replied STOP from a shared phone
- Carrier-level opt-out
- Number reassignment
Resolution:
- Verify user identity
- Have them text START to opt back in
- Document the re-consent
Next Steps
- Compliance - Understand regulatory requirements
- Webhooks - Track opt-out events
- API Reference - Complete API documentation
On This Page
- Overview
- How Suppressions Work
- Suppression Reasons
- Automatic Opt-Out Handling
- Opt-Out Keywords
- Opt-In Keywords
- Managing Suppressions
- List Suppressions
- Check If Suppressed
- Add Suppression Manually
- Remove Suppression
- Dashboard Management
- Viewing Suppressions
- Bulk Import
- Bulk Export
- API Reference
- List Suppressions
- Add Suppression
- Remove Suppression
- Check Suppression
- Webhook Events
- Opt-Out Event
- Opt-In Event
- Privacy Considerations
- Phone Number Hashing
- Data Retention
- Best Practices
- 1. Check Before Sending
- 2. Honor Opt-Outs Immediately
- 3. Sync with Your Systems
- 4. Import Existing Lists
- Troubleshooting
- Message Blocked Unexpectedly
- User Says They Didn't Opt Out
- Next Steps