> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ugatext.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send SMS messages

> Send single, bulk, and scheduled SMS with UgaText, format phone numbers, and understand segments and encoding.

All requests go to `https://ugatext.com/api/v1` and need your [API credentials](https://docs.ugatext.com/authentication.md).

## Send a single SMS

`POST /sms/send` sends one message.

```bash theme={null}
curl -X POST https://ugatext.com/api/v1/sms/send \
  -H "Client-ID: YOUR_CLIENT_ID" \
  -H "Client-Secret: YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f14e45f-ceea-467f-a8f1-4e45fceea67f" \
  -d '{
    "to": "+256750625684",
    "message": "Your verification code is 482910.",
    "sender_id": "UGATEXT"
  }'
```

| Field | Required | Description |
| - | - | - |
| `to` | Yes | Recipient phone number. Aliases: `phone`, `recipient`. |
| `message` | Yes | Message text. Aliases: `text`, `body`. |
| `sender_id` | Yes | Approved [Sender ID](https://docs.ugatext.com/sender-ids.md), 1 to 11 characters. Aliases: `senderId`, `from`. |

The response contains a `message_id` (format `msg_<13-digit-unix-ms>_<8-hex-chars>`) and the initial status `queued`. Add an `Idempotency-Key` header to retry safely. See [Idempotency](https://docs.ugatext.com/errors.md#idempotency).

> [!WARNING]
>
> `sender_id` is required. A missing, blank, or unapproved value returns `403 SENDER_ID_NOT_APPROVED`.

## Phone number formats

UgaText delivers to Uganda (+256), Kenya (+254), and DR Congo (+243). Each of these formats is accepted:

| Format | Example |
| - | - |
| E.164 with `+` | `+256750625684`, `+254712345678`, `+243810000000` |
| E.164 without `+` | `256750625684` |
| Local national format | `0750625684`, `0810000000` |

Invalid numbers return `422 INVALID_PHONE_NUMBER`. To test for free, send to `+256700000000`, `+254700000000`, or `+243810000000`. See [Sandbox](https://docs.ugatext.com/sandbox.md).

## Costs and currency

| Country | Rate |
| - | - |
| Uganda | UGX 25 per SMS |
| Kenya | KES 0.4 per SMS |
| DR Congo | USD 0.035 per SMS |

Volume discounts apply. See [ugatext.com/pricing](https://ugatext.com/pricing) for current rates.

Send and status responses report cost in several currencies:

| Field | Description |
| - | - |
| `cost_ugx` | Cost in Ugandan shillings. |
| `cost_kes` | Cost in Kenyan shillings. |
| `cost_usd` | Cost in US dollars. |
| `currency` | Billing currency: `UGX`, `KES`, or `USD`. |
| `country` | Destination country, for example `Uganda`. |
| `network` | Destination carrier, for example `Airtel`. |

## Send bulk SMS

`POST /sms/bulk` sends one message to up to **5,000 recipients** per request.

```bash theme={null}
curl -X POST https://ugatext.com/api/v1/sms/bulk \
  -H "Client-ID: YOUR_CLIENT_ID" \
  -H "Client-Secret: YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "recipients": ["+256700000000", "+256772123456"],
    "message": "Important community update from UgaText.",
    "sender_id": "UGATEXT"
  }'
```

* `recipients` also accepts the aliases `phones`, `to`, and `messages`.
* Items can be objects with their own `to`, `message`, and `sender_id`, so each recipient can get a different message.

The response includes a `batch_id`, totals (`total_recipients`, `dispatched_count`, `failed_count`, `total_segments`, `total_cost_ugx`), and a `results` array with one entry per recipient. See [Bulk results](https://docs.ugatext.com/errors.md#bulk-results).

## Schedule a message

`POST /sms/schedule` queues a message for a future time. Send to one number or pass an array for a scheduled bulk broadcast.

```bash theme={null}
curl -X POST https://ugatext.com/api/v1/sms/schedule \
  -H "Content-Type: application/json" \
  -H "Client-ID: YOUR_CLIENT_ID" \
  -H "Client-Secret: YOUR_CLIENT_SECRET" \
  -d '{
    "to": "+256750625684",
    "sender_id": "UGATEXT",
    "message": "Reminder: Your invoice #1042 is due tomorrow.",
    "scheduled_at": "2026-11-01T09:00:00.000Z",
    "timezone": "Africa/Kampala",
    "recurrence": "none",
    "title": "Invoice Reminder"
  }'
```

| Field | Type | Required | Description |
| - | - | - | - |
| `to` | string or string\[] | Yes | One E.164 number (for example `+256750625684`) or an array of numbers for a scheduled bulk broadcast. Aliases: `phone`, `recipients`, `phones`. |
| `message` | string | Yes | SMS text. 160 characters per segment for GSM-7, 70 for Unicode. Alias: `text`. |
| `scheduled_at` | string | Yes | Future send time in ISO-8601, for example `2026-11-01T09:00:00.000Z`. Alias: `scheduledAt`. |
| `sender_id` | string | No | Approved 3 to 11 character alphanumeric [Sender ID](https://docs.ugatext.com/sender-ids.md). Defaults to `UGATEXT`. Alias: `senderId`. |
| `timezone` | string | No | IANA timezone used for local scheduling. Defaults to `Africa/Kampala`. |
| `recurrence` | string | No | `none` (default), `daily`, `weekly`, or `monthly`. |
| `title` | string | No | Internal campaign label. Defaults to `API Scheduled Message`. |

```json Response (200 OK) theme={null}
{
  "success": true,
  "message_id": "sched_1760425200000_1a2b3c4d",
  "status": "scheduled",
  "recipient": "+256750625684",
  "sender_id": "UGATEXT",
  "scheduled_at": "2026-11-01T09:00:00.000Z",
  "segments": 1,
  "estimated_cost_ugx": 25
}
```

### Cancel or reschedule

You can change a scheduled message until its send time.

| Action | Endpoint | Body |
| - | - | - |
| Cancel a scheduled SMS | `POST /sms/schedule/{id}/cancel` | None |
| Reschedule a pending SMS | `POST /sms/schedule/{id}/reschedule` | `{"scheduled_at": "2026-11-02T14:00:00.000Z"}` |

```json Cancel response theme={null}
{
  "success": true,
  "message_id": "sched_1760425200000_1a2b3c4d",
  "status": "cancelled",
  "message": "Scheduled SMS cancelled successfully."
}
```

Cancelling an unknown ID returns `404 NOT_FOUND`.

## Track delivery

Messages move from `queued` to `sent` to `delivered`, or end as `failed`.

* **Poll:** `GET /sms/status/{id}` returns the status, timestamps (`sent_at`, `delivered_at`, `failed_at`), `failure_reason`, `network`, and `provider_reference`.
* **Push:** register a [webhook](https://docs.ugatext.com/webhooks.md) to receive `sms.sent`, `sms.delivered`, and `sms.failed` events.
* **History:** `GET /sms/history` lists your recent sent and queued messages.

## Segments and encoding

Long messages are split into segments, and you're billed per segment.

| Encoding | Used when | Single SMS | Per segment in multi-part messages |
| - | - | - | - |
| `GSM-7` | The message contains only standard characters | 160 | 153 |
| `UCS-2` (Unicode) | The message contains emoji or non-Latin characters | 70 | 67 |

Unicode supports Luganda, Swahili, and other regional character sets. Each response includes `segments` and `encoding` so you can confirm the cost. To check a message before sending, use the [compliance pre-check](https://docs.ugatext.com/errors.md#compliance-pre-check).

## Check your balance

`GET /sms/balance` returns your wallet balance in UGX, the price per SMS, and the remaining SMS units.

```json theme={null}
{
  "success": true,
  "currency": "UGX",
  "balance_ugx": 150000,
  "rate_per_sms_ugx": 25,
  "sms_units_remaining": 6000,
  "account_status": "active"
}
```

When the balance is too low, sends return `402 INSUFFICIENT_BALANCE`. Top up with MTN Mobile Money, Airtel Money, or M-Pesa from the [dashboard](https://ugatext.com).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.