To integrate an SMS API, create an account and API key, choose a sender ID that is allowed in your destination countries, send a test message from your backend, and add a webhook that receives delivery reports. A first working send takes minutes; making it production-ready means adding opt-out handling, idempotent callbacks and a queue, which is what this guide walks through.
The examples use the SMS.to SMS API, but the same six steps apply to any HTTP messaging provider. You will need a server that can make HTTPS requests and a public URL for callbacks.
What should you decide before writing any code?
Start with one use case and be specific. The use case decides everything that follows: which sender you use, whether you need replies, what consent you must hold and which delivery states you care about.
| Use case | What matters most | Replies needed? |
|---|---|---|
| OTP and login codes | Speed, short content, abuse limits | No |
| Order, payment and delivery alerts | Delivery reports, clear sender | Rarely |
| Appointment reminders | Scheduling, confirm or reschedule replies | Often |
| Marketing and lifecycle | Consent, opt-out, quiet hours | Opt-out replies |
Then list your destination countries. Sender rules, registration and pricing are set country by country, and finding out after launch that a market needs a registered sender is the most common cause of a failed go-live.
Step 1: How do you create an account and API key?
Sign up, open the API section of the dashboard and generate a key. SMS.to gives free credits on sign-up with no credit card, and you can use a test key before switching to a live one. By default SMS.to generates long “secure” keys; a short format exists only for older third-party tools that cannot handle long keys, as its API key article explains. If you prefer short-lived tokens, the API also supports a client ID and secret exchanged at POST https://auth.sms.to/oauth/token.
Treat the key like a password:
- Keep it in a secrets manager or environment variable, never in source control.
- Call the API from your backend only, never from a browser or mobile app.
- Use separate keys per environment and service so you can revoke one without an outage.
- Rotate keys on a schedule and immediately after any suspected leak.
Step 2: Which sender ID should you use?
The sender ID is what the recipient sees as the “from”. Depending on the country and route you may use an alphanumeric name such as your brand, a long virtual number that can receive replies, a toll-free number or a short code. Many countries require alphanumeric senders to be registered before A2P traffic is accepted, and in the US application traffic to local numbers must be registered for 10DLC. If you plan to send SMS to the United States, start registration early.
From an engineering point of view, store the sender as configuration per country and per message type rather than hardcoding it. OTPs and support threads often need different senders, and rules change. If a sender does not meet local rules, delivery and throughput can be reduced or blocked, so confirm the setup for each market with your account manager before launch.
Step 3: How do you send your first message?
Send a single message with POST https://api.sms.to/sms/send, a Bearer token and a JSON body. Use a real test handset and a number in E.164 format, with the plus sign and country code.
curl -X POST 'https://api.sms.to/sms/send' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"message": "Your verification code is 482913. It expires in 5 minutes.",
"to": "+35799999999",
"sender_id": "YourBrand",
"callback_url": "https://example.com/webhooks/sms-status"
}'
A successful request is queued and returns an identifier, as documented in SMS.to’s bulk SMS and webhooks article:
{
"message": "Message is queued for sending! Please check report for update",
"success": true,
"message_id": "11ec-832f-a6f3fcfe-9fea-02420a0002ab"
}
Store the message_id against your own record straight away. “Queued” only means the platform accepted the request; delivery is reported later. The same endpoint accepts an array in to (up to 2,000 numbers), a list_id for saved contact lists, or a messages array for personalised text, and you can price any of these first by sending the same body to /sms/estimate.
Keep OTP and alert content short. A message over 160 GSM-7 characters, or 70 once it contains a Unicode character such as an emoji, is split into a concatenated SMS billed per part. Paste drafts into the SMS length calculator to see the encoding and part count, and read our guide to SMS pricing and character limits for the detail.
Step 4: How do you receive delivery reports?
Delivery reports tell you whether each message reached the handset. Pass a callback_url on each request, or set a Default Outbound Callback URL under Webhook Management in your account settings. According to SMS.to’s callback documentation, status updates arrive as a form-encoded POST with these fields:
| Field | What it holds |
|---|---|
| trackingId | The message_id or campaign_id returned when you sent |
| messageId | The individual message |
| phone | Recipient number |
| status | Delivery result, for example DELIVERED or FAILED |
| parts | Number of segments billed |
| price | Cost of the message |
Two rules shape your handler. Your endpoint must return HTTP 200 and finish in under 3 seconds. If it fails, SMS.to retries after 1 hour, then 2 hours, 4 hours and 24 hours, and then discards the callback. So:
- Validate the request and put the payload on a queue.
- Return 200 immediately; do the database work in a worker.
- Make processing idempotent: key updates on
messageIdand never move a message from a final state back to an earlier one. - Verify the signature. SMS.to signs webhooks with an
X-SMSto-Signatureheader and generates a separate secret for every endpoint, retrieved from the API Clients page, as described in its secure webhooks article. Reject anything that fails.
Log parts and price from every callback. A copy change that adds an emoji can double your segments overnight, and the callback is where you will see it first. If a callback never arrives, you can still look a message up with GET https://api.sms.to/message/{id}.
Step 5: How do you connect SMS to your business workflows?
Now wire sends to real events: a login triggers an OTP, a paid order triggers a confirmation, a booking triggers a reminder. Put a queue between the event and the API call. Bursts such as password-reset storms or a campaign going out then flow at a controlled rate, and you can retry network errors with exponential backoff, a retry counter and a cut-off instead of hammering the API.
Build consent into your data model from day one. Store opt-in status, timestamp and source per number, and check it before every marketing send. The CTIA Messaging Principles and Best Practices say standard “STOP” wording should be used for opt-out instructions, and that normal-language requests such as “end”, “cancel” or “unsubscribe” should also be honoured. On SMS.to, adding STOPSMS {optout} to a message body inserts a one-click opt-out link, and opted-out numbers are skipped unless you explicitly set bypass_optout, which should be reserved for genuinely transactional messages. Our SMS marketing compliance guide covers the rest.
If you send OTPs, add abuse limits per user, IP and device, and consider an HLR check on new numbers before sending.
Step 6: What should you check before going live?
- Keys: live key in a secrets manager, test key removed, no client-side calls.
- Senders: sender ID registered or approved in every launch country.
- Numbers: all numbers normalised to E.164 at the edge; unparseable input rejected.
- Webhooks: signature verified, 200 returned in under 3 seconds, duplicates handled.
- Content: every template checked for encoding and part count.
- Consent: opt-outs block sends, including from test and staging systems.
- Monitoring: alerts for spikes in send errors, failed statuses by country, webhook failures and parts per message.
- Balance: a low-balance alert using
GET https://auth.sms.to/api/balanceso a top-up never becomes an outage.
Roll out country by country and watch delivery rates for the first few days. Our HLR and MNP checks guide explains how to cut failed sends caused by dead or ported numbers.
What goes wrong most often?
- Local-format numbers. “07…” or “00…” in your database leads to misrouted or rejected messages. Normalise on input.
- Slow webhook handlers. Doing heavy work before returning 200 causes timeouts, retries hours later and duplicate events.
- Unexpected multipart messages. One emoji or other non-GSM character switches the whole message to UCS-2 and cuts each part to 70 characters.
- Unregistered senders. A sender that works in one country is filtered or replaced in another.
- Opt-outs ignored in secondary systems. A CRM or script that bypasses your consent check is a compliance incident waiting to happen.
How SMS.to handles SMS API integration
The SMS.to API for developers uses one send endpoint for single, bulk, list, personalised and scheduled messages, with cost estimates on the same body, signed delivery webhooks and two-way SMS with inbound webhooks. Messages route over Intergo Telecom’s licensed operator connections, and SDKs and code samples cover cURL, PHP, Node.js, Ruby, Python, Java and Go. If you would rather not code, ready-made integrations include Zapier, Salesforce, Magento, PrestaShop and OpenCart.
When volume grows you can move to SMPP on the same account, add Viber or WhatsApp fallback, or use the Verify API for OTPs with multi-channel fallback. Full reference documentation is at developers.sms.to.
FAQs
How long does it take to integrate an SMS API?
A first test send takes minutes once you have a key. A production integration with webhooks, opt-out handling, a queue and monitoring typically takes a few days of engineering, plus any sender registration time in your target countries.
Do I need a developer to integrate an SMS API?
For a custom integration, yes. If you only need notifications from a store or CRM, a ready-made integration such as Zapier, Salesforce or an ecommerce plugin can be set up without code.
How much does an SMS API cost?
Most providers charge per message part, with prices set by destination country. SMS.to is pay as you go from $0.023 per SMS, varying by country, with no setup fees and volume discounts on request.
Can I build my own SMS API instead?
Only if you want to become a messaging operator. You would need operator connections, routing, delivery-report handling and compliance in every country. For almost every business, using an existing provider is faster and cheaper.
Why does my message show as sent but not delivered?
“Sent” means the network accepted it. The final status comes in the delivery report. Common reasons for failure are an invalid or inactive number, a handset that is off for too long, or a sender that is not allowed in that country.
Ready to try it? Create a free account, no credit card needed, generate a key and send your first message with the cURL example above.