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

# Messaging Best Practices

> Optimize deliverability, compliance, and user experience across all channels

# 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.

```
✅ +14155552671
✅ +905551234567
❌ (415) 555-2671
❌ 4155552671
```

### Register for 10DLC (US)

All A2P SMS to US numbers requires [10DLC registration](/guides/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:

1. Stop sending immediately
2. Send a confirmation: "You have been unsubscribed. Reply START to resubscribe."
3. 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)

```
Acme Corp: Welcome! You'll receive order updates here.
Reply STOP to opt out. Msg & data rates may apply.
```

### 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)   |

**Cost optimization tips:**

* 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:

```
❌ "Your order has shipped."
✅ "Hi Jane, your order #12345 has shipped! ETA: March 10."
```

### 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:

```javascript theme={null}
const MAX_RETRIES = 3

async function sendMessage(params) {
  for (let i = 0; i < MAX_RETRIES; i++) {
    try {
      return await orbit.messages.send(params)
    } catch (error) {
      if (error.status >= 500 && i < MAX_RETRIES - 1) {
        await sleep(Math.pow(2, i) * 1000)
        continue
      }
      throw error
    }
  }
}
```

### 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_LIMITED`          | 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_NUMBER` errors)
* Opted-out numbers (`RECIPIENT_OPTED_OUT`)
* Undeliverable addresses (repeated `failed` status)

***

## 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 cross-channel fallback at the
**organization** level rather than per-request. Once configured, every send
on the primary channel transparently retries the next channel in the chain
when the primary delivery fails — no per-call flag required.

1. Open **Settings → Channels → Cross-Channel Fallback** on the dashboard.
2. Add a rule, e.g. **Primary: WhatsApp → Fallback: SMS**. Chains of 2+
   channels are supported (`RCS → WhatsApp → SMS`); each fallback fires only
   when the previous one exhausts its retries or returns a hard,
   non-retryable error.
3. Save. The fallback takes effect on the next send.

```javascript theme={null}
// The send body itself does NOT carry a `fallback` field — fallback
// behaviour is driven by the org-level cross_channel_fallback configuration.
await orbit.messages.send({
  to: '+14155552671',
  channel: 'whatsapp',
  body: 'Your package has been delivered.',
})
```

When the primary channel chain (WhatsApp providers) exhausts its retries and
returns a non-retryable failure, the router advances to SMS automatically and
applies the recipient's opt-out + DNC checks against the new channel before
delivery.

***

## Performance

### Use Webhooks Instead of Polling

Subscribe to delivery status webhooks rather than polling `GET /api/v1/messages/{id}`:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/webhooks \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/orbit",
    "events": ["message.delivered", "message.failed"]
  }'
```

### Batch Operations

For bulk sends, use campaigns instead of individual API calls:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/campaigns \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "March Newsletter",
    "channel": "sms",
    "audience": { "contact_list_id": "list_abc123" },
    "content": { "body": "Hi {{first_name}}, check out our new features!" },
    "schedule": "2026-03-10T10:00:00Z"
  }'
```

<Tip>
  Need help optimizing your messaging strategy? Contact the Orbit solutions team at [solutions@devotel.io](mailto:solutions@devotel.io).
</Tip>
