Skip to content

Senders — Smart Routing & Fallback

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

View .md

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 messaging
  • WhatsApp Business Account — for WhatsApp messaging (rich media, templates, interactive messages)
  • Email domain — for transactional email via Amazon SES
  • Telegram bot — for Telegram messaging
  • Instagram Business Account — for Instagram direct messaging
  • Webhooks — real-time notifications for inbound messages and delivery updates
  • Allowed destinations — countries you can send to
{ "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:

ChannelIdentifierSmart RoutingFallbackSetup Guide
SMSPhone number (E.164)YesYesSMS Guide
WhatsAppPhone number (E.164)YesYesWhatsApp Guide
EmailEmail addressNoNoEmail Guide
TelegramTelegram chat IDNoNoTelegram Guide
InstagramInstagram-scoped IDNoNo—
VoicePhone number (E.164)NoNoSending Messages

Default Sender

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

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

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

When Smart Routing Applies

Message TypeRouting 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:

Code
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

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

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

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 works between SMS and WhatsApp only.

Fallback Flow

Code
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

RuleDescription
Max 2 attemptsEach message is tried on at most 2 channels
5-second delayWait 5 seconds before retry to avoid race conditions
No duplicate channelsNever retry on a channel that already failed
Sender must support bothFallback only works if sender has both channels configured

Enabling/Disabling Fallback

Whether fallback runs depends on how you choose the channel:

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

ChannelKey RequirementDocs
EmailA domain you own, verified in ZavuEmail Setup
TelegramBot token via BotFatherTelegram Setup
InstagramInstagram Business Account—
VoicePhone number with voice capabilitySending Messages

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 to ensure reliable delivery for all users.

Limits by Channel

ChannelRate LimitLevel
SMS10 messages/secondGlobal
Email14 messages/secondGlobal
WhatsApp60 messages/secondPer WABA

Round-Robin Fairness

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

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

Managing Senders

List Senders

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

Create Sender

terminal
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

terminal
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 for payload details and security.

Create Sender with Webhook

terminal
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

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

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

Available Webhook Events

EventDescription
message.queuedMessage created and queued for sending
message.sentMessage accepted by the provider
message.deliveredMessage delivered to recipient
message.failedMessage delivery failed
message.inboundContact sent you a message
message.unsupportedReceived an unsupported message type
conversation.newFirst message from a new contact
template.status_changedWhatsApp template approval status changed

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 to avoid 24-hour window issues.

Monitor Metrics

Check your contact metrics to understand channel performance in your region.

Set Allowed Destinations

Restrict senders to specific countries to control costs and compliance.

Next Steps

API Reference

Manage senders programmatically: