Send a message
Send a message to a recipient via SMS or WhatsApp.
Channel selection:
- If
channelis omitted andmessageTypeistext, defaults to SMS - If
messageTypeis anything other thantext, WhatsApp is used automatically
WhatsApp 24-hour window:
- Free-form messages (non-template) require an open 24h window
- Window opens when the user messages you first
- Use template messages to initiate conversations outside the window
Plan allowances and email billing:
- WhatsApp, Telegram, Instagram and Messenger share an allowance of 2,000 messages per month on Free. It counts messages in both directions: a message a contact sends you consumes one unit exactly as a message you send them does, so a project that has sent 300 and received 1,700 has used the whole allowance. Messages you send from the WhatsApp Business App on your own phone under coexistence are mirrored into your inbox but never counted, and neither are failed sends. Over the allowance, sends return 429 with code
a2p_limit_exceededand upgrade details, and inbound messages on those channels are refused as well: not stored, not shown in the inbox, and nomessage.inboundwebhook, and not delivered later when the month resets. The counter resets on the 1st of each month. Paid plans have no message caps - Email is billed from your prepaid balance in 1,000-message blocks: 0.80 per 1,000 marketing (broadcast) emails. A block is charged when your monthly count crosses each 1,000 boundary, and at zero balance email sends return 402 with code
insufficient_balance. Free teams start with $2 of credit and additionally cap at 3,000 emails/month and 100/day. Teams on earlier plans keep their original email quotas instead - SMS and voice are billed per message from your balance on every plan
Daily limits:
- An account sends on every channel from its first minute, to any destination. Verification is not a permission to send: identity verification and business verification (KYB) raise the ceilings below and nothing else asks for them here. KYB is still required to register a 10DLC brand and campaign, which every US and Canadian (+1) SMS destination needs — a carrier rule, answered separately with
403 ten_dlc_required - Daily ceilings apply per channel group and rise with verification. An account that has verified nothing: 25/day across
sms+sms_oneway, 5/day forvoice, 100/day across WhatsApp, Telegram, Instagram and Messenger combined. Past that floor: 200/day for SMS, or 10,000/day once identity or business verification is approved (or a higher limit agreed for your account); 50/day voice and 250/day conversational on Free. Paid plans have no voice or conversational daily ceiling. Over a ceiling, sends return429with codedaily_limit_exceededanddetails.limit; the count resets at 00:00 UTC - The daily ceiling never reduces the monthly allowance: 100/day on the conversational group still reaches the 2,000 monthly A2P messages Free includes
- Email: a sender with a verified domain sends from day one, within the plan quota (100/day and 3,000/month on Free). Over the daily quota it returns
429with codedaily_limit_exceeded - Full reference: https://docs.zavu.dev/concepts/sending-limits
Risk review:
Every outbound sms, sms_oneway, email and voice message is read before it is sent — the content, and how this account has been sending. What is checked is the message, not who you are.
- A message can be held for a short review. It stays
queuedwhile it waits: no new status exists for this, andMessageStatusis unchanged. When it is approved it sends normally. - A message that is not approved moves to
failedand firesmessage.failed.errorCodesays which happened:RISK_REJECTED(a reviewer refused it),RISK_REVIEW_EXPIRED(the review window closed first — it is a couple of hours, because a code that arrives late is worse than one that does not arrive), orRISK_BLOCKED(refused outright, without a hold). An SMS that fails this way is not charged; the prepaid amount is returned. - A call is never held.
POST /v1/callsfails a call the review stops rather than placing it hours late. - A message whose content cannot be read — the check is briefly unavailable — is held rather than sent. An account with an approved business verification is unaffected, and so is one that has verified something, already sends real traffic, and has a clean recent record.
- Repeated refusals suspend an account’s sending. While it is suspended every send is refused with
403and codesending_suspended,details.dashboardUrlpoints at support, and a message already queued fails witherrorCodeSENDING_SUSPENDED. - A broadcast is read once, on the broadcast itself, rather than per recipient — see
POST /v1/broadcasts/{broadcastId}/send.
Email recipient pre-flight:
Email messages are validated automatically before dispatch. Sends that would be a guaranteed hard bounce are failed instead of sent, protecting your bounce rate: the message transitions to failed (visible via GET /v1/messages/{messageId} and the message.failed webhook) with errorCode set to EMAIL_INVALID_RECIPIENT (malformed address), EMAIL_DOMAIN_NOT_FOUND (recipient domain has no MX or A records), or EMAIL_RECIPIENT_SUPPRESSED (address is on your suppression list after a previous bounce or complaint). Advisory signals (role addresses, disposable domains) do not block sends — check them beforehand with POST /v1/introspect/email.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
Optional sender profile ID. If omitted, the project's default sender will be used.
"sender_12345"
Body
Request body to send a message.
Recipient phone number in E.164 format, email address, WhatsApp business-scoped user ID (BSUID, e.g. US.13491208655302741918), or numeric chat ID (for Telegram/Instagram/Messenger). A BSUID is routed to WhatsApp and sent via the recipient field; use it to message a contact who adopted a username and whose phone number is hidden.
"+56912345678"
Delivery channel. Use 'auto' for intelligent routing. If omitted, channel is auto-selected based on sender capabilities and recipient type. For email recipients, defaults to 'email'.
auto, sms, sms_oneway, whatsapp, telegram, email, instagram, messenger, voice Type of message. Defaults to 'text'.
text, image, video, audio, document, sticker, location, contact, buttons, list, cta_url, request_contact_info, location_request, reaction, template Text body for text messages or caption for media messages.
"Your verification code is 123456."
Additional content for non-text message types.
Email subject line. Required when channel is 'email' or recipient is an email address.
998"Your order confirmation"
HTML body for email messages. If provided, email will be sent as multipart with both text and HTML.
Reply-To email address for email messages.
"support@example.com"
Optional idempotency key to avoid duplicate sends.
"msg_01HZY4ZP7VQY2J3BRW7Z6G0QGE"
Arbitrary metadata to associate with the message.
Whether to enable automatic fallback to SMS if WhatsApp fails. Defaults to true.
Language code for voice text-to-speech (e.g., 'en-US', 'es-ES', 'pt-BR'). If omitted, language is auto-detected from recipient's country code.
"es-ES"
Email attachments. Only supported when channel is 'email'. Maximum 40MB total size.
50Response
Message accepted for delivery.
