Send your first SMS with the API
This guide shows how to send an SMS with the demo API, read the segments and encoding, then follow the statuses. The SMS is simulated until a provider is configured.
Updated on
Before you start
- A fictional test key: tq_test_EXEMPLE.
- A sender number and a recipient in E.164 format without spaces. Here: +33199001234 and +33199005678, a fictional range.
- A clear idea of the message nature: transactional (tied to an action by the person) or marketing (commercial communication).
Send the message
- Write the text. A long SMS is split into several segments, and each segment is billable according to your contract.
- Choose the nature: transactional or marketing. A marketing message falls under rules that differ by country, notably on consent and opt-out lists.
- Send POST /messages with an Idempotency-Key. Add scheduled_at and timezone to schedule the message.
curl -X POST https://api.example.test/v1/messages \
-H "Authorization: Bearer tq_test_EXEMPLE" \
-H "Idempotency-Key: 8d4e6b10-2c9a-47f3-b5e1-0a7c3d9f2e64" \
-H "Content-Type: application/json" \
-d '{"from":"+33199001234","to":"+33199005678","text":"Your test code is 4821.","nature":"transactional"}'Read the response
The response shows the queued status: the message was accepted, not yet delivered. The segments and encoding fields show how the text was split. The encoding is GSM-7 or UCS-2.
A single character outside the GSM-7 alphabet can switch the whole message to UCS-2, which shrinks each segment and may increase their number. Check the segments field before sending at scale.
{
"id": "msg_EXEMPLE_001",
"status": "queued",
"segments": 1,
"encoding": "GSM-7",
"simulated": true
}Schedule a message
Add scheduled_at (date and time) and timezone to the request body. Always state the time zone: the same hour does not mean the same moment in Paris and in Mexico City.
{
"from": "+33199001234",
"to": "+33199005678",
"text": "Reminder: your appointment is tomorrow.",
"nature": "transactional",
"scheduled_at": "2026-11-09T09:00:00",
"timezone": "Europe/Paris"
}Understand the statuses
You receive these statuses through the message.sent, message.delivered and message.undelivered events, via a signed webhook.
| Status | Meaning |
|---|---|
| queued | Accepted by the platform, not yet handed over. |
| sent | Handed over to the network. This is not a delivery. |
| delivered | Delivered to the recipient’s device. It does not mean read. |
| undelivered | Not delivered. The cause is not always available. |
| unknown | Final status not known. It may never change: treat it neither as a failure nor as a success. |
Common errors
| Symptom | Likely cause | What to do |
|---|---|---|
| 400 invalid_request | Malformed number, missing nature or a value other than transactional and marketing, empty text. | Fix the field named in the error message. |
| 409 idempotency_conflict | Same Idempotency-Key with a different text. | Use a new key for a new message. |
| 429 rate_limited | Sending rate too high. | Respect Retry-After, then retry. |
| More segments than expected | A special character moved the message to UCS-2. | Read encoding and segments, then simplify the text if needed. |
What this guide does not do
- It sends no real SMS until a provider is configured.
- It promises no delivery: a delivered status is not guaranteed, and delivered does not mean the message was read.
- It does not cover receiving SMS. Inbound replies require a compatible number and country.
- It does not replace checking your obligations (consent, opt-out lists, sender identity), which are determined by the service, the country and your actual role.
Frequently asked questions
Why does my SMS count as several segments?
Because the text exceeds the size of one segment, or because a special character forced UCS-2 encoding. The segments field in the response gives you the exact number before any real sending.
Can I send to any country?
No. SMS capabilities depend on the country, the chosen provider and the contract. Check the country catalog and request a quote for your scope.