# SMS Messaging

Send SMS messages directly or as automatic fallback when WhatsApp delivery fails. SMS provides universal reach — every mobile phone can receive an SMS.

Authentication Required
All API requests require your Developer Key in the `Authorization` header. No `Bearer` prefix — pass the key directly.
See [Authentication](/guides/authentication) for setup and security best practices.

## Endpoints

| Method | Endpoint | Description |
|  --- | --- | --- |
| `POST` | `/whatsapp-api-service/v2/messages` | Unified endpoint — set `channel: "SMS"` |
| `POST` | `/whatsapp-api-service/v2/channels/sms` | SMS-only endpoint |


## Sending an SMS

Unified Endpoint
```json
POST /whatsapp-api-service/v2/messages

{
  "channel": "SMS",
  "payload": {
    "messages": [
      {
        "to": "+27987654321",
        "text": "Your verification code is 123456",
        "ctId": "your-tracking-id",
        "unicode": false
      }
    ]
  }
}
```

SMS Endpoint
```json
POST /whatsapp-api-service/v2/channels/sms

{
  "messages": [
    {
      "to": "+27987654321",
      "text": "Your verification code is 123456",
      "ctId": "your-tracking-id",
      "unicode": false
    }
  ]
}
```

**Response (202 Accepted):**

```json
{
  "response": "Request Accepted for Processing",
  "smsGatewayResponse": {
    "statusCode": "0",
    "statusDescription": "Message(s) Accepted For Processing",
    "completionTime": "2026-01-15T10:30:00Z",
    "gstid": "tracking-uuid"
  }
}
```

## Encoding and character limits

| Encoding | `unicode` value | Single SMS | Multipart (per segment) | Best for |
|  --- | --- | --- | --- | --- |
| **GSM 7-bit** | `false` | 160 chars | 153 chars | English and standard Latin text |
| **Unicode** | `true` | 70 chars | 67 chars | Non-Latin characters, emoji, accented text |


Choosing the right encoding
- Use **GSM 7-bit** (`unicode: false`) for standard English text — it's more cost-effective since you get more characters per message part.
- Use **Unicode** (`unicode: true`) when your message contains non-Latin characters (Arabic, Chinese, Cyrillic), accented characters (e.g., `e`), or emoji.
- Multipart messages are automatically split and reassembled on the recipient's device.


### GSM 7-bit character set

The GSM 7-bit encoding supports: `A-Z`, `a-z`, `0-9`, space, and these special characters:

```
@ £ $ ¥ è é ù ì ò Ç Ø ø Å å Δ _ Φ Γ Λ Ω Π Ψ Σ Θ Ξ
^ { } \ [ ~ ] | € ! " # ¤ % & ' ( ) * + , - . / : ; < = > ? ¡ §
```

Any character outside this set will require Unicode encoding.

## Segments and billing

A single SMS can hold up to **160 GSM 7-bit characters**. Once a message goes over that limit, it is automatically split into **153-character segments** so the recipient's device can reassemble them into one long message. Each segment is billed as one SMS.

The 7 characters "lost" per segment (160 → 153) hold the User Data Header that tells the handset how to stitch the parts back together.

Calculate length on the client
Measure the message length **before** sending so you know how many SMS will be charged. The platform does not pre-flight the cost — once the message is accepted, every segment counts.

### GSM 7-bit segmentation

| Message length (characters) | Segments | Charged SMS |
|  --- | --- | --- |
| 1 – 160 | 1 | 1 |
| 161 – 306 | 2 | 2 (2 × 153) |
| 307 – 459 | 3 | 3 (3 × 153) |
| 460 – 612 | 4 | 4 (4 × 153) |
| 613 – 765 | 5 | 5 (5 × 153) |
| 766 – 918 | 6 | 6 (6 × 153) |


A message of **161 characters** costs **2 SMS**, not 1 — crossing the 160-character boundary by even a single character doubles the cost.

### Unicode (UCS-2) segmentation

When `unicode: true`, the per-segment limits drop because each character takes 2 bytes:

| Message length (characters) | Segments | Charged SMS |
|  --- | --- | --- |
| 1 – 70 | 1 | 1 |
| 71 – 134 | 2 | 2 (2 × 67) |
| 135 – 201 | 3 | 3 (3 × 67) |
| 202 – 268 | 4 | 4 (4 × 67) |


Watch for accidental Unicode
A single curly quote (`'`), em dash (`—`), or emoji forces the entire message onto Unicode encoding. A 161-character "English" message that contains one `—` becomes a **3-SMS Unicode** send instead of a **2-SMS GSM** send. Sanitise input or strip smart punctuation if you want to guarantee GSM 7-bit billing.

## SMS as WhatsApp fallback

Enable automatic SMS fallback on any WhatsApp message by adding the `fallback` object:

```json
{
  "sender": "+27123456789",
  "templateName": "your_template",
  "templateId": "template-uuid",
  "messageType": "NOTIFICATION",
  "messages": [ ... ],
  "fallback": {
    "sendFallback": true,
    "text": "Custom SMS text (optional)",
    "unicode": false
  }
}
```

| Field | Type | Description |
|  --- | --- | --- |
| `sendFallback` | boolean | `true` to send SMS if recipient is not on WhatsApp |
| `text` | string | Custom SMS text. If omitted, the resolved WhatsApp template text is used |
| `unicode` | boolean | `false` = GSM 7-bit, `true` = Unicode |


Fallback needs a phone number
SMS fallback delivers to the recipient's phone number, so it isn't available for a recipient addressed by `customerUserId` (BSUID) alone — there's no number to fall back to. Supply `to` as well if you want SMS fallback to apply.

**Toggle fallback at the client level:**

```
PUT /payless4messaging-service/WhatsApp/Client/updateClientSMSFallback
```

This enables or disables SMS fallback globally for all messages sent by that client.

## SMS reports

Retrieve sent and received SMS messages:

```
GET /whatsapp-api-service/SMSSendReceiveMessages/getSMSSendReceiveMessagesForCurrentLoginUser
```

**Query parameters:**

| Parameter | Type | Description |
|  --- | --- | --- |
| `page` | integer | Page number (0-based) |
| `size` | integer | Page size |
| `searchString` | string | Filter by phone number or text content |
| `direction` | enum | `OUTGOING` or `INCOMING` |
| `mode` | enum | `DIRECT` (sent as SMS) or `FALLBACK` (WhatsApp fallback) |


**Response fields:**

| Field | Description |
|  --- | --- |
| `receiver` | Recipient phone number |
| `text` | Message content |
| `messageStatus` | `DELIVERED`, `SENT`, `FAILED`, etc. |
| `messageCost` | Cost of the message |
| `messageType` | `DIRECT` or `FALLBACK` |
| `messageDirection` | `OUTGOING` or `INCOMING` |


## Check SMS balance

```
GET /whatsapp-api-service/SMSBalance/getClientBalance
```

Returns your current SMS credit balance. Monitor this to avoid delivery failures due to insufficient credits.

## Production tips

- **Always validate phone numbers** in E.164 format before sending (`+27...` for South Africa)
- **Use GSM 7-bit encoding by default** — only switch to Unicode when your message content requires it
- **Set `ctId` for tracking** — correlate SMS delivery reports with your internal records
- **Monitor your balance** — set up alerts when credits drop below a threshold
- **Check the `mode` field** in reports to distinguish between direct SMS and WhatsApp fallback messages