Skip to main content

UC-001 — Send Single SMS

FieldValue
IDUC-001
GoalSend a single SMS and verify its delivery
ChannelSMS
ComplexityBasic
Estimated time10 minutes
APIs involvedPOST /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:

:::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
  1. Validation: The gateway verifies the API Key, recipient format, and message length.
  2. Routing: The Message Router identifies the recipient's carrier (+3934x = Vodafone IT) and selects the route with the best quality/cost ratio.
  3. 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.
  4. Concatenation: If the message exceeds the threshold, it is split into multiple parts (multipart SMS) with automatic UDH header.
  5. Delivery: The message travels through the carrier's SMSC network to the device.
  6. DLR (Delivery Report): The carrier returns the delivery report which the gateway translates into the status DELIVERED (3) or ERROR (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
StatusCodeDescription
DELIVERED3Message delivered to the device
SENTMessage sent, waiting for confirmation
ERROR6Delivery error (wrong number, unreachable network)
EXPIRED8Message expired before delivery (TTL exceeded)
UNKNOWNStatus 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

StepActionResult
1POST /sms/sendmessageId returned, accepted: true
2GET /messages/status/{id}deliveryStatus: "DELIVERED"
3Webhook receivedstatusCode: 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