Use cases · Replace Twilio
You built a phone company inside your product. Retire it.
Teams that built messaging on raw CPaaS own subaccount plumbing, opt-out bookkeeping, 10DLC orchestration, and webhook glue nobody wants to maintain. Handset is the application layer you were forced to write (multi-tenant, compliant, and billed on usage) with your send calls staying almost identical.
// Before: raw CPaaS + your own platform code client.messages.create({ from, to, body }) // …plus ~2,000 lines you maintain // After: the platform layer is the product await sendMessage({ body: { from, to, body } }); → threads, opt-outs, 10DLC, receipts: handled
The maintenance surface
The code you get to delete
None of this code is your product. All of it pages someone when it breaks. Here's where each piece goes.
Subaccount scaffolding
todaySubaccount-per-customer creation, credential storage, and the mapping tables that tie them to your users.
afterTenants are first-class API objects: numbers, threads, hours, and opt-out lists hang off them natively.
Opt-out bookkeeping
todayA stop-words table, a send-time check you hope every code path calls, and the audit trail for when it didn't.
afterSTOP/HELP keywords answer themselves; opt-outs are enforced at send time, per tenant, on our side of the API.
10DLC state machine
todayBrand and campaign registration flows, vetting-status polling, and the spreadsheet that tracks which customer is stuck where.
afterBrands and campaigns are objects with approval webhooks. Test mode approves instantly so onboarding is code.
Message threading
todayThe conversations table you hand-rolled: matching inbound numbers to customers, ordering, unread counts.
afterEvery message carries a conversation_id. The inbox view becomes a GET.
Voice glue
todayTwiML endpoints, ring-timeout handling, voicemail recording storage, and a transcription vendor.
afterHours-based routing, voicemail, and transcripts are configuration per tenant: voicemail.created arrives transcribed.
Concept mapping
Your mental model survives the migration
SubaccountTenant
First-class, with its own numbers, threads, hours, and opt-out list
Messaging ServiceTenant + number
No pooling abstraction to configure: sends come from the tenant's number
client.messages.createPOST /v1/messages
Same shape: from, to, body, plus threading and compliance underneath
Status callbacksSigned webhooks
HMAC-signed, retried until acknowledged, one catalog of event types
A2P registration consolePOST /v1/brands, /v1/campaigns
Registration is an API object with approval webhooks, per tenant
Port-in ticketsPOST /v1/port_ins
Porting is an API: submit, then status webhooks until numbers go live
The migration
Five steps, rehearsed before anything moves
The whole path runs in test mode first, including porting. Your production traffic switches when you've already watched it work.
Rehearse in test mode
Point your staging environment at test keys. Magic numbers simulate delivery, replies, opt-outs, and port-ins, and the whole migration runs green before a real number moves.
Map subaccounts to tenants
One import loop: create a tenant per subaccount, carry over your customer IDs as metadata.
Re-register campaigns by API
Brands and campaigns per tenant, with approval webhooks. Design partners get white-glove 10DLC re-registration, we've done the TCR dance so you don't.
Port your numbers
POST /v1/port_ins per batch, then watch status webhooks until they flip live. Your customers keep the numbers their customers know.
Point your triggers at one endpoint
Your existing send calls become POST /v1/messages, same shape, less code around it. Then start deleting the plumbing above.
And the "someday" features come with the switch. Voice routing, transcribed voicemail, click-to-call with live transcripts, DTMF gather, raw media streaming for voice agents, the roadmap items you kept deferring because they meant more CPaaS plumbing are already on the same API and the same numbers.
Migrating? Bring a founder.
Design partners get white-glove 10DLC re-registration, a rehearsed port plan, and a founder on the call until traffic is switched.