Skip to content

Send SMS Messages with Zavu

Send SMS messages programmatically to any phone number worldwide. REST API, a TypeScript SDK, smart routing across carriers.

View .md

SMS (Short Message Service) is the most universal messaging channel, reaching virtually any mobile phone without requiring an internet connection or app installation.

When to Use SMS

  • Verification codes: OTPs, 2FA
  • Transactional alerts: Order confirmations, shipping updates
  • Time-sensitive notifications: Appointment reminders
  • Universal reach: When you need to reach users without smartphones

Sending an SMS

const result = await zavu.messages.send({ to: "+14155551234", text: "Your verification code is 123456", channel: "sms", });

Message Length

SMS messages are limited to 160 characters (GSM-7 encoding) or 70 characters (Unicode). Longer messages are split into multiple segments.

EncodingSingle SMSConcatenated SMS
GSM-7160 chars153 chars/segment
Unicode70 chars67 chars/segment

Character Encoding

GSM-7 supports basic Latin characters. Using emojis, accents, or non-Latin scripts triggers Unicode encoding:

Code
GSM-7: "Your code is 123456" (20 chars, 1 segment) Unicode: "Your code is 123456" (22 chars, 1 segment with special chars) Unicode: "Tu codigo es 123456" (19 chars, 1 segment, 'o' with accent triggers Unicode)

GSM-7 Character Set

Code
A-Z a-z 0-9 @ $ _ ! " # % & ' ( ) * + , - . / : ; < = > ? Space, newline, carriage return

Any character outside this set triggers Unicode encoding.

Sender ID

Some countries support alphanumeric sender IDs (e.g., "ZAVU" instead of a phone number).

Supported Countries

RegionAlphanumeric Sender ID
US/CanadaNot supported (10DLC or short code required)
UKSupported
EUMostly supported
LATAMVaries by country

SMS Templates

Send pre-defined templates via SMS by specifying channel: "sms" and messageType: "template":

const result = await zavu.messages.send({ to: "+14155551234", channel: "sms", messageType: "template", content: { templateId: "tpl_abc123", templateVariables: { "1": "John", "2": "ORD-12345", }, }, });

If the template has an smsBody, it will be used instead of the default body. Contact variables like {{contact.first_name}} are automatically resolved from the recipient's contact metadata.

Delivery Status

Check message status by ID:

terminal
curl https://api.zavu.dev/v1/messages/msg_abc123 \ -H "Authorization: Bearer zv_live_xxx"
StatusDescription
queuedAccepted, pending delivery
sentSent to carrier
deliveredConfirmed delivered
failedDelivery failed

Common Errors

Error CodeDescriptionSolution
30003Unreachable destinationInvalid number or phone off
30004Message blockedContent filtered by carrier
30005Unknown destinationNumber doesn't exist
30006Landline destinationCannot send SMS to landlines
30007Carrier violationMessage rejected by carrier

Compliance

Requirements

  • Opt-in consent: Users must explicitly agree to receive SMS
  • Opt-out mechanism: Include instructions to unsubscribe (e.g., "Reply STOP to unsubscribe")
  • Business identification: Identify your business in the message
  • Time restrictions: Avoid sending during quiet hours (typically 9 PM - 9 AM local time)

Content check

Every SMS and one-way SMS with text is read before it is sent. A message the check refuses is answered right away with 422 and code sms_compliance_blocked; nothing is sent or charged. One-time codes (verification codes) always pass.

JSON
{ "code": "sms_compliance_blocked", "message": "SMS blocked: The message asks for a payment through a link without identifying the sender.", "details": { "riskScore": 85, "messageType": "marketing", "complianceFailures": [ { "code": "MISSING_SENDER_ID", "severity": "high", "title": "Sender not identified" } ], "requiredFixes": ["Name your business in the message."], "suggestedCompliantVersion": "[YourBrand] Your invoice is ready: https://yourbrand.com/pay/123" } }

Apply requiredFixes, or send suggestedCompliantVersion when there is one, and send again. If the check itself could not run, message says so; retry in a few minutes.

Example Compliant Message

Code
[YourBrand] Your order #12345 has shipped! Track: https://track.co/abc Reply STOP to unsubscribe

Best Practices

  1. Keep it short - Aim for under 160 characters
  2. Identify yourself - Start with your brand name
  3. Be actionable - Include clear next steps or links
  4. Respect timing - Send during business hours in the recipient's timezone
  5. Provide opt-out - Always include unsubscribe instructions for marketing messages