# SMS Gateway (Payless4SMS)

The **SMS Gateway** is a direct HTTP/JSON API for sending single and bulk SMS to any mobile network, with delivery tracking, two-way replies, scheduling, and credit management. It is a standalone product — separate from the WhatsApp-centric [Omnichannel API](/apis/omnichannel) and from the XML-based [Biz SMS API](/apis/biz-sms).

For the full endpoint and schema reference, see the [SMS Gateway API](/apis/sms).

## Base URL

```
https://api.payless4sms.com
```

`https://api.ecommunicate.co.za` is an alternate production host. Always use the hostname, never a raw IP.

## Authentication

Every request is authenticated with an **API key** — send an `X-API-Key: ecomm_...` header. Always use HTTPS so the key is never sent in the clear.

Get an API key or OTP token
Generate and revoke API keys from the client portal (**API Keys**). For one-time-pin traffic that must deliver in 5–10 seconds, request an `otpToken` from [support@ecommunicate.co.za](mailto:support@ecommunicate.co.za) and send it as an additional header.

## Send your first SMS

```bash
curl -X POST https://api.payless4sms.com/sms/json \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ecomm_your_api_key" \
  -d '{
    "messages": [
      {
        "ctid": "order-12345",
        "recipients": [
          { "to": "27821234567", "identifier": "John" }
        ],
        "messageText": "Hello from eCommunicate"
      }
    ]
  }'
```

**Response — inspect `statusCode` for the outcome:**

```json
{
  "gstid": "3e99e8d9-50bf-469d-9fd4-d6c10cf5b152",
  "statusCode": "100",
  "statusDescription": "MESSAGE_ACCEPTED_FOR_PROCESSING",
  "completionTime": "2026-05-21T21:22:26+02:00"
}
```

`statusCode` `100` means the batch was accepted. Keep each request to a maximum of **1000** recipients, and send the next request only after receiving the previous response.

## Sending patterns

| Pattern | How |
|  --- | --- |
| One message to one recipient | A single-entry `messages` array |
| Same text to many recipients | Top-level `ctid` + `recipients` + `messageText` |
| Many messages to many recipients | Multiple entries in `messages`, each with its own `recipients` |
| Schedule a batch | `settings.scheduledSmsDate` (`YYYY-MM-DDThh:mm:ssZ`) |
| Unicode | `"unicode": "true"` (70 chars/segment) |
| Don't save message | `settings.dsm: "true"` |


## Track delivery

Query delivery status by `ctid`, `stid`, time range, or the global ids:

```bash
curl -X POST https://api.payless4sms.com/sms/trackingMessageStatus \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ecomm_your_api_key" \
  -d '{ "ctid": "order-12345", "sentDate": "2026-05-21", "showfinalstatus": "true" }'
```

Each receipt carries a `statusCode` — for example `500` Message Sent, `501` Queued At MNO, `600` Delivery Success, `620` Failed In Delivery.

Tracking is rate limited
Each id can be queried up to 10 times in the first 10 minutes, then once every 10 minutes. Exceeding this returns `statusCode` `228`.

## Receive delivery receipts and replies

Instead of polling, configure callback URLs and let the gateway push events to you:

```json
{
  "settings": {
    "receiptCallBackURL": "https://your-server.com/receipts",
    "replyCallBackURL": "https://your-server.com/replies"
  },
  "messages": [ ... ]
}
```

- **Delivery receipts** are delivered as an HTTP `GET` to your `receiptCallBackURL`.
- **Replies** are delivered to your `replyCallBackURL` (GET or POST).
- Return HTTP `200`. Undelivered callbacks are retried for up to 24 hours.


See the [webhook reference](/apis/sms) for the exact payloads.

## Opt-outs

Recipients who reply `STOP`, `END`, `CANCEL`, `QUIT`, or `UNSUBSCRIBE` are blacklisted automatically; further sends to them are blocked and refunded. Retrieve the list with `POST /sms/getUnsubscribelist`.

## Check your balance

```bash
curl -X POST https://api.payless4sms.com/sms/getBalance \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ecomm_your_api_key" \
  -d '{}'
```

## Production tips

- **Prefer POST over GET** — the request body is not length-limited, and nothing sensitive lands in the URL.
- **Set a unique `ctid`** (ideally a GUID) per message so you can track and safely retry.
- **Retry safely** — resending an identical request with the same `ctid` will not double-send; already-sent messages are skipped.
- **Watch for `502`** — if you run a backup gateway, a `502` response means resend via the backup until the status returns to `100`.