Messaging Best Practices
Follow these best practices to maximize deliverability, stay compliant with carrier regulations, and provide the best experience for your recipients.Deliverability
Use E.164 Phone Number Format
Always format phone numbers in E.164:+[country code][number] with no spaces, dashes, or parentheses.
Register for 10DLC (US)
All A2P SMS to US numbers requires 10DLC registration. Unregistered traffic will be filtered or blocked.Warm Up New Numbers
When using a new number for high-volume sending, gradually increase volume over 2–4 weeks:| Week | Daily Volume |
|---|---|
| 1 | 100 messages |
| 2 | 500 messages |
| 3 | 2,000 messages |
| 4+ | Full volume |
Monitor Delivery Rates
Use webhooks to track delivery status in real time. If your delivery rate drops below 95%, investigate immediately:- Check for opt-outs and invalid numbers
- Review carrier feedback for content filtering
- Verify 10DLC campaign status
Compliance
Always Get Consent
- Express consent is required for transactional messages
- Express written consent is required for marketing messages (TCPA requirement)
- Keep records of when and how each recipient opted in
Honor Opt-Outs Immediately
Orbit automatically handles standard opt-out keywords (STOP, CANCEL, UNSUBSCRIBE). When a user opts out:- Stop sending immediately
- Send a confirmation: “You have been unsubscribed. Reply START to resubscribe.”
- Never message the number again until they re-opt-in
Include Required Disclosures
Every first message to a new recipient should include:- Your business name
- Message frequency description
- “Reply STOP to unsubscribe”
- “Msg & data rates may apply” (for US)
Follow Quiet Hours
Avoid sending marketing messages outside business hours in the recipient’s timezone:| Region | Quiet Hours |
|---|---|
| US (TCPA) | 9 PM – 8 AM local time |
| EU (GDPR) | Follow local telecom regulations |
| Turkey | 8 PM – 8 AM (KVKK) |
Content
Keep SMS Concise
SMS has a 160-character limit per segment (70 for Unicode). Longer messages are split into segments and cost more:| Encoding | Characters per Segment |
|---|---|
| GSM-7 (standard) | 160 (single) / 153 (multi-part) |
| Unicode (emoji, non-Latin) | 70 (single) / 67 (multi-part) |
- Remove unnecessary whitespace and formatting
- Use URL shorteners for links
- Avoid emoji in transactional SMS to stay in GSM-7
Personalize Messages
Personalized messages see 2–3x higher engagement:Use Templates for WhatsApp
WhatsApp requires pre-approved templates for business-initiated conversations. Best practices:- Keep templates under 1024 characters
- Use variables for personalization:
Hello {{1}}, your order {{2}} is ready. - Submit templates in all languages you need upfront
- Avoid promotional language in transactional templates
Error Handling
Implement Retry Logic
Use exponential backoff for transient failures:Handle Specific Error Codes
| Code | Action |
|---|---|
INVALID_PHONE_NUMBER | Remove from contact list; do not retry |
RECIPIENT_OPTED_OUT | Remove from send list immediately |
RATE_LIMIT_EXCEEDED | Wait for retry_after seconds and retry |
TEMPLATE_NOT_APPROVED | Check template status in dashboard |
MESSAGE_SEND_FAILED | Retry with backoff; escalate after 3 failures |
CHANNEL_UNAVAILABLE | Try fallback channel or retry later |
Clean Your Contact Lists
Regularly remove:- Invalid numbers (persistent
INVALID_PHONE_NUMBERerrors) - Opted-out numbers (
RECIPIENT_OPTED_OUT) - Undeliverable addresses (repeated
failedstatus)
Channel Selection
Choose the right channel for each use case:| Use Case | Recommended Channel | Why |
|---|---|---|
| OTP / 2FA | SMS | Universal reach, no app required |
| Order updates | WhatsApp or SMS | Rich media on WhatsApp, fallback to SMS |
| Marketing campaigns | WhatsApp, RCS, Email | Rich content, higher engagement |
| Support conversations | WhatsApp, Web Chat | Async, supports media and threading |
| Transactional alerts | Email + SMS | Email for detail, SMS for urgency |
| Voice notifications | Voice API | Time-sensitive alerts, confirmation |
Implement Channel Fallback
For critical messages, configure automatic fallback:Performance
Use Webhooks Instead of Polling
Subscribe to delivery status webhooks rather than pollingGET /v1/messages/{id}: