Sending Your First SMS
Once your account is set up and a number is provisioned, sending a message takes one API call. This article walks through the pre-flight, the call itself, delivery tracking, and what to do if something goes wrong.
Just want to try the API? You don't need a brand, campaign, or number to send your first request. Use the shared test phone described in Testing SMS With the Shared Test Phone — same endpoint, same SDK, just prefix the body with
[Otter]. Switch thefromto your real number when you're ready for production traffic.
Pre-flight checklist
| Step | Where |
|---|---|
| Brand registered and Verified | Brand Registry |
| 10DLC campaign in Approved status | Campaigns → 10DLC |
| At least one number attached to the campaign | Numbers → Manage |
| Number belongs to a messaging profile | Messaging Profiles |
API key with messages.send permission |
API Keys |
| Balance sufficient for at least one segment | Billing → Overview |
If any box is unchecked, the API returns a clear error pointing to the step you missed.
The API call
curl -X POST https://api.otterblocx.com/messaging/send \
-H "x-access-key-id: $BLOCX_ACCESS_KEY_ID" \
-H "x-secret-access-key: $BLOCX_SECRET_ACCESS_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "+15551234567",
"to": "+15557654321",
"body": "Hello from Blocx!",
"type": "SMS"
}'
Response (202 Accepted):
{
"messageId": "msg_...",
"type": "SMS",
"status": "QUEUED",
"to": "+15557654321",
"from": "+15551234567"
}
Full reference: api.otterblocx.com/docs.
Using the SDK
import { createBlocxClient, Messaging } from '@otterlabs/blocx'
const { client } = createBlocxClient({
accessKeyId: process.env.BLOCX_ACCESS_KEY_ID!,
secretAccessKey: process.env.BLOCX_SECRET_ACCESS_KEY!,
})
const res = await Messaging.sendMessage({
client,
body: {
from: '+15551234567',
to: '+15557654321',
body: 'Hello from Blocx!',
type: 'SMS',
},
})
console.log(res.data?.messageId)
Install: npm install @otterlabs/blocx. Source on npm: @otterlabs/blocx.
MMS
Set type: 'MMS' and pass mediaUrls:
await Messaging.sendMessage({
client,
body: {
from: '+15551234567',
to: '+15557654321',
body: 'Check this out',
type: 'MMS',
mediaUrls: ['https://cdn.example.com/image.png'],
},
})
The sending number must have MMS capability. Check at Numbers → Manage.
Tracking delivery
Configure a webhook endpoint at Developer → Webhooks and subscribe to message.sent, message.delivered, and message.failed to receive each transition. Status is also visible per-message at Messaging → Debug and aggregated at Messaging → Reports.
Compliance basics
- Include opt-out language ("Reply STOP to opt out") in the first message of any new conversation, especially marketing.
- Honor STOP, HELP, START, and other standard keywords. Blocx handles
STOPautomatically at the profile level when configured — see Creating a Messaging Profile. - Don't message anyone without opt-in. Carrier filters will block you and your compliance inbox will light up.
- Respect quiet hours. Most jurisdictions disallow non-emergency commercial SMS before 8am or after 9pm in the recipient's local time.
Debugging a failed send
If the API returns an error or the message later fails:
- Note the message ID from the response (or webhook event).
- Open Messaging → Debug and paste the ID.
- The timeline shows the full path: request received → routing decision → carrier handoff → carrier response → delivery receipt.
- Each step displays its exact payload and any error codes.
Common errors:
| Code | Meaning | Fix |
|---|---|---|
30003 |
Unreachable handset | Retry later |
30005 |
Unknown destination | Number doesn't exist |
30006 |
Landline / can't receive SMS | Validate numbers before sending |
30007 |
Filtered by carrier | Review content and opt-in; see compliance inbox |
30008 |
Carrier-side unknown | Retry with backoff |
21610 |
Recipient opted out | Stop sending to this number |
See Messaging Reports and Debugging Tools for deeper troubleshooting.
Next steps
- Set up webhooks for delivery receipts.
- Add auto-recharge so high-volume sending never pauses.
- Watch deliverability at Messaging → Reports.