UC-001 — Send Single SMS
| Field | Value |
|---|---|
| ID | UC-001 |
| Goal | Send a single SMS and verify its delivery |
| Channel | SMS |
| Complexity | Basic |
| Estimated time | 10 minutes |
| APIs involved | POST /api/message-server/sms/send, GET /api/partner-gateway/v1/messages/status/{customerMessageId} |
Real-world scenarios
- E-commerce — Order confirmation: TechStore sends an SMS to the customer to confirm order receipt and provide a tracking code.
- Clinic — Appointment reminder: Studio Dentistico Bianchi reminds the patient about the next day's appointment.
- Marketing — Flash promo: FashionOutlet launches a flash promotion with a 24-hour deadline, sending a personalized SMS.
Prerequisites
Before you begin, make sure you have:
- Active API Key → How to get one
- Sufficient credit → Check in the Qlara Dashboard
:::tip Test without costs
Add "simulation": true in the request body to validate the flow without actually sending messages and without consuming credit.
:::
Message flow
The diagram illustrates the complete cycle: your server sends the request, the gateway routes the message to the carrier, and the delivery status comes back to you via polling or webhook.
Step 1 — Send the SMS
Call the send endpoint with the recipient, sender, and message text.
curl -X POST https://lora-api.agiletelecom.com/api/message-server/sms/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393471234567",
"sender": "TechStore",
"body": "Ciao Marco, il tuo ordine #ORD-20260409 e stato confermato! Consegna prevista: 11 aprile. Tracking: https://techstore.it/t/TRK789",
"campaignId": "conferma-ordini-2026-04",
"enableNotification": true
}'
Response — Message accepted
{
"messageId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"simulation": false,
"results": {
"sms": {
"accepted": true,
"unicode": false,
"parts": 1,
"reasons": []
}
}
}
:::tip Save the messageId
The messageId field is the unique identifier you will use to check delivery status. Save it in your database associated with the order.
:::
Behind the scenes — What happens after sending
- Validation: The gateway verifies the API Key, recipient format, and message length.
- Routing: The Message Router identifies the recipient's carrier (+3934x = Vodafone IT) and selects the route with the best quality/cost ratio.
- Encoding: The text is analyzed to determine whether to use GSM-7 (160 char/SMS) or UCS-2 Unicode (70 char/SMS). Characters like
e(without accent) fall within GSM-7. - Concatenation: If the message exceeds the threshold, it is split into multiple parts (multipart SMS) with automatic UDH header.
- Delivery: The message travels through the carrier's SMSC network to the device.
- DLR (Delivery Report): The carrier returns the delivery report which the gateway translates into the status
DELIVERED(3) orERROR(6).
Step 2 — Check delivery status (Polling)
After a few seconds, query the delivery status using the received messageId.
curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/messages/status/f47ac10b-58cc-4372-a567-0e02b2c3d479?channel=SMS" \
-H "X-Api-Key: YOUR_API_KEY"
Response — Delivered
{
"customerMessageId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"channel": "SMS",
"destination": "+393471234567",
"deliveryStatus": "DELIVERED",
"deliveryStatusDescription": "Message delivered to handset",
"sendDate": "2026-04-09T10:15:00+02:00",
"deliveryDate": "2026-04-09T10:15:03+02:00",
"readDate": null
}
Behind the scenes — Status codes table
| Status | Code | Description |
|---|---|---|
DELIVERED | 3 | Message delivered to the device |
SENT | — | Message sent, waiting for confirmation |
ERROR | 6 | Delivery error (wrong number, unreachable network) |
EXPIRED | 8 | Message expired before delivery (TTL exceeded) |
UNKNOWN | — | Status not yet available |
Polling is useful for spot checks. For real-time monitoring on high volumes, use Webhooks.
Step 3 — Receive the delivery webhook
If you have configured a webhook endpoint (see the Webhook guide), you will receive an automatic HTTP POST notification:
{
"channel": "SMS",
"eventType": "DELIVERY",
"messageId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"statusCode": 3,
"statusDescription": "Delivered",
"price": 0.035,
"numPart": 1,
"totalParts": 1,
"timestamp": "2026-04-09T10:15:03Z"
}
:::info Webhook vs Polling The webhook is the recommended method for production: you receive the notification in real time without making repeated calls. Configure your endpoint in the Webhook section of the platform. :::
Common errors
401 Unauthorized — Missing or invalid API Key
{
"status": "fail",
"data": {
"authentication": "Invalid or missing API key"
}
}
Solution: Verify that the X-Api-Key header is present and that the key is active in the platform dashboard.
accepted: false — Message rejected
{
"messageId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"simulation": false,
"results": {
"sms": {
"accepted": false,
"unicode": false,
"parts": 0,
"reasons": ["Invalid destination number format"]
}
}
}
Solution: The number must be in full international format (e.g. +393471234567). Verify that you have not omitted the +39 prefix.
Simulation mode active
{
"messageId": "a2c4e6f8-1234-5678-9abc-def012345678",
"simulation": true,
"results": {
"sms": {
"accepted": true,
"unicode": false,
"parts": 1,
"reasons": []
}
}
}
Solution: The simulation: true field in the response indicates that the message was not actually sent. Remove "simulation": true from the request body for actual delivery.
Expected result
| Step | Action | Result |
|---|---|---|
| 1 | POST /sms/send | messageId returned, accepted: true |
| 2 | GET /messages/status/{id} | deliveryStatus: "DELIVERED" |
| 3 | Webhook received | statusCode: 3, eventType: "DELIVERY" |
Complete end-to-end example
Here is the complete TechStore scenario, from sending to verification:
# 1. Send the order confirmation SMS
MESSAGE_ID=$(curl -s -X POST https://lora-api.agiletelecom.com/api/message-server/sms/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393471234567",
"sender": "TechStore",
"body": "Ciao Marco, ordine #ORD-20260409 confermato! Tracking: https://techstore.it/t/TRK789",
"enableNotification": true
}' | jq -r '.messageId')
echo "Message ID: $MESSAGE_ID"
# 2. Wait a few seconds and verify delivery
sleep 5
curl -s -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/messages/status/${MESSAGE_ID}?channel=SMS" \
-H "X-Api-Key: YOUR_API_KEY" | jq .
Variants
Send with placeholders
Use placeholders to personalize the text without building strings on the server side:
curl -X POST https://lora-api.agiletelecom.com/api/message-server/sms/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393481234567",
"sender": "TechStore",
"body": "Ciao {nome}, il tuo ordine {ordine} e pronto per il ritiro presso {negozio}.",
"placeholders": {
"nome": "Giulia",
"ordine": "#ORD-20260410",
"negozio": "TechStore Milano Centrale"
},
"enableNotification": true
}'
Scheduled send
Schedule sending for a future date and time:
curl -X POST https://lora-api.agiletelecom.com/api/message-server/sms/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393471234567",
"sender": "StBianchi",
"body": "Gentile Marco, le ricordiamo l appuntamento di domani 10 aprile alle ore 15:30. Studio Dentistico Bianchi - Tel. 02 1234567",
"scheduledDate": "2026-04-10 08:00:00.000+0200"
}'
:::note scheduledDate format
The required format is yyyy-MM-dd HH:mm:ss.SSSZ, for example 2026-04-10 08:00:00.000+0200 for 8:00 AM CEST.
:::
Next steps
- UC-002 — Send RCS Rich Card: Send rich messages with images and interactive buttons
- UC-003 — Send WhatsApp Template: Use Meta-approved templates for WhatsApp messages
- UC-004 — Check Delivery Status: Deep dive into batch polling and webhook comparison
- SMS Universal Guide: Complete SMS channel documentation
- Authentication Guide: Details on API Key and Basic Auth