# Senders — Smart Routing & Fallback

> Senders combine phone numbers, WhatsApp Business accounts and webhooks into routing identities. Smart routing and automatic SMS/WhatsApp fallback included.

## Senders

A **Sender** is a messaging profile that represents "who" is sending the message. Senders can be configured with multiple channels — SMS, WhatsApp, Email, Telegram, Instagram, and Voice — and Zavu intelligently routes messages through them.

## What is a Sender?

Think of a sender as your messaging identity. It contains:

- **Phone number** — used for SMS, WhatsApp, and [Voice](https://www.zavu.dev/docs/guides/sending-messages/easy-way) messaging
- **WhatsApp Business Account** — for [WhatsApp](https://www.zavu.dev/docs/guides/whatsapp/overview) messaging (rich media, templates, interactive messages)
- **Email domain** — for [transactional email](https://www.zavu.dev/docs/guides/sending-messages/email) via Amazon SES
- **Telegram bot** — for [Telegram](https://www.zavu.dev/docs/guides/telegram/overview) messaging
- **Instagram Business Account** — for Instagram direct messaging
- **Webhooks** — real-time notifications for [inbound messages and delivery updates](https://www.zavu.dev/docs/guides/receiving-messages/webhooks)
- **Allowed destinations** — countries you can send to

```json
{
  "id": "sender_12345",
  "name": "Primary Sender",
  "phoneNumber": "+13125551212",
  "isDefault": true,
  "webhook": {
    "url": "https://your-app.com/webhooks",
    "events": ["message.inbound", "message.delivered"],
    "active": true
  },
  "whatsapp": {
    "phoneNumberId": "123456789",
    "displayPhoneNumber": "+13125551212"
  },
  "emailReceivingEnabled": false,
  "createdAt": "2025-01-15T10:00:00Z",
  "updatedAt": "2025-01-15T10:00:00Z"
}
```

## Channels

Zavu supports 6 messaging channels. Each has different requirements and routing behavior:

| Channel | Identifier | Smart Routing | Fallback | Setup Guide |
|---------|-----------|---------------|----------|-------------|
| **SMS** | Phone number (E.164) | Yes | Yes | [SMS Guide](https://www.zavu.dev/docs/guides/sending-messages/sms) |
| **WhatsApp** | Phone number (E.164) | Yes | Yes | [WhatsApp Guide](https://www.zavu.dev/docs/guides/whatsapp/overview) |
| **Email** | Email address | No | No | [Email Guide](https://www.zavu.dev/docs/guides/sending-messages/email) |
| **Telegram** | Telegram chat ID | No | No | [Telegram Guide](https://www.zavu.dev/docs/guides/telegram/overview) |
| **Instagram** | Instagram-scoped ID | No | No | — |
| **Voice** | Phone number (E.164) | No | No | [Sending Messages](https://www.zavu.dev/docs/guides/sending-messages/easy-way) |

> **Note:**
> **Smart routing and automatic fallback only apply to SMS and WhatsApp.** Email, Telegram, Instagram, and Voice are standalone channels that must be explicitly specified with the `channel` parameter.

## Default Sender

Every project has a **default sender**. When you send a message without specifying a sender, Zavu uses the default.

```bash
# Uses default sender automatically
curl -X POST https://api.zavu.dev/v1/messages \
  -H "Authorization: Bearer zv_live_xxx" \
  -d '{"to": "+14155551234", "text": "Hello!"}'
```

To use a specific sender, include the `Zavu-Sender` header:

```bash
curl -X POST https://api.zavu.dev/v1/messages \
  -H "Authorization: Bearer zv_live_xxx" \
  -H "Zavu-Sender: sender_67890" \
  -d '{"to": "+14155551234", "text": "Hello!"}'
```

## Smart Routing

Zavu's smart routing system automatically selects the **optimal channel** for each message based on cost, deliverability, and contact history. Smart routing applies only to SMS and WhatsApp.

> **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. If they have, this affects channel availability:

```
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**. This means contacts who have messaged you before will typically receive messages via WhatsApp.

### 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](https://www.zavu.dev/docs/concepts/templates) configured, the smart router will automatically select SMS instead of failing.

### Channel Metrics

Zavu tracks delivery metrics for each [contact](https://www.zavu.dev/docs/guides/contacts/overview) 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 works between SMS and WhatsApp only.

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

### Enabling/Disabling Fallback

Whether fallback runs depends on how you choose the channel:

| Request | Fallback |
|---------|----------|
| `channel` omitted or `"auto"` | On, unless you set `fallbackEnabled: false` |
| `channel` set explicitly, e.g. `"whatsapp"` | Off, unless you set `fallbackEnabled: true` |

Choosing a channel explicitly means Zavu does not switch it for you, because an SMS is billed from your balance. To keep the SMS safety net on an explicit WhatsApp send, ask for it:

```json
{
  "to": "+14155551234",
  "channel": "whatsapp",
  "text": "Your order has shipped.",
  "fallbackEnabled": true
}
```

Only text and template messages fall back. Media, buttons, lists and other WhatsApp-only types never do.

## Standalone Channels

Email, Telegram, Instagram, and Voice operate independently from smart routing. You must explicitly specify the `channel` parameter when using them.

| Channel | Key Requirement | Docs |
|---------|-----------------|------|
| **Email** | A domain you own, verified in Zavu | [Email Setup](https://www.zavu.dev/docs/guides/email/setup) |
| **Telegram** | Bot token via BotFather | [Telegram Setup](https://www.zavu.dev/docs/guides/telegram/setup) |
| **Instagram** | Instagram Business Account | — |
| **Voice** | Phone number with voice capability | [Sending Messages](https://www.zavu.dev/docs/guides/sending-messages/easy-way) |

These channels don't participate in smart routing or automatic fallback because they use different recipient identifiers and have different delivery semantics than SMS/WhatsApp.

## Rate Limiting

Zavu implements fair [rate limiting](https://www.zavu.dev/docs/concepts/rate-limiting) to ensure reliable delivery for all users.

### Limits by Channel

| Channel | Rate Limit | Level |
|---------|------------|-------|
| SMS | 10 messages/second | Global |
| Email | 14 messages/second | Global |
| WhatsApp | 60 messages/second | Per WABA |

### Round-Robin Fairness

When multiple projects are sending messages, Zavu uses **round-robin scheduling** to ensure fairness:

```
Without round-robin:
Project A: 10 messages = A1, A2, A3... A10 (1 second)
Project B: 1 message  = B1 waits 1 second

With round-robin:
A1 (0ms), B1 (100ms), A2 (200ms), A3 (300ms)...
B1 only waits 100ms instead of 1 second
```

This prevents high-volume senders from blocking smaller senders.

> **Note:**
> Messages are never dropped due to rate limiting. They're queued and sent at the next available slot.

## Managing Senders

### List Senders

```bash
curl https://api.zavu.dev/v1/senders \
  -H "Authorization: Bearer zv_live_xxx"
```

### Create Sender

```bash
curl -X POST https://api.zavu.dev/v1/senders \
  -H "Authorization: Bearer zv_live_xxx" \
  -d '{
    "name": "Marketing Sender",
    "phoneNumber": "+13125559999",
    "setAsDefault": false
  }'
```

### Update Sender

```bash
curl -X PATCH https://api.zavu.dev/v1/senders/sender_12345 \
  -H "Authorization: Bearer zv_live_xxx" \
  -d '{
    "name": "Updated Name",
    "setAsDefault": true
  }'
```

## Webhook Configuration

Each sender can have one webhook configured to receive real-time notifications for events like incoming messages and delivery updates. See the [Webhooks guide](https://www.zavu.dev/docs/guides/receiving-messages/webhooks) for payload details and security.

### Create Sender with Webhook

```bash
curl -X POST https://api.zavu.dev/v1/senders \
  -H "Authorization: Bearer zv_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support",
    "phoneNumber": "+15551234567",
    "webhookUrl": "https://your-app.com/webhooks",
    "webhookEvents": ["message.inbound", "message.delivered", "message.failed"]
  }'
```

The response includes the webhook secret (only shown once):

```json
{
  "id": "sender_12345",
  "name": "Support",
  "webhook": {
    "url": "https://your-app.com/webhooks",
    "events": ["message.inbound", "message.delivered", "message.failed"],
    "secret": "whsec_abc123...",
    "active": true
  }
}
```

### Update Webhook

```bash
curl -X PATCH https://api.zavu.dev/v1/senders/sender_12345 \
  -H "Authorization: Bearer zv_live_xxx" \
  -d '{
    "webhookUrl": "https://new-url.com/webhooks",
    "webhookEvents": ["message.inbound"],
    "webhookActive": false
  }'
```

### Regenerate Webhook Secret

If your webhook secret is compromised:

```bash
curl -X POST https://api.zavu.dev/v1/senders/sender_12345/webhook/secret \
  -H "Authorization: Bearer zv_live_xxx"
```

### Available Webhook Events

| Event | Description |
|-------|-------------|
| `message.queued` | Message created and queued for sending |
| `message.sent` | Message accepted by the provider |
| `message.delivered` | Message delivered to recipient |
| `message.failed` | Message delivery failed |
| `message.inbound` | Contact sent you a message |
| `message.unsupported` | Received an unsupported message type |
| `conversation.new` | First message from a new contact |
| `template.status_changed` | WhatsApp template approval status changed |

> **Note:**
> For webhook payload structure and signature verification, see the [Webhooks guide](https://www.zavu.dev/docs/guides/receiving-messages/webhooks) and [Webhook Security](https://www.zavu.dev/docs/guides/receiving-messages/security).

## Best Practices

  - **Configure Multiple Channels**: Set up both SMS and WhatsApp on your sender to enable smart routing and automatic fallback.
  - **Use Templates for Outreach**: When initiating conversations, use [WhatsApp templates](https://www.zavu.dev/docs/concepts/templates) to avoid 24-hour window issues.
  - **Monitor Metrics**: Check your [contact](https://www.zavu.dev/docs/guides/contacts/overview) metrics to understand channel performance in your region.
  - **Set Allowed Destinations**: Restrict senders to specific countries to control costs and compliance.

## Next Steps

  - [Adding Channels](https://www.zavu.dev/docs/guides/senders/adding-channels): Connect SMS, WhatsApp, Email, Telegram, and more to your sender
  - [Phone Numbers](https://www.zavu.dev/docs/concepts/phone-numbers): Purchase and manage phone numbers for SMS and voice
  - [Templates](https://www.zavu.dev/docs/concepts/templates): Create WhatsApp templates for outbound messaging
  - [Smart Routing Guide](https://www.zavu.dev/docs/guides/sending-messages/smart-routing): Deep dive into routing configuration

## API Reference

Manage senders programmatically:

- [List senders](https://www.zavu.dev/docs/api-reference/list-senders) — fetch all senders for your project
- [Create a sender](https://www.zavu.dev/docs/api-reference/create-sender) — register a new messaging profile
- [Get a sender](https://www.zavu.dev/docs/api-reference/get-sender) — retrieve sender details by ID
- [Update a sender](https://www.zavu.dev/docs/api-reference/update-sender) — change profile, channels, or webhooks
- [Delete a sender](https://www.zavu.dev/docs/api-reference/delete-sender) — remove a sender from your project
