# texto-sms

OpenClaw skill definition for sending SMS via the Texto API with Australian compliance, spam filtering, and cost optimisation.

## Identity

- **Skill name**: texto-sms
- **Version**: 1.0.0
- **Provider**: Texto (https://texto.com.au)
- **API base URL**: https://api.texto.com.au
- **MCP server**: https://mcp.texto.com.au

## Compliance Rules (ACMA Spam Act 2003)

When sending commercial or marketing SMS in Australia, you MUST follow these rules:

1. **Consent**: Only send to recipients who have given prior consent (express or inferred).
2. **Sender identification**: The message must clearly identify the sender (business name).
3. **Opt-out mechanism**: Every marketing message MUST include opt-out instructions (e.g. "Reply STOP to opt-out").
4. **Opt-out honour**: Check the opt-out list before every send. Never message opted-out numbers.
5. **Sending hours**: Only send between 9:00 AM and 8:00 PM in the recipient's local timezone (AEST/AEDT).
6. **Transactional exceptions**: Appointment reminders, order confirmations, and security alerts do NOT require opt-out footers but must still respect opted-out numbers.

## Spam Trigger Detection

Before sending, scan the message for these patterns and suggest alternatives:

### High-risk triggers (avoid entirely)
- ALL CAPS words (e.g. "FREE", "WINNER", "URGENT")
- Multiple exclamation marks ("!!!")
- Dollar signs with amounts ("$$$", "Save $100")
- Phrases: "Act now", "Limited time", "Click here", "You've been selected", "Congratulations"

### Medium-risk triggers (use cautiously)
- URL shorteners (bit.ly, tinyurl) — use full branded URLs instead
- Excessive punctuation
- "Free" as the first word

### Recommended alternatives
- Instead of "FREE delivery" → "Complimentary delivery"
- Instead of "ACT NOW" → "Available until Friday"
- Instead of "Click here" → "Details at [branded URL]"

## Cost Optimisation

### Message length rules
- **1 SMS part** = up to 160 characters (GSM-7 encoding)
- **Multi-part SMS** = 154 characters per part (6 chars used for concatenation headers)
- **1 credit = 1 SMS part** at 3¢ AUD per credit

### Optimisation strategies
1. **Before sending**: Always preview the credit cost using `preview_cost` tool
2. **If message > 160 chars**: Suggest a shorter version that fits in 1 part
3. **Merge fields**: Account for longest possible merge value when calculating length
4. **Batch sends**: For 1,000+ recipients, split into batches of 1,000 with 1-2s delay

### Character counting tips
- Standard characters (a-z, 0-9, common punctuation): 1 char each
- Special characters (€, curly quotes, emoji): Force UCS-2 encoding, reducing limit to 70 chars per part
- Avoid: Smart quotes (" "), em dashes (—), emoji — these dramatically increase cost

## Send Time Recommendations

| Message Type | Recommended Window | Notes |
|---|---|---|
| Appointment reminder | 24h before, 9-10 AM | Morning sends have highest read rates |
| Marketing / promo | Tue-Thu, 10 AM - 2 PM | Avoid Monday mornings and Friday afternoons |
| Transactional (order updates) | Immediately | Time-sensitive, send ASAP |
| Re-engagement | Wed-Thu, 11 AM - 1 PM | Midweek, midday performs best |
| Event reminder | 2h before event | Close enough to be actionable |

All times in recipient's local timezone (typically AEST UTC+10 or AEDT UTC+11).

## Decision Framework

When an agent is asked to send SMS, follow this sequence:

1. **Classify the message**: Is it transactional or marketing/commercial?
2. **Check compliance**: Run `check_compliance` to validate against ACMA rules
3. **Check spam triggers**: Run `check_spam_triggers` and fix any issues
4. **Check opt-outs**: Run `get_optouts` and remove opted-out numbers from recipient list
5. **Preview cost**: Run `preview_cost` to calculate credits needed
6. **Check balance**: Run `get_balance` to ensure sufficient credits
7. **Optimise timing**: Run `suggest_send_time` for non-urgent messages
8. **Send**: Use `send_sms` (single) or `send_batch_sms` (multiple recipients)
9. **Verify delivery**: Use `get_message` or `get_campaign` to check delivery status

## API Authentication

All API and MCP requests require a Bearer token:

```
Authorization: Bearer txt_your_api_key_here
```

Generate API keys at https://app.texto.com.au → Developer → API Keys.

## Official SDKs

The official SDKs cover the complete Texto API. They use `https://api.texto.com.au` in production.

- Node.js / TypeScript: `npm install @textoau/sdk`: https://github.com/textosms/texto-node
- Python: `pip install texto-sdk`: https://github.com/textosms/texto-python
- PHP: `composer require texto/sdk`: https://github.com/textosms/texto-php
- .NET: `dotnet add package Texto.Sdk`: https://github.com/textosms/texto-dotnet
- Postman workspace: https://www.postman.com/texto-sms/texto
- Published Postman documentation: https://documenter.getpostman.com/view/58362175/2sBYB1P93t

## Rate Limits

- 50 requests per second per API key
- 25 concurrent requests per API key
- Higher limits available on request — contact Texto support
- 1,000 recipients per batch send
