Quickstart: Send an SMS and get a delivery report

|

View as Markdown

In this guide, you send a single SMS and receive its delivery report.

Before you start, you need the following:

  • An Infobip account, the Base URL of your account, and credentials for one of the authentication methods. Most integrations use an API key. See API authentication.
  • A sender. During the free trial, use the shared test sender InfoSMS.
  • On a self-signup account on the free trial, a verified recipient to send your test message to.


Send an SMS

Use the Send SMS endpoint to send your first message. Replace {baseUrl} with the Base URL of your account and {your-phone-number} with the number you send to. Replace {authorization} with the scheme and credentials of your authentication method, for example App {your-api-key} for an API key or Bearer {access_token} for OAuth 2.0.

Send an SMS
1curl -X POST 'https://{baseUrl}/sms/3/messages' \
2 -H 'Authorization: {authorization}' \
3 -H 'Content-Type: application/json' \
4 -H 'Accept: application/json' \
5 -d '{
6 "messages": [
7 {
8 "sender": "InfoSMS",
9 "destinations": [
10 { "to": "{your-phone-number}" }
11 ],
12 "content": {
13 "text": "This is a sample message"
14 }
15 }
16 ]
17 }'

The request contains the following fields:

  • sender: The sender ID, the name or number that appears on the device of the recipient. InfoSMS is a shared test sender available during the free trial. Production sending requires your own sender. You can buy a number or request an alphanumeric sender, and register it where the country requires registration. See Numbers and senders to compare sender types.
  • destinations.to: The phone number of the recipient in international E.164 format, with no leading + or 00, for example 41793026727. See Phone numbers.
  • content.text: The message body. Message length depends on character encoding. A single message can hold 160 GSM-7 or 70 Unicode characters. Longer messages are split into parts of 153 or 67 characters. For how encoding and segmentation affect length and cost, see Send messages in multiple languages.

The API returns the following response:

Response
1{
2 "bulkId": "2034072219640523072",
3 "messages": [
4 {
5 "messageId": "2250be2d4219-3af1-78856-aabe-1362af1edfd2",
6 "status": {
7 "groupId": 1,
8 "groupName": "PENDING",
9 "id": 26,
10 "name": "PENDING_ACCEPTED",
11 "description": "Message sent to next instance"
12 },
13 "destination": "{your-phone-number}",
14 "details": {
15 "messageCount": 1
16 }
17 }
18 ]
19}

The response contains the following fields:

  • bulkId: Identifies this request. Use it to fetch delivery reports and logs for the whole request, and to manage messages scheduled under it.
  • messages[].messageId: The unique ID for this specific message. Use it to correlate the delivery report, look up status in the logs, or troubleshoot.
  • messages[].status: The status of the message. PENDING_ACCEPTED means the platform accepted the message and queued it for sending. It does not confirm delivery to the handset. See Message status codes for the full list of status codes and what they mean.
  • messages[].destination: The phone number the message was sent to.
  • messages[].details.messageCount: The number of SMS parts the message was split into.

The response confirms the platform accepted your request. It is not a delivery confirmation. To find out whether the message reached the recipient, query the message logs using messageId, or configure a webhook to receive delivery reports automatically. Message logs cover the last 48 hours.

If the request returns HTTP 401, check your credentials and the Authorization scheme. See Authentication errors.



Receive a delivery report

To close the loop, receive a delivery report (DLR). Infobip sends a POST to a webhook URL you host when each message reaches a final state.

Set the webhook URL on the send request, in webhooks.delivery.url. Add the webhooks object to the message, next to content:

Webhook settings
1"webhooks": {
2 "delivery": {
3 "url": "https://www.example.com/dlr"
4 }
5}

The URL must be publicly reachable and respond with HTTP 200. Infobip then posts the DLR to that URL when the message reaches its final state. The following example shows the fields used in this guide:

Delivery report
1{
2 "results": [
3 {
4 "bulkId": "2034072219640523072",
5 "messageId": "2250be2d4219-3af1-78856-aabe-1362af1edfd2",
6 "to": "{your-phone-number}",
7 "sender": "InfoSMS",
8 "sentAt": "2026-06-22T16:00:00.000+0100",
9 "doneAt": "2026-06-22T16:00:00.000+0100",
10 "messageCount": 1,
11 "status": {
12 "groupId": 3,
13 "groupName": "DELIVERED",
14 "id": 5,
15 "name": "DELIVERED_TO_HANDSET",
16 "description": "Message delivered to handset"
17 },
18 "error": {
19 "groupId": 0,
20 "groupName": "OK",
21 "id": 0,
22 "name": "NO_ERROR",
23 "description": "No Error",
24 "permanent": false
25 }
26 }
27 ]
28}

The delivery report contains the following fields:

  • messageId: Matches the messageId from your send response, so you can correlate the report with the message you sent.
  • status: The final delivery status. DELIVERED_TO_HANDSET (id 5) confirms the message reached the device. Check the specific id and name, not only groupName. DELIVERED_TO_OPERATOR is also in the DELIVERED group but confirms only that the operator received the message, not the handset. See Message delivery lifecycle.
  • error: NO_ERROR on success. On failure, this carries the reason and a permanent flag that tells you whether a retry can succeed.

To also receive real-time intermediate reports, not only the final status, set webhooks.delivery.intermediateReport to true. For endpoint setup, retries, security, and the full event catalog, see Webhooks.



Related pages

Handling errors
Decide whether to retry and how to read error codes.

SDKs
Use a typed client library instead of raw HTTP.

Go live checklist
Move from the free trial to production traffic.




Was this page helpful?