# Smart Routing

> Automatic channel selection that reduces costs up to 80%

Smart Routing is Zavu's system that automatically selects the optimal channel for each message, maximizing delivery rates while minimizing costs.

> **Note:**
> **Smart routing only applies to outbound messages.** When replying to an inbound message, Zavu always responds on the **same channel** the contact used.

## When Smart Routing Applies

| Message Type | Routing Behavior |
|--------------|------------------|
| **Outbound** (you initiate) | Smart routing selects optimal channel |
| **Inbound reply** (direct response) | Always use the contact's channel |

## How It Works

For outbound messages, the router checks if the contact has previously messaged you:

```
Has contact messaged via WhatsApp in last 24h?
      |
   +--+--+
   |     |
  Yes   No
   |     |
   v     v
WhatsApp    WhatsApp only
available   with template
(preferred)
```

Since WhatsApp is cheaper than SMS, the router **prefers WhatsApp when the 24-hour window is open**.

## Channel Selection Algorithm

The router evaluates channels in this order:

1. **Filter viable channels**: Remove channels that can't deliver (e.g., WhatsApp without open window)
2. **Sort by cost**: Cheapest channels first
3. **Check success rate**: Channel must have at least 80% success rate (or fewer than 3 attempts for exploration)
4. **Select best option**: First channel meeting all criteria

## Cost Optimization

| Channel | Approximate Cost |
|---------|------------------|
| WhatsApp | ~$0.01/message |
| SMS | ~$0.05/message |

Smart routing can reduce messaging costs by **up to 80%** by preferring WhatsApp when available.

## WhatsApp 24-Hour Window

WhatsApp has a strict rule: you can only send free-form messages within **24 hours** of the last message received from the contact.

```
Contact sends message ... 24-hour window opens
      |
Within 24h: Send any message type
      |
After 24h: Only template messages allowed
```

> **Warning:**
> If the 24-hour window is closed and you don't have a template configured, the smart router will automatically select SMS instead of failing.

## Channel Metrics

Zavu tracks delivery metrics for each contact and channel:

```json
{
  "channelMetrics": {
    "sms": {
      "successCount": 45,
      "failureCount": 2,
      "avgDeliveryTimeMs": 3200,
      "lastSuccessAt": "2025-01-15T10:30:00Z"
    },
    "whatsapp": {
      "successCount": 120,
      "failureCount": 1,
      "avgDeliveryTimeMs": 1100,
      "lastSuccessAt": "2025-01-15T14:22:00Z"
    }
  }
}
```

The router uses these metrics to:
- Avoid channels with low success rates (below 80%)
- Prefer faster channels when speed matters
- Explore new channels (first 3 attempts get a chance regardless of stats)

## Automatic Fallback

When a message fails on one channel, Zavu **automatically retries** on an alternate channel.

### Fallback Flow

```
Send via WhatsApp
      |
      v
  Failed?
      |
   +--+--+
   |     |
  No    Yes
   |     |
   v     v
Done   Wait 5s
         |
         v
   Retry via SMS
         |
         v
     Success?
         |
      +--+--+
      |     |
     Yes   No
      |     |
      v     v
   Done   Mark Failed
```

### Fallback Rules

| Rule | Description |
|------|-------------|
| Max 2 attempts | Each message is tried on at most 2 channels |
| 5-second delay | Wait 5 seconds before retry to avoid race conditions |
| No duplicate channels | Never retry on a channel that already failed |
| Sender must support both | Fallback only works if sender has both channels configured |

### Tracking Fallback

A message that fell back keeps its id and reports the channel it was finally sent on:

```json
{
  "id": "msg_abc123",
  "status": "delivered",
  "channel": "sms"
}
```

In this example, the message first tried WhatsApp, failed, and was delivered via SMS.

Fallback is on by default only when Zavu picks the channel. A send with an explicit `channel` does not fall back unless it sets `fallbackEnabled: true`; see [Senders](https://www.zavu.dev/docs/concepts/senders#enablingdisabling-fallback).

## Manual Override

To bypass Smart Routing for a specific message, specify the channel explicitly:

```typescript
await zavu.messages.send({
  to: "+56912345678",
  text: "This must go via SMS",
  channel: "sms"
});
```

```bash
curl -X POST https://api.zavu.dev/v1/messages \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+56912345678",
    "text": "This must go via SMS",
    "channel": "sms"
  }'
```

> **Tip:**
> You can optionally specify a sender by passing `"Zavu-Sender": "snd_abc123"` inside the send params (TypeScript), or the `Zavu-Sender` header (cURL). If omitted, your project's default sender is used.

## Best Practices

  - **Configure Multiple Channels**: Set up both SMS and WhatsApp on your sender to enable automatic fallback.
  - **Use Templates for Outreach**: When initiating conversations, use WhatsApp templates to avoid 24-hour window issues.
  - **Monitor Metrics**: Check your contact metrics to understand channel performance in your region.
  - **Keep Numbers Updated**: Invalid numbers waste attempts across all channels.

## Next Steps

  - [Senders](https://www.zavu.dev/docs/concepts/senders): Learn more about sender configuration
  - [WhatsApp Templates](https://www.zavu.dev/docs/guides/whatsapp/templates/sending): Create templates for outbound messaging
