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:

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://api.qlara.ai/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": []
}
}
}
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 a final status: DELIVERED (3) if the SMS reached the handset, otherwise REJECTED (2), EXPIRED (4), DELETED (5) or UNDELIVERABLE (6). Until the report arrives, the message stays ACCEPTED (1).

Step 2 — Check delivery status (Polling)​

After a few seconds, query the delivery status using the received messageId.

curl -X GET "https://api.qlara.ai/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": "delivered",
"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
ACCEPTED1Handed to the carrier, waiting for the delivery report. Not final
REJECTED2The carrier refused the message. Final
DELIVERED3Message delivered to the device. Final
EXPIRED4Not delivered within its validity window. Final
DELETED5Cancelled before delivery. Final
UNDELIVERABLE6The destination cannot receive it (unreachable or invalid number). Final
UNKNOWN0No status held for the message

The code is the numeric statusCode sent by the delivery webhook; the polling API returns the name in deliveryStatus and the lowercase description (delivered, undeliverable…) in deliveryStatusDescription.

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:

{
"eventType": "DELIVERY",
"channel": "SMS",
"messageId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"destination": "+393471234567",
"statusCode": 3,
"description": "delivered",
"eventDate": "2026-04-09T10:15:03+02:00",
"price": 0.035,
"totalParts": 1,
"numPart": 1
}

messageId is the identifier you received at send time. For a multipart SMS you receive one event per part (numPart from 1 to totalParts).

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}?channel=SMSdeliveryStatus: "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://api.qlara.ai/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://api.qlara.ai/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://api.qlara.ai/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://api.qlara.ai/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"
}'
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​