> ## 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.

# Compliance and opt-outs

> UCC content rules, promotional quiet hours, opt-out suppression, and the pre-flight compliance check for UgaText SMS.

UgaText enforces Uganda Communications Commission (UCC) and East African telecom anti-spam directives through a real-time 21-rule compliance engine. Every message is checked before it reaches the carrier.

## Content rules

> [accordion] Sender identity
>
> Every broadcast must come from a verified alphanumeric [Sender ID](https://docs.ugatext.com/sms/sender-ids.md) (3 to 11 characters) or the default `UGATEXT`. Impersonating banks, government agencies, or telecom operators (for example `MTN`, `AIRTEL`, `BOU`, `URA`) without authorization is rejected with `403 COMPLIANCE_BLOCKED`.

> [accordion] Prohibited content
>
> These are blocked automatically (decision `BLOCK`):
>
> * Phishing links
> * Fake Mobile Money PIN prompts
> * Unlicensed loan scams
> * Betting or gambling broadcasts to unverified lists
> * Fraudulent impersonation

> [accordion] Promotional quiet hours
>
> Promotional and marketing broadcasts may only be sent between **07:00 and 21:00 EAT** (`Africa/Kampala`). Transactional messages such as OTPs, payment receipts, and security alerts can be sent 24/7.

> [accordion] URL and link shortener inspection
>
> Shortened URLs that hide malicious redirects or credential-harvesting domains are flagged for review (decision `REVIEW`) or blocked.

## Opt-outs

### Include an opt-out line

Marketing and promotional campaigns must end with clear unsubscribe instructions, for example `Reply STOP to unsubscribe`.

### Suppression list

A number is added to your opt-out suppression list immediately when:

* The recipient replies with an opt-out keyword: `STOP`, `UNSUBSCRIBE`, `CANCEL`, `END`, `QUIT`, or `OPT OUT`.
* You add it from the dashboard or through the [Opt-out API](#opt-out-api).

Sending promotional SMS to a suppressed number returns `422 NUMBER_SUPPRESSED_ON_OPT_OUT_LIST`.

> [!NOTE]
>
> In bulk broadcasts, suppressed numbers are filtered out before billing, so you are not charged for them.

### Opt back in

When a recipient replies `START` or `SUBSCRIBE`, the number is removed from the suppression list and receives a confirmation SMS.

## Opt-out API

Manage your suppression list with the `/api/opt-outs` endpoints. They are also available under `/api/sms/opt-outs`.

| Action | Endpoint |
| - | - |
| List opted-out numbers | `GET /api/opt-outs` (or `GET /api/opt-outs/list`) |
| Add a number | `POST /api/opt-outs/add` |
| Remove a number | `POST /api/opt-outs/remove` (or `/delete`) |
| Bulk import numbers | `POST /api/opt-outs/import` |
| Export as CSV | `GET /api/opt-outs/export` |
| Filter recipients before sending | `POST /api/opt-outs/check` |
| Get audit events | `GET /api/opt-outs/audit-logs` |
| Receive carrier replies | `POST /api/opt-outs/inbound-webhook` |

### List opted-out numbers

`GET /api/opt-outs` accepts these query parameters:

| Parameter | Default | Description |
| - | - | - |
| `page` | `1` | Page number. |
| `limit` | `20` | Results per page, up to 100. |
| `search` | | Filter by phone number. |
| `source` | | `sms_reply`, `manual`, or `import`. |

The response contains `success`, `records`, `total`, `page`, `limit`, `totalPages`, and `stats`.

### Add, remove, and import numbers

```json Add (POST /api/opt-outs/add) theme={null}
{
  "phone": "+256772123456",
  "notes": "Requested via support",
  "campaignId": "cmp_123",
  "senderId": "UGATEXT"
}
```

```json Remove (POST /api/opt-outs/remove) theme={null}
{
  "phone": "+256772123456",
  "reason": "Customer requested resubscription"
}
```

```json Import (POST /api/opt-outs/import) theme={null}
{
  "numbers": ["+256772123456", "+254712345678"],
  "notes": "CSV import"
}
```

`GET /api/opt-outs/export` downloads a CSV file of every opted-out number on your account.

### Filter recipients before sending

`POST /api/opt-outs/check` splits a recipient list into numbers you can message and numbers that opted out.

```json Request theme={null}
{
  "recipients": ["+256772123456", "+256700000000"]
}
```

```json Response theme={null}
{
  "success": true,
  "allowed": ["+256700000000"],
  "skipped": ["+256772123456"],
  "summary": "1 allowed, 1 skipped (opted out)"
}
```

### Audit log

`GET /api/opt-outs/audit-logs` returns the last 100 opt-out and opt-in events.

### Inbound carrier webhook

`POST /api/opt-outs/inbound-webhook` receives recipient replies from the carrier and records opt-outs and opt-ins automatically.

```json theme={null}
{
  "from": "+256772123456",
  "message": "STOP"
}
```

## Pre-flight compliance check

Validate message copy before you send with `POST /compliance/inspect`.

```bash theme={null}
curl -X POST https://ugatext.com/api/v1/compliance/inspect \
  -H "Content-Type: application/json" \
  -d '{
    "sender_id": "UGATEXT",
    "message": "Your verification code is 482910. Valid for 10 minutes."
  }'
```

| Field | Description |
| - | - |
| `decision` | `APPROVE`, `REVIEW`, or `BLOCK`. |
| `risk_score` | Risk from 0 to 100. |
| `encoding` | `GSM-7` or `UCS-2`. |
| `sms_parts` | Number of segments the message uses. |
| `violations` | Rules the message breaks. |
| `warnings` | Issues that do not block sending. |

## Related errors

| Status | Code | Meaning |
| - | - | - |
| 403 | `COMPLIANCE_BLOCKED` | The message or Sender ID failed compliance checks. |
| 422 | `NUMBER_SUPPRESSED_ON_OPT_OUT_LIST` | The recipient opted out of promotional messages. |

See [Errors and limits](https://docs.ugatext.com/errors.md) for all error codes.


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