# SEND SMS

Send SMS text messages to phone numbers using various providers with optional priority levels.

## Syntax

```basic
' Basic SMS sending (default priority: normal)
SEND SMS phone, message

' With priority level
SEND SMS phone, message, priority

' With specific provider
SEND SMS phone, message, provider

' With provider AND priority (full syntax)
SEND SMS phone, message, provider, priority
```

## Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `phone` | String | Yes | Recipient phone number (E.164 format recommended) |
| `message` | String | Yes | The text message to send (max 160 chars for single SMS) |
| `priority` | String | No | Priority level: `low`, `normal`, `high`, `urgent` |
| `provider` | String | No | SMS provider: `twilio`, `aws_sns`, `vonage`, `messagebird`, or custom |

### Priority Levels

| Priority | Description | Provider Behavior |
|----------|-------------|-------------------|
| `low` | Non-urgent, promotional messages | Standard delivery |
| `normal` | Default priority | Standard delivery |
| `high` | Important messages | Transactional routing (AWS SNS), priority prefix |
| `urgent` | Critical/time-sensitive | Flash message (Vonage), [URGENT] prefix (Twilio) |

## Return Value

Returns a map object with the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `success` | Boolean | `true` if SMS was sent successfully |
| `message_id` | String | Provider's message ID for tracking |
| `provider` | String | The provider used to send the message |
| `to` | String | Normalized recipient phone number |
| `priority` | String | The priority level used |
| `error` | String | Error message (only present if `success` is `false`) |

## Configuration

Configure SMS provider credentials in `config.csv`:

```csv
key,value
sms-provider,twilio
sms-default-priority,normal
twilio-account-sid,YOUR_ACCOUNT_SID
twilio-auth-token,YOUR_AUTH_TOKEN
twilio-from-number,+15551234567
```

### Provider-Specific Configuration

**Twilio:**
```csv
sms-provider,twilio
twilio-account-sid,ACxxxxx
twilio-auth-token,your_token
twilio-from-number,+15551234567
```

**AWS SNS:**
```csv
sms-provider,aws_sns
aws-access-key,AKIAXXXXXXXX
aws-secret-key,your_secret
aws-region,us-east-1
```

**Vonage (Nexmo):**
```csv
sms-provider,vonage
vonage-api-key,your_api_key
vonage-api-secret,your_secret
vonage-from-number,+15551234567
```

**MessageBird:**
```csv
sms-provider,messagebird
messagebird-access-key,your_access_key
messagebird-originator,YourBrand
```

## Examples

### Basic SMS

```basic
HEAR phone AS TEXT "Enter phone number:"
SEND SMS phone, "Hello from General Bots!"
TALK "SMS sent successfully!"
```

### SMS with Priority

```basic
' Send urgent notification
result = SEND SMS "+15551234567", "Server is DOWN! Immediate action required.", "urgent"

IF result.success THEN
    TALK "Urgent alert sent with ID: " + result.message_id
ELSE
    TALK "Failed to send alert: " + result.error
END IF
```

### Order Confirmation (Normal Priority)

```basic
' Send order confirmation via SMS
order_id = "ORD-2025-001"
phone = customer.phone

message = "Your order " + order_id + " has been confirmed. "
message = message + "Estimated delivery: 2-3 business days."

result = SEND SMS phone, message, "normal"

IF result.success THEN
    TALK "Confirmation SMS sent to " + phone
ELSE
    TALK "Failed to send SMS. We'll email you instead."
    SEND MAIL customer.email, "Order Confirmation", message, []
END IF
```

### Two-Factor Authentication (High Priority)

```basic
' Generate and send OTP with high priority for faster delivery
otp = RANDOM(100000, 999999)
REMEMBER "otp_" + user.id, otp, "5 minutes"

message = "Your verification code is: " + otp + ". Valid for 5 minutes."
result = SEND SMS user.phone, message, "high"

IF NOT result.success THEN
    TALK "Failed to send verification code. Please try again."
    RETURN
END IF

HEAR entered_code AS TEXT "Enter the code sent to your phone:"

stored_otp = RECALL "otp_" + user.id

IF entered_code = stored_otp THEN
    TALK "✅ Phone verified successfully!"
    SET USER MEMORY "phone_verified", true
ELSE
    TALK "❌ Invalid code. Please try again."
END IF
```

### Emergency Alert (Urgent Priority)

```basic
' Send emergency notification to multiple recipients
alert_message = "⚠️ ALERT: System maintenance in 30 minutes. Save your work."

contacts = FIND "emergency_contacts", "notify=true"

sent_count = 0
failed_count = 0

FOR EACH contact IN contacts
    result = SEND SMS contact.phone, alert_message, "urgent"
    
    IF result.success THEN
        sent_count = sent_count + 1
    ELSE
        failed_count = failed_count + 1
        PRINT "Failed to send to " + contact.phone + ": " + result.error
    END IF
    
    WAIT 100  ' Small delay between messages
NEXT

TALK "Emergency alert sent to " + sent_count + " contacts (" + failed_count + " failed)"
```

### Using Specific Provider with Priority

```basic
' Use AWS SNS for high-priority transactional messages
result = SEND SMS "+15551234567", "Your appointment is in 1 hour!", "aws", "high"

IF result.success THEN
    TALK "Reminder sent via " + result.provider + " with " + result.priority + " priority"
END IF
```

### Priority-Based Routing

```basic
' Route messages based on urgency
SUB send_notification(phone, message, urgency)
    SELECT CASE urgency
        CASE "critical"
            ' Use multiple channels for critical messages
            result = SEND SMS phone, message, "urgent"
            SEND MAIL user.email, "CRITICAL: " + message, message, []
            
        CASE "important"
            result = SEND SMS phone, message, "high"
            
        CASE "info"
            result = SEND SMS phone, message, "low"
            
        CASE ELSE
            result = SEND SMS phone, message, "normal"
    END SELECT
    
    RETURN result
END SUB

' Usage
send_notification(customer.phone, "Your package has been delivered!", "important")
```

### Appointment Reminder with Priority

```basic
' Send appointment reminder based on time until appointment
hours_until = DATEDIFF(appointment.datetime, NOW(), "hour")

IF hours_until <= 1 THEN
    ' Urgent - appointment is very soon
    priority = "urgent"
    message = "⏰ REMINDER: Your appointment is in " + hours_until + " hour(s)!"
ELSE IF hours_until <= 4 THEN
    ' High priority - same day
    priority = "high"
    message = "Reminder: Your appointment is today at " + FORMAT(appointment.datetime, "h:mm A")
ELSE
    ' Normal priority - advance reminder
    priority = "normal"
    message = "Reminder: You have an appointment on " + FORMAT(appointment.datetime, "MMMM D")
END IF

result = SEND SMS patient.phone, message, priority

IF result.success THEN
    UPDATE "appointments", appointment.id, "reminder_sent", true
END IF
```

### Bulk SMS with Priority Levels

```basic
' Send promotional messages with low priority (cost-effective)
customers = FIND "customers.csv", "marketing_opt_in = true"

FOR EACH customer IN customers
    message = "Hi " + customer.first_name + "! Check out our weekend sale - 20% off!"
    
    ' Use low priority for promotional bulk messages
    result = SEND SMS customer.phone, message, "low"
    
    IF result.success THEN
        INSERT "sms_log", customer.phone, message, result.message_id, NOW()
    END IF
    
    WAIT 500  ' Rate limiting for bulk sends
NEXT

TALK "Campaign completed!"
```

### Multi-Channel Fallback with Priority

```basic
' Try SMS first, fall back to other channels
SUB notify_user(user, message, priority)
    ' Try SMS first
    result = SEND SMS user.phone, message, priority
    
    IF result.success THEN
        RETURN "sms"
    END IF
    
    ' SMS failed, try WhatsApp
    wa_result = SEND WHATSAPP user.phone, message
    
    IF wa_result.success THEN
        RETURN "whatsapp"
    END IF
    
    ' Fall back to email
    SEND MAIL user.email, "Notification", message, []
    RETURN "email"
    
END SUB

' Usage
channel_used = notify_user(customer, "Your order has shipped!", "high")
TALK "Notification sent via " + channel_used
```

## Phone Number Formats

The keyword accepts various phone number formats and normalizes them:

| Format | Example | Result |
|--------|---------|--------|
| E.164 | `+14155551234` | `+14155551234` |
| National (US) | `(415) 555-1234` | `+14155551234` |
| Digits only (10) | `4155551234` | `+14155551234` |
| Digits only (11) | `14155551234` | `+14155551234` |

**Best Practice:** Always use E.164 format (`+` followed by country code and number).

## Message Length

| Type | Characters | Notes |
|------|------------|-------|
| Single SMS | 160 | Standard ASCII |
| Unicode SMS | 70 | Emojis, non-Latin scripts |
| Concatenated | 153 × segments | Long messages split |

> **Note:** High and urgent priority messages may have prefixes added (e.g., `[URGENT]`), which reduces available characters.

```basic
' Check message length before sending
IF LEN(message) > 140 AND priority = "urgent" THEN
    TALK "Warning: Urgent prefix may cause message to split"
END IF

SEND SMS phone, message, priority
```

## Priority Behavior by Provider

| Provider | Low | Normal | High | Urgent |
|----------|-----|--------|------|--------|
| **Twilio** | Standard | Standard | `[HIGH]` prefix | `[URGENT]` prefix |
| **AWS SNS** | Promotional | Promotional | Transactional | Transactional |
| **Vonage** | Standard | Standard | Standard | Flash message (class 0) |
| **MessageBird** | Standard | Standard | Class 1 | Flash message (class 0) |

## Error Handling

```basic
' Handle SMS errors gracefully
result = SEND SMS phone, message, "high"

IF NOT result.success THEN
    ' Log the failure
    INSERT "sms_failures", phone, message, result.error, NOW()
    
    ' Check error type and respond
    IF result.error LIKE "*INVALID_PHONE*" THEN
        TALK "The phone number appears to be invalid."
    ELSE IF result.error LIKE "*INSUFFICIENT_FUNDS*" THEN
        TALK "SMS service temporarily unavailable."
        ' Alert admin
        SEND MAIL admin.email, "SMS Balance Low", "Please top up SMS credits", []
    ELSE
        TALK "Could not send SMS: " + result.error
    END IF
    
    ' Fallback to email if available
    IF user.email <> "" THEN
        SEND MAIL user.email, "Notification", message, []
    END IF
END IF
```

## Cost Considerations

SMS messages incur costs per message sent. Consider:

- Use `low` priority for promotional/non-urgent messages (may use cheaper routes)
- Use `high`/`urgent` only when delivery speed is critical
- Use [SEND WHATSAPP](./universal-messaging.md) for free messaging when possible
- Batch non-urgent messages to optimize costs

## Compliance

When sending SMS messages, ensure compliance with:

- **TCPA** (US) - Require consent before sending
- **GDPR** (EU) - Document consent and provide opt-out
- **LGPD** (Brazil) - Similar consent requirements

```basic
' Check opt-in before sending
IF GET USER MEMORY "sms_opt_in" = true THEN
    SEND SMS phone, message, priority
ELSE
    TALK "User has not opted in to SMS notifications"
END IF
```

## See Also

- [SEND WHATSAPP](./universal-messaging.md) - WhatsApp messaging
- [SEND MAIL](./keyword-send-mail.md) - Email messaging
- [SEND TEMPLATE](./keyword-send-template.md) - Template messages
- [Universal Messaging](./universal-messaging.md) - Multi-channel messaging
- [SMS Provider Configuration](../08-config/sms-providers.md) - Provider setup guide

## Implementation

The SEND SMS keyword is implemented in `src/basic/keywords/sms.rs` with support for multiple providers through a unified interface. Priority levels are mapped to provider-specific features for optimal delivery.