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

# Vobiz Messaging Opt-outs

> How Vobiz records STOP, HELP and other keyword replies as opt-outs, how to add, list, check and remove opt-outs by API, what happens when you send to an opted-out number, and how broadcasts honour the list.

An opt-out is a number that must not receive messages from your account on a channel. Vobiz builds the list for you from keyword replies and lets you add to it, query it and remove from it by API. Every send - single messages and broadcasts alike - is checked against the list before anything leaves the platform. The console shows the same list under **SMS & RCS → Opt-outs**.

<Note>
  Honouring opt-outs is a legal requirement in most markets (for example TCPA and CTIA guidelines in the US, and TRAI rules in India) and a condition of US 10DLC and toll-free registration. Keep the list intact, and make sure your own records of consent match it.
</Note>

## Keyword replies are recorded automatically

When a contact replies to one of your numbers, Vobiz lower-cases and trims the text, strips trailing punctuation, and compares it with the standard keywords. An exact match creates an opt-out entry for that number and channel with `source: "inbound"` and the reason shown:

| Keyword reply | Recorded `reason` | Meaning |
| - | - | - |
| `STOP`, `UNSUBSCRIBE`, `CANCEL`, `END` | `stop` | The contact asked to receive no more messages. |
| `START`, `SUBSCRIBE`, `UNSTOP` | `start` | The contact asked to receive messages again. |
| `HELP`, `INFO` | `help` | The contact asked what the number is and how to stop. |

All three groups are recorded automatically, so you have a timestamped record of every keyword interaction. The reply itself is also stored in the contact's [conversation](/docs/sms/conversations), where you can see it in context.

<Tip>
  When a contact replies `START`, remove their opt-out entry with [Remove an opt-out](/docs/sms/api/opt-outs/delete-opt-out) once you have confirmed their consent, so that sends to them succeed again.
</Tip>

Keyword matching is exact: `STOP` and `stop.` match, `please stop` does not. Add a manual opt-out for any request that arrives in free text.

## Add an opt-out manually

[Create an opt-out](/docs/sms/api/opt-outs/create-opt-out) records a request that reached you another way - a support call, an email, an unsubscribe link:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.vobiz.ai/api/v1/sms/opt-outs" \
    -H "X-Auth-ID: MA_XXXXXXXX" \
    -H "X-Auth-Token: YOUR_AUTH_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "phoneNumber": "+14155550123", "channel": "sms", "reason": "support-request" }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://api.vobiz.ai/api/v1/sms/opt-outs",
      headers={
          "X-Auth-ID": "MA_XXXXXXXX",
          "X-Auth-Token": "YOUR_AUTH_TOKEN",
          "Content-Type": "application/json",
      },
      json={"phoneNumber": "+14155550123", "channel": "sms", "reason": "support-request"},
  )
  resp.raise_for_status()
  print(resp.status_code, resp.json())
  ```

  ```javascript Node theme={null}
  const resp = await fetch("https://api.vobiz.ai/api/v1/sms/opt-outs", {
    method: "POST",
    headers: {
      "X-Auth-ID": "MA_XXXXXXXX",
      "X-Auth-Token": "YOUR_AUTH_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ phoneNumber: "+14155550123", channel: "sms", reason: "support-request" }),
  });
  console.log(resp.status, await resp.json());
  ```
</CodeGroup>

| Field | Required | Notes |
| - | - | - |
| `phoneNumber` | yes | E.164 with a leading `+`. Missing it returns `400 {"error":"phoneNumber is required"}`. |
| `channel` | no | `sms` (default), `mms` or `rcs`. |
| `reason` | no | Free text for your records. Default `manual`. |

```json Response - 201 Created theme={null}
{ "status": "ok" }
```

The entry is keyed on number and channel. Adding the same number again updates its `reason` rather than creating a duplicate. Manual entries have `source: "manual"`.

## List opt-outs

[List opt-outs](/docs/sms/api/opt-outs/list-opt-outs) returns a JSON array of entries. **Both `limit` and `offset` are required**; page through the list by increasing `offset`.

```bash cURL theme={null}
curl "https://api.vobiz.ai/api/v1/sms/opt-outs?limit=100&offset=0" \
  -H "X-Auth-ID: MA_XXXXXXXX" \
  -H "X-Auth-Token: YOUR_AUTH_TOKEN"
```

```json Response - 200 OK theme={null}
[
  {
    "id": "9b2e1c40-8a3d-4f5e-9c1a-7d6b2e8f4a01",
    "accountId": "MA_XXXXXXXX",
    "phoneNumber": "+14155550123",
    "channel": "sms",
    "reason": "stop",
    "source": "inbound",
    "syncedToProvider": true,
    "createdAt": "2026-10-18T07:23:03.658669Z"
  },
  {
    "id": "3c1d7e52-6f4b-4a8e-b2d9-0e5f1a7c9b34",
    "accountId": "MA_XXXXXXXX",
    "phoneNumber": "+14155550124",
    "channel": "sms",
    "reason": "support-request",
    "source": "manual",
    "syncedToProvider": true,
    "createdAt": "2026-10-17T15:02:11.104233Z"
  }
]
```

| Field | Meaning |
| - | - |
| `phoneNumber` | The opted-out number. |
| `channel` | The channel the entry applies to. |
| `reason` | `stop`, `start` or `help` for keyword entries; `manual` or your own text for API entries. |
| `source` | `inbound` (keyword reply) or `manual` (API or console). |
| `syncedToProvider` | Whether the entry has also been propagated to the upstream network's suppression list. |
| `createdAt` | When the entry was recorded or last updated. |

## Check one number

[Check an opt-out](/docs/sms/api/opt-outs/check-opt-out) answers a yes/no question for one number and channel. URL-encode the `+` as `%2B`. `channel` defaults to `sms`.

```bash cURL theme={null}
curl "https://api.vobiz.ai/api/v1/sms/opt-outs/%2B14155550123?channel=sms" \
  -H "X-Auth-ID: MA_XXXXXXXX" \
  -H "X-Auth-Token: YOUR_AUTH_TOKEN"
```

```json Response - 200 OK theme={null}
{ "optedOut": true }
```

Call it before you add a number to a marketing list, or to explain to an agent why a send returned `422`.

## Remove an opt-out

[Remove an opt-out](/docs/sms/api/opt-outs/delete-opt-out) deletes the entry for a number and channel. `channel` defaults to `sms`.

```bash cURL theme={null}
curl -X DELETE "https://api.vobiz.ai/api/v1/sms/opt-outs/%2B14155550123?channel=sms" \
  -H "X-Auth-ID: MA_XXXXXXXX" \
  -H "X-Auth-Token: YOUR_AUTH_TOKEN"
```

```json Response - 200 OK theme={null}
{ "status": "ok" }
```

The call returns `200` whether or not an entry existed.

<Warning>
  Remove an opt-out only when the contact has given you fresh, documented consent - a `START` reply, a signed form, a renewed subscription. Deleting an entry because a campaign needs more reach exposes you to complaints, carrier filtering and regulatory penalties, and can put your 10DLC or toll-free registration at risk.
</Warning>

## What happens when you send to an opted-out number

Every recipient of [Send a message](/docs/sms/api/messages/send-message) is checked against the list for the message's channel before routing:

* A send where the only (or first) recipient is opted out creates no message and returns `422 {"error":"recipient has opted out: +14155550123"}`.
* In a multi-recipient send, the opted-out recipient is skipped and the others are sent; the call returns `202 Accepted` with the first created message. See [several recipients in one call](/docs/sms/channels/sms#several-recipients-in-one-call).
* An `sms` opt-out also blocks `mms` to that number, so a STOP reply to a text message suppresses picture messages too.
* The check runs before the idempotency lookup, so replaying an earlier `idempotencyKey` to a number that has since opted out also returns `422`.

### Broadcasts

When you [upload recipients](/docs/sms/api/broadcasts/upload-recipients) to a broadcast, numbers with an `sms` opt-out are stored with status `opted_out` and counted in the upload result's `optedOut` field. They are never sent, and they appear in the broadcast's `stats.optedOut` and in the [export](/docs/sms/api/broadcasts/export-broadcast). See [Broadcasts](/docs/sms/broadcasts).

## Recommended practice

* Include opt-out instructions (`Reply STOP to opt out`) in the first message of any marketing thread and in every broadcast template. US 10DLC and toll-free registration both expect this.
* Reply to `HELP` with your brand name, a support contact and the STOP instruction. The `help` entries in the list show you who asked.
* Mirror the list into your CRM by polling [List opt-outs](/docs/sms/api/opt-outs/list-opt-outs) or by watching the `message.received` [webhook](/docs/sms/webhooks) event for keyword replies.
* Record the consent that justifies every [removal](/docs/sms/api/opt-outs/delete-opt-out).

## Before you go live

<CardGroup cols={2}>
  <Card title="Messaging numbers" icon="hashtag" href="/docs/sms/numbers">
    The numbers your opt-outs apply to.
  </Card>

  <Card title="India DLT" icon="flag" href="/docs/sms/compliance/india-dlt">
    Consent and DLT rules for Indian recipients.
  </Card>
</CardGroup>

## Related

<CardGroup cols={2}>
  <Card title="Broadcasts" icon="bullhorn" href="/docs/sms/broadcasts">
    Opted-out numbers are excluded from every broadcast.
  </Card>

  <Card title="Conversations" icon="comments" href="/docs/sms/conversations">
    See keyword replies in the contact's thread.
  </Card>

  <Card title="Compliance overview" icon="shield-check" href="/docs/sms/compliance/overview">
    Registration requirements that depend on opt-out handling.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/docs/sms/errors">
    The `422` opt-out response and other status codes.
  </Card>
</CardGroup>


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