1import{j as e}from"./vendor-motion-CfBPC-kS.js";import{L as n}from"./vendor-react-BR_v4Ont.js";import{C as i}from"./ContentPage-BxMYAaUt.js";import"./index-VVKdn61F.js";import"./vendor-supabase-BSd6ADfF.js";import"./HireCTA-DktS03tb.js";import"./EmailGateModal-BCI8ZqlV.js";import"./dialog-my3VBzDi.js";const t=e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:"What actually changes"}),e.jsxs("p",{children:["Twilio and Telnyx do the same job â programmable SMS and voice over an HTTP API â but they're not drop-in compatible. Migrating an n8n automation from Twilio to Telnyx is three distinct pieces of work: ",e.jsx("strong",{children:"porting the numbers"}),", ",e.jsx("strong",{children:"remapping the send API"}),", and ",e.jsx("strong",{children:"rewiring inbound webhooks"})," (including a different signature scheme). Do them in that order and the cutover is boring, which is what you want when live messaging is on the line."]}),e.jsx("p",{children:"I moved a production telephony pipeline off Twilio on CloserIntelligence for exactly this reason â the per-message and per-number economics at volume. The API surface is similar enough that most of the migration is mechanical; the parts that bite are the signature verification and 10DLC, covered below."}),e.jsx("h2",{children:"Prerequisites"}),e.jsxs("ul",{children:[e.jsx("li",{children:"A Telnyx account with a Messaging Profile created"}),e.jsx("li",{children:"Your existing Twilio numbers and the n8n workflows that use them"}),e.jsx("li",{children:"API v2 key from Telnyx (Portal â Auth â API Keys)"}),e.jsx("li",{children:"n8n reachable on a public URL for inbound webhooks"})]}),e.jsx("h2",{children:"Step 1: Port the numbers (or run parallel first)"}),e.jsxs("ul",{children:[e.jsx("li",{children:"In Telnyx, start a port request with your numbers and a recent Twilio bill/CSR as proof of ownership"}),e.jsxs("li",{children:["Porting takes days, not minutes â ",e.jsx("strong",{children:"don't release the Twilio numbers"})," until the port completes"]}),e.jsx("li",{children:"Safer path: buy one Telnyx test number first, migrate the workflow logic against it, and only port production numbers once the pipeline is proven"})]}),e.jsx("h2",{children:"Step 2: Remap the send API"}),e.jsxs("p",{children:["Twilio's send is a form-encoded POST to ",e.jsx("code",{children:"/Messages.json"})," with ",e.jsx("code",{children:"From"}),"/",e.jsx("code",{children:"To"}),"/",e.jsx("code",{children:"Body"}),". Telnyx is a JSON POST to ",e.jsx("code",{children:"/v2/messages"})," with ",e.jsx("code",{children:"from"}),"/",e.jsx("code",{children:"to"}),"/",e.jsx("code",{children:"text"})," and a ",e.jsx("code",{children:"messaging_profile_id"}),". In n8n, swap the Twilio node (or HTTP Request) for an HTTP Request node configured like this:"]}),e.jsx("pre",{style:{background:"var(--tm-code-bg)",color:"var(--tm-code-text)",padding:16,borderRadius:4,marginTop:8,fontSize:13,overflowX:"auto"},children:`POST https://api.telnyx.com/v2/messages 2Headers: 3 Authorization: Bearer KEY0123... // Telnyx API v2 key 4 Content-Type: application/json 5Body: 6 { 7 "from": "+1XXXXXXXXXX", 8 "to": "+1YYYYYYYYYY", 9 "text": "Your message", 10 "messaging_profile_id": "abc-123" 11 }`}),e.jsxs("p",{children:["Store the API key in an n8n Header Auth credential, not inline. The response shape differs too: Telnyx returns the message under ",e.jsx("code",{children:"data.id"})," with a ",e.jsx("code",{children:"data.to[].status"}),", where Twilio returned a flat ",e.jsx("code",{children:"sid"})," and ",e.jsx("code",{children:"status"}),". Anything downstream that read ",e.jsx("code",{children:"sid"})," needs updating."]}),e.jsx("h2",{children:"Step 3: Rewire inbound webhooks and delivery receipts"}),e.jsxs("p",{children:["Point your Telnyx Messaging Profile's inbound and delivery webhook URLs at your n8n Webhook node's Production URL. Telnyx sends inbound messages and delivery status as JSON events (",e.jsx("code",{children:'event_type: "message.received"'})," / ",e.jsx("code",{children:'"message.finalized"'}),"), nested under ",e.jsx("code",{children:"data.payload"}
11)," â a different shape from Twilio's form-encoded inbound POST. Normalize the payload in a Code node right after the webhook so the rest of the workflow doesn't care which provider sent it. Same normalization discipline as the ",e.jsx(n,{to:"/guide/connect-ghl-to-n8n-webhook",style:{color:"var(--tm-accent)"},children:"GHL webhook pipeline"}),"."]}),e.jsx("h2",{children:"Step 4: Verify webhook signatures"}),e.jsxs("p",{children:["This is the piece people skip and regret. Twilio signs with an ",e.jsx("code",{children:"X-Twilio-Signature"})," HMAC over the URL + params. Telnyx signs differently: an ",e.jsx("strong",{children:"Ed25519 signature"})," in ",e.jsx("code",{children:"Telnyx-Signature-Ed25519"})," with a ",e.jsx("code",{children:"Telnyx-Signature-Ed25519-Timestamp"}),", verified against your account's public key. You can't port the Twilio verification code â you rewrite it. Verify the signature before trusting any inbound event, or anyone who finds your webhook URL can inject fake messages."]}),e.jsx("h2",{children:"Step 5: Cutover checklist"}),e.jsxs("ul",{children:[e.jsx("li",{children:"Telnyx test number sends and receives through the rewired workflow â"}),e.jsx("li",{children:"Delivery receipts land and update your records â"}),e.jsx("li",{children:"Signature verification rejects a tampered payload â"}),e.jsx("li",{children:"10DLC brand + campaign registered and approved (US traffic) â"}),e.jsx("li",{children:"Port production numbers, flip the send node, monitor the first hour closely â"}),e.jsx("li",{children:"Keep the Twilio credential in place for one billing cycle as a rollback path â"})]}),e.jsx("h2",{children:"Common gotchas"}),e.jsxs("p",{children:[e.jsx("strong",{children:"1. 10DLC registration."})," US A2P traffic on Telnyx needs its own brand and campaign registration â your Twilio 10DLC approval does ",e.jsx("em",{children:"not"})," transfer. Start this early; approval can lag the number port."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"2. Delivery receipts are a separate event."})," Telnyx sends the send-response and the final delivery status as two different webhook events. If you treated Twilio's synchronous status as final, you'll now under-report failures until you wire the ",e.jsx("code",{children:"message.finalized"})," event."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"3. Media (MMS) URLs."})," Telnyx expects media as a ",e.jsx("code",{children:"media_urls"})," array of publicly reachable URLs, and inbound media comes back as time-limited links â download and re-host anything you need to keep, don't store the Telnyx URL."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"4. Number format."})," Telnyx is strict about E.164 (",e.jsx("code",{children:"+1XXXXXXXXXX"}),"). Twilio was more forgiving. Normalize numbers before sending or you'll get 422s."]}),e.jsxs("p",{style:{marginTop:32},children:["Running this at volume? The ",e.jsx(n,{to:"/lab/n8n-production-reliability",style:{color:"var(--tm-accent)"},children:"n8n production reliability checklist"})," covers retries, dedupe, and error workflows for a messaging pipeline."]}),e.jsx("p",{style:{marginTop:16},children:e.jsx(n,{to:"/workflows",style:{color:"var(--tm-accent)"},children:"Browse 4,900+ ready-to-import workflow templates â"})})]}),u=()=>e.jsx(i,{tier:2,slug:"twilio-to-telnyx-migration-n8n",title:"How to migrate from Twilio to Telnyx in n8n",subtitle:"Porting numbers, remapping the send API, and rewiring inbound webhooks â including the Ed25519 signature scheme and 10DLC re-registration that trip up most migrations.",lastUpdated:"2026-09-03",readTime:"7",techStack:["Telnyx","Twilio","n8n","HTTP Request","SMS"],leadMagnet:{label:"Skip the rewiring. Download the n8n workflow JSON â a Telnyx send node, an inbound webhook with payload normalization, delivery-receipt handling, and a signature-verification stub. Import it, drop in your API key and Messaging Profile ID.",downloadUrl:"/workflows/telnyx-n8n-sms-starter.json"},relatedPages:[{title:"How to connect GoHighLevel to n8n via webhook",slug:"connect-ghl-to-n8n-webhook",tier:2},{title:"n8n production reliability checklist",slug:"n8n-production-reliability",tier:3}],relatedServices:["Telnyx","HTTP Request"],howTo:[{name:"Port the numbers (or run parallel first)",text:"Start a Telnyx port request with proof of ownership, and don't release the Twilio numbers until it completes. Safer: prove the pipeline against one Telnyx test number before porting production numbers."},{name:"Remap the send API",text:"Replace Twilio's form-encoded POST to /Messages.json with a JSON POST to https://api.telnyx.com/v2/messages using from/to/text and messaging_profile_id, authenticated with a Telnyx API v2 key. Update anything downstream that read Twilio's sid."},{name:"Rewire inbound webhooks",text:"Point the Telnyx Messaging Profile's inbound and delivery webhooks at your n8n Webhook Production URL, and normalize Telnyx's data.payload JSON events in a Code node so the rest of the workflow is provider-agnostic."},{name:"Verify webhook signatures",text:"Telnyx signs with an Ed25519 signature in Telnyx-Signature-Ed25519 plus a timestamp, verified against your account public key â you can't reuse Twilio's HMAC verification. Verify before trusting any inbou
11nd event."},{name:"Run the cutover checklist",text:"Confirm send, receive, delivery receipts, and signature rejection on a test number; register 10DLC brand and campaign; then port production numbers, flip the send node, and keep Twilio as a rollback path for one billing cycle."}],faq:[{q:"Does my Twilio 10DLC registration transfer to Telnyx?",a:"No. US A2P traffic on Telnyx needs its own brand and campaign registration. Start it early â approval can lag the number port, and unregistered traffic gets filtered."},{q:"Can I reuse my Twilio webhook signature verification code on Telnyx?",a:"No. Twilio uses an X-Twilio-Signature HMAC over the URL and params; Telnyx uses an Ed25519 signature in Telnyx-Signature-Ed25519 with a timestamp header, verified against your account's public key. You rewrite the verification."},{q:"Why am I under-reporting delivery failures after migrating?",a:"Telnyx sends the send-response and the final delivery status as two separate webhook events. If you treated Twilio's synchronous status as final, wire the message.finalized event to capture real delivery outcomes."},{q:"Why do my Telnyx sends return 422 errors?",a:"Telnyx is strict about E.164 number format (+1XXXXXXXXXX) where Twilio was forgiving. Normalize numbers to E.164 before sending."}],body:t});export{u as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.