How to migrate from SMS.to to Sinch
A developer's guide to migrating messaging traffic from SMS.to to Sinch, covering channel and compliance differences, request-format changes, and a step-by-step cutover checklist.
SMS.to is an omnichannel business-messaging platform and API from Cyprus-based Intergo Telecom, covering SMS, Viber, WhatsApp, RCS and Telegram. Sinch is a publicly traded cloud-communications platform out of Stockholm that spans messaging, voice and email APIs. On the messaging.dev Score, SMS.to rates 49/100 and Sinch 92/100; this guide walks through what actually changes at the API level when you move between them.
What you gain and what you lose
Channels. Everything SMS.to sends, Sinch sends too: SMS, RCS, WhatsApp, Viber and Telegram all carry over, so you lose no channel by migrating. You additionally gain MMS, Facebook Messenger, Apple Messages for Business, Voice and Email, none of which SMS.to offers.
Compliance. Both providers are GDPR- and ISO 27001-aligned. Sinch adds SOC 2 and HIPAA; SMS.to carries neither.
Data residency. Identical on the core options: both run EU and US servers and let you choose where data is processed. Sinch additionally lists APAC, Australia and Brazil.
Pricing and credit. SMS.to is prepaid pay-as-you-go with no contracts (advertised from $0.023 per SMS). Sinch is also pay-as-you-go but adds volume and committed-use tiers (approximately $0.0075 per US SMS segment, plus carrier fees). Both offer free trial credit on sign-up.
Tooling. SMS.to ships a single PHP SDK, has no sandbox, and its docs are rated medium. Sinch ships Java, Python, C#, Node.js and PHP SDKs, provides a sandbox test environment, and its docs are rated high. Both expose REST and SMPP; Sinch adds SMTP for email.
How the request format differs
SMS.to quickstart:
curl -X POST https://api.sms.to/sms/send \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{"message": "Hello from SMS.to", "to": "+35794000001", "sender_id": "SMSto"}'
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"}'
Endpoint. SMS.to posts to one fixed URL, https://api.sms.to/sms/send. Sinch posts to a service-plan- and region-scoped URL, https://us.sms.api.sinch.com/xms/v1/{service_plan_id}/batches — you inject your service_plan_id into the path, and the host is region-pinned (us. here; use the EU host for EU processing).
Authentication. This barely changes. Both send the key as a Bearer token in the Authorization header — swap in a Sinch API token. SMS.to also accepts the key as an api_key query parameter on GET requests; Sinch is header-only.
Payload mapping. Three fields rename. The message text moves from message to body. The recipient moves from a single to string to a to array (["+1555..."]), so wrap existing numbers in a list. The sender moves from sender_id ("SMSto") to from ("+15005550006" in the example).
Migration checklist
- Create a Sinch account (self-onboarding) and generate an API token; note your
service_plan_id. - Map the request fields:
message→body,to(string) →to(array),sender_id→from. - Re-point your sending code to the batches endpoint and select the correct regional host.
- Re-test in Sinch’s sandbox before sending any live traffic.
- Update your delivery/webhook callbacks to Sinch’s callback format.
- Run both providers in parallel and reconcile delivery results.
- Cut over, then decommission the SMS.to integration.
Watch out for
On the dimensions compared here, Sinch does not regress: no channel, certification, residency option, sandbox, SDK or free-credit loss versus SMS.to. The gotchas are structural rather than feature losses.
- The endpoint is region-pinned. The quickstart host is
us.; if you need EU residency, you must send to the EU host — the URL, not a dashboard setting, determines routing. - The
service_plan_idlives in the path. A per-account value now replaces SMS.to’s single global endpoint, so the base URL is no longer static across environments. - The recipient is now an array. Passing a bare string where Sinch expects
["+1555..."]will fail. - The sender renames to
from. The example uses a numeric number rather than SMS.to’s alphanumericsender_id, so confirm sender-type support for your destinations.
For a fuller onboarding walkthrough, see how to start with Sinch, and for a side-by-side breakdown, see Sinch vs SMS.to.