Compliance & Regulations
Understand and implement compliance requirements for messaging regulations worldwide.
GDPR (Europe)
Data Processing
- Obtain explicit consent before messaging
- Provide opt-out mechanism
- Honor data deletion requests
- Maintain processing records
Implementation
// Check consent before sending
async function canMessageUser(userId: string) {
const user = await db.users.findById(userId);
return user.messagingConsent === true &&
user.optedOutAt === null;
}
// Handle opt-out
app.post('/opt-out', async (req, res) => {
await db.users.update(req.body.phoneNumber, {
optedOutAt: new Date(),
messagingConsent: false
});
res.send('You have been unsubscribed');
});TCPA (United States)
Requirements
- Written consent for marketing messages
- Honor opt-outs within 24 hours
- Maintain consent records
- No messages before 8 AM or after 9 PM (recipient's timezone)
Best Practices
// Timezone-aware sending
async function sendInUserTimezone(userId: string, templateId: string) {
const user = await db.users.findById(userId);
const userTime = new Date().toLocaleString('en-US', {
timeZone: user.timezone
});
const hour = new Date(userTime).getHours();
// Only send between 9 AM and 8 PM
if (hour >= 9 && hour < 20) {
return client.messages.send({
to: [user.phoneNumber],
template: { id: templateId }
});
} else {
// Queue for next available window
await queueForTomorrow(userId, templateId);
}
}Country-Specific Requirements
| Country | Requirement |
|---|---|
| Australia | SPAM Act compliance, unsubscribe within 5 days |
| Canada | CASL - express consent required |
| UK | PECR regulations, opt-in required |
| Singapore | PDPA compliance |
| Brazil | LGPD data protection |
Opt-Out Handling
Handle opt-outs automatically via webhook (error code BUSINESS_007 indicates recipient opted out):
app.post('/webhooks/sent', async (req, res) => {
// Acknowledge immediately
res.sendStatus(200);
const { field, payload } = req.body;
if (field === 'messages' && payload.message_status === 'FAILED') {
// Fetch the message via API for full error details (e.g. BUSINESS_007 = opted out)
const message = await client.messages.get(payload.message_id);
const errorCode = message.data?.error?.code;
if (errorCode === 'BUSINESS_007') {
await db.users.update(payload.inbound_number, {
optedOutAt: new Date(),
messagingConsent: false
});
}
}
});