Migration guide

How to migrate from Telnyx to Sinch

A developer-focused guide to moving messaging traffic from Telnyx to Sinch: channel and compliance differences, request-format mapping, and a step-by-step migration checklist.

Telnyx is a licensed telecom carrier offering a CPaaS platform with APIs for SMS, MMS, RCS, WhatsApp, voice, and email over its own private global IP network. Sinch is a cloud communications platform covering those same core channels plus several chat apps. On the messaging.dev Score, Telnyx rates 78/100 and Sinch 92/100 — this guide covers what that gap means in practice and how to re-point your sending code.

What you gain and what you lose

Every channel you use on Telnyx exists on Sinch: SMS, MMS, RCS, WhatsApp, voice, and email all carry over, so you lose no channels in the move. You gain four: Viber, Facebook Messenger, Telegram, and Apple Messages for Business.

Compliance is identical on both sides — GDPR, ISO 27001, SOC 2, and HIPAA — as is data residency: both run US and EU servers with a region choice. Two developer-experience gaps favor Sinch: it offers a sandbox test environment (Telnyx has none) and free trial credit for new accounts (Telnyx has none).

The trade-offs are narrower. SDK coverage overlaps on Node.js, Python, Java, and PHP; Sinch lists C# where Telnyx lists .NET, but drops the Ruby and Go SDKs Telnyx ships, so Ruby or Go integrations fall back to raw HTTP. Both document at a “high” quality level. Pricing stays pay-as-you-go, but list SMS pricing is higher on Sinch (~$0.0075 per US segment) than Telnyx ($0.004 per US message part); Sinch adds committed-use pricing and covers 150 countries to Telnyx’s 130. Sinch also exposes SMTP alongside the REST and SMPP interfaces both share.

How the request format differs

Telnyx quickstart:

curl -X POST https://api.telnyx.com/v2/messages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "from": "+15551234567",
    "to": "+15559876543",
    "text": "Hello, world!"
  }'

Sinch quickstart:

curl -X POST 'https://us.sms.api.sinch.com/xms/v1/YOUR_SERVICE_PLAN_ID/batches' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"from":"+15005550006","to":["+15551234567"],"body":"Hello from Sinch"}'

Three things change:

  • Endpoint. Telnyx posts to a flat https://api.telnyx.com/v2/messages. Sinch posts to a region-prefixed, service-plan-scoped batches URL: https://us.sms.api.sinch.com/xms/v1/{service_plan_id}/batches. Your service_plan_id lives in the path, not a header.
  • Auth. Both use a Bearer token in the Authorization header. On Telnyx it’s an API key; on Sinch it’s an API token paired with the service plan ID baked into the URL.
  • Payload. from (the sender) keeps its name and stays a string. The recipient field is still to, but Sinch expects an array of numbers (["+1555..."]) rather than Telnyx’s single string. The message body renames from text to body.

Migration checklist

  1. Create a Sinch account, then copy your API token and service_plan_id from the dashboard.
  2. Map the request fields: textbody, wrap to in an array, keep from as a string.
  3. Swap the base URL to your region’s ...sms.api.sinch.com/xms/v1/{service_plan_id}/batches and update the auth token.
  4. Re-point your sending code, or switch to a Sinch SDK (Node.js, Python, Java, C#, or PHP).
  5. Re-test in the Sinch sandbox before sending any live traffic.
  6. Update your delivery/status webhook handlers to parse Sinch’s callback format.
  7. Run Telnyx and Sinch in parallel, compare delivery, then cut over.

For a from-scratch walkthrough, see how to start with Sinch; for a full spec-by-spec view, see Sinch vs Telnyx.

Watch out for

  • Higher list SMS price: ~$0.0075 per US segment versus Telnyx’s $0.004 per message part — model your volume before cutover.
  • Lower uptime SLA: Sinch publishes 99.95% against Telnyx’s 99.99%.
  • No Ruby or Go SDK: those two integrations must call the REST API directly.
  • Recipient is an array: a to sent as a bare string will be rejected — the most common porting bug.