SMS
SMS via Twilio / MessageBird / Sinch with auto-shortened deep links and STOP / HELP compliance.
Features
- **Twilio integration** — `POST /orgs/:orgId/sms/send`, per-org webhook URL `POST /sms/webhooks/twilio/:orgId` with x-twilio-signature verification. **Honest:** MessageBird + Sinch adapters are not built today.
- **CTIA-compliant STOP keyword handling** — inbound `STOP / STOPALL / UNSUBSCRIBE / CANCEL / END / QUIT` writes to `sms_suppressions`; `START / UNSTOP / YES` re-subscribes. **Honest:** suppression is sms-only + per-org; does NOT propagate to email/push for the same recipient.
- **Recipient-dedup at dispatch** — same `(orgId, recipient, body)` within 60s → `status='suppressed' suppressed_reason='recent_duplicate'`. Same belt-and-braces as Email.
- **Pre-send suppression check** — recipient on the org's `sms_suppressions` list → `status='failed' metadata.suppressed=true`. Customer API cannot bypass.
- **`sms.*` events** — `sms.sent` + `sms.delivered` + `sms.failed` fire on the platform bus. **Honest:** no `sms.replied` event today — inbound non-keyword messages aren't surfaced as first-class events.
- **Per-org rate limit + quota meter** — `reserveQuota` decrements before send; `QuotaExceededError` on hit.
- **Audit log on every send** — actor + resource + payload size recorded.
- **Honest non-features:** no audience-targeted single-call send (fan-out via Automation workflow); no Deep Links auto-wrap on outbound bodies; no per-region cost controls (international spend caps not built); no MessageBird / Sinch adapters; no Verify-API integration for OTP (use Auth Service's email OTP instead).
Common use cases
- BYOP Twilio SMS in a stack where the same tenant also handles Auth + Customers + Audit — useful when you need the dedup window + STOP keyword compliance without a separate platform.
- Cross-channel lifecycle via Automation workflows where SMS is a step (Push → wait → Email → SMS) — fan-out happens per-step.
- Transactional SMS (order confirmations, alerts) where you already pay Twilio + just need the platform-level send + audit + suppression layer on top.
SMS
Send an SMS
STARTER+Server-side send via Twilio (sk_* secret key). Per-org rate-limited. STOP-list checked before delivery — suppressed numbers silently dropped + logged.
curl -X POST https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/sms/send \
-H "x-api-key: pk_prod_…" \
-d '{ "to": "+15551234567", "body": "Your code is 482910", "category": "transactional" }'STOP / START keyword handling
STARTER+TCPA + CTIA Tier 1 keywords (STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, QUIT) auto-suppress. Twilio inbound webhook signed via HMAC-SHA1.
# Inbound webhook URL to set in Twilio console (org id baked in path):
# https://api.sendoracloud.com/api/v1/sms/webhooks/twilio/<ORG_UUID>
# Twilio signs with auth token — Sendora verifies signature before processing.Query send history
STARTER+List recent sends + per-send detail. Filter by status / phone / category. Aggregate counters via /stats.
# List
curl 'https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/sms/sends?status=failed' \
-H "x-api-key: pk_prod_…"
# Aggregate
curl https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/sms/stats \
-H "x-api-key: pk_prod_…"Manual suppression
STARTER+Manually suppress a number (opt-out form / customer support request). Returns 409 if already suppressed. ADMIN role required.
# Add
curl -X POST https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/sms/suppressions \
-H "x-api-key: pk_prod_…" \
-d '{ "phoneNumber": "+15551234567", "reason": "user_request" }'
# List
curl https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/sms/suppressions \
-H "x-api-key: pk_prod_…"
# Remove (URL-encode the phone — '+' becomes '%2B')
curl -X DELETE https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/sms/suppressions/<PHONE_E164_URLENCODED> \
-H "x-api-key: pk_prod_…"Configure Twilio
STARTER+Per-org Twilio credentials (Account SID + Auth Token + From number). Stored AES-256-GCM at rest. Configure in Dashboard → SMS → Provider; sends return 412 until configured.
# Dashboard-only — visual editor for Twilio creds + From-number selection.