API reference
SMSLab speaks Twilio's Programmable Messaging wire format, so an app already written
for Twilio works unchanged: point its base URL here. Sign up to get your own
ACCOUNT_SID and token.
Point your app
One environment variable. Everything else is your existing Twilio code.
TWILIO_API_BASE=https://smslab.subdot.link TWILIO_SID=AC… # from your dashboard TWILIO_TOKEN=… # from your dashboard
Send a message
HTTP basic auth (ACCOUNT_SID:AUTH_TOKEN), form-encoded body.
POST https://smslab.subdot.link/2010-04-01/Accounts/{AccountSid}/Messages.json
To +15552000001
From +14704678554 (your service number)
Body hello
A success returns 201 with the Message resource (sid,
status: queued, RFC 2822 dates, the usual Twilio fields). Errors return
the Twilio envelope:
{"code": 21211, "message": "Invalid 'To' Phone Number",
"more_info": "https://www.twilio.com/docs/errors/21211", "status": 400}
| Code | Meaning |
|---|---|
| 20003 | authentication failed |
| 21211 | invalid 'To' number |
| 21603 | missing 'From' |
| 21606 | 'From' not owned by the account |
| 21610 | recipient opted out (replied STOP) |
Inbound webhook
When someone replies on a virtual phone, SMSLab POSTs your configured webhook URL a
form-encoded request with a valid X-Twilio-Signature header — the same
HMAC-SHA1 scheme Twilio uses, so your existing signature validation passes unchanged.
POST {your webhook URL}
Header X-Twilio-Signature: base64(HMAC-SHA1(url + sorted params, AuthToken))
Body From, To, Body, MessageSid, NumMedia, NumSegments
Replying STOP opts the number out (later sends answer 21610);
START opts back in. Your app still runs its own STOP handling — SMSLab
just delivers the message.
The board
Each workspace has a private board: your service number's traffic on tiled virtual phones, plus a chronological event strip of every API call and webhook. Sign in to view your own.