Create, get and delete numbers from your Opt Out List
The Opt Outs API lets you manage the list of recipients who have opted out of receiving messages on a given channel. Use it to query existing opt-outs, create new ones, and remove them — for example, to honour an unsubscribe request, sync opt-out state from another system, or audit who is currently suppressed.
Account-level vs asset-level opt-outs
Every opt-out is recorded at one of two scopes:
Account-level — the opt-out applies across all assets on the account for that channel. A recipient who is opted out at the account level will not receive messages on that channel from any of your numbers or WhatsApp profiles.
Asset-level — the opt-out is scoped to a single asset (a specific inbound number or WhatsApp profile). The recipient remains contactable on that channel via your other assets.
In responses, the account_level_opt_out field tells you which scope a record uses. Asset-level records additionally return inbound_asset_id and inbound_number identifying the asset they are tied to.
Channels
Opt-outs are tracked per channel. The API currently supports SMS and WHATSAPP. The same phone number can hold separate opt-out records on each channel, and at different scopes — for example, an account-level WhatsApp opt-out alongside an asset-level SMS opt-out.
Synchronous processing
All three endpoints process requests synchronously. The create and delete endpoints accept arrays so you can submit multiple entries in a single request, but there is no background job — the response always reflects the final outcome of every entry. Each result is reported individually in an items array, so you should inspect the per-entry status rather than relying on the HTTP status alone, particularly when submitting in bulk.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /optouts/ | Query the opt-outs on an account, with optional filtering and paging. |
| POST | /optouts/ | Create one or more opt-outs at account or asset level. |
| DELETE | /optouts/ | Remove one or more opt-outs, optionally scoped by channel or asset |
Query the opt-outs
Method: GET
Rate Limit: 10 transactions per second.
Parameters
| Parameter name | Type | Mandatory | Example values | Description |
|---|---|---|---|---|
| number | string | No | +447807127121447807127121 | Exact match phone number search. Accepts either E.164 format (with + and country code) or a national number with country code. |
| opt_out_type | string | No | keyword web_opt_out account_import api_import | Filter by how the opt-out was created. keyword - The recipient replied to an inbound asset with an opt-out keyword (for example, STOP). web_opt_out - The recipient opted out via a web form. account_import - The opt-out was added through a bulk import in the Webex Interact app. api_import - The opt-out was added via the Opt Outs API. Single value only. |
| channel | string | No | SMS | Filter by communication channel. Case-insensitive. |
| inbound_number | string | No | 447860000001 | Returned only when opt_out_type is keyword. The inbound number associated with the asset. Can be either an E.164 long number (for example, +447860008141) or a short code (for example, 66777). Always treat as a string. |
| asset_id | string | No | num_2AkZZTFulHFfIEHVYteKKsTdymo | Returned only when opt_out_type is keyword. The UID of the inbound asset (SMS dedicated inbound number or WhatsApp Business Profile) that received the opt-out keyword. |
| start_time | string | No | 2026-05-28T09:17:53Z | Filter to opt-outs created at or after this time. ISO 8601 UTC format. Inclusive bound. Filters on opt_out_time. |
| end_time | string | No | 2026-05-28T09:17:53Z | Filter to opt-outs created at or before this time. ISO 8601 UTC format. Inclusive bound. Filters on opt_out_time. |
| page_number | integer | No | 1 | Determines which page is returned. Use in conjunction with page_size to control the set of opt-outs you want to get. Defaults to 1 if not given. |
| page_size | integer | No | 10 | Determines how many items will be returned per page. Min: 1 Max: 1000 Defaults to 10 if not given. |
| sort_order | string | No | ASC, DESC | Determines the sort order by opt_out_time. Defaults to DESC if not given. |
Default behaviour
If no parameters are supplied, the 10 most recently created opt-outs are returned.
Response fields
| Field name | Type | Description |
|---|---|---|
| number | string | The phone number that has opted out, in E.164 format. |
| channel | string | The communication channel the opt-out applies to. Either SMS or WHATSAPP. |
| account_level_opt_out | boolean | true - The opt-out applies to all communications sent from your account on this channel.false - The opt-out applies only to communications sent via the specific inbound asset returned in inbound_asset. |
| opt_out_type | string | How the opt-out was created. One of: keyword, web_opt_out, account_import, api_import. |
| inbound_asset | string | Returned only when opt_out_type is keyword.The UID of the inbound asset (SMS dedicated inbound number or WhatsApp Business Profile) that received the opt-out keyword. |
| inbound_number | string | Returned only when opt_out_type is keyword.The inbound number associated with the asset. Can be either an E.164 long number (for example, +447860008141) or a short code (for example, 66777). Always treat as a string. |
| opt_out_time | string | The time the opt-out was created, in ISO 8601 UTC format. |
Sample request
GET https://api.webexinteract.com/contacts/v1/optouts?opt_out_type=keyword&page_size=10
Sample responses
{
"paging": {
"current_page": 1,
"total_items": 6,
"total_pages": 1
},
"items": [
{
"number": "+447944638173",
"channel": "SMS",
"account_level_opt_out": true,
"opt_out_type": "keyword",
"inbound_asset_id": "num_397K0l3HrujnEtVfLFtaECRqFjV",
"inbound_number": "66777",
"opt_out_time": "2026-05-27T07:32:56Z"
},
{
"number": "+447944638173",
"channel": "SMS",
"account_level_opt_out": false,
"opt_out_type": "keyword",
"inbound_asset_id": "num_3DNr8KIVDwMtQKYtYvRtQCXbc5x",
"inbound_number": "+447860008141",
"opt_out_time": "2026-05-27T07:29:13Z"
},
{
"number": "+918074948043",
"channel": "WHATSAPP",
"account_level_opt_out": false,
"opt_out_type": "keyword",
"inbound_asset_id": "wbp_2k8U5Sdg3fM615QpOvEgzFiJZ1C",
"inbound_number": "+447488865097",
"opt_out_time": "2025-06-04T02:34:30Z"
}
]
}
{
"paging": {
"current_page": 1,
"total_items": 8861,
"total_pages": 887
},
"items": [
{
"number": "+447807127121",
"channel": "WHATSAPP",
"account_level_opt_out": true,
"opt_out_type": "api_import",
"opt_out_time": "2026-05-28T09:17:53Z"
},
{
"number": "+447944638175",
"channel": "SMS",
"account_level_opt_out": false,
"opt_out_type": "api_import",
"opt_out_time": "2026-05-27T07:38:45Z"
}
]
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_VAL_001",
"error": "VALIDATION_ERROR",
"message": "Invalid number. Supply a valid E.164 number, or a national number with country_code.",
"status": 400,
"timestamp": "2026-05-28T11:13:31.798355228Z",
"validation_errors": null
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_VAL_001",
"error": "VALIDATION_ERROR",
"message": "Invalid opt_out_type. Allowed values: keyword, web_opt_out, account_import, api_import.",
"status": 400,
"timestamp": "2026-05-28T11:02:15.336680287Z",
"validation_errors": null
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_VAL_001",
"error": "VALIDATION_ERROR",
"message": "Invalid channel. Must be SMS or WHATSAPP.",
"status": 400,
"timestamp": "2026-05-28T11:23:17.146338088Z",
"validation_errors": null
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_VAL_001",
"error": "VALIDATION_ERROR",
"message": "Request validation failed",
"status": 400,
"timestamp": "2026-05-28T11:18:49.836191335Z",
"validation_errors": [
{
"field": "getOptOuts.pageSize",
"message": "page.size.generic",
"rejected_value": 1001
}
]
}
Create an opt-out
Method: POST
One opt-out per request
The request body accepts an
optoutsarray, but the endpoint processes a single entry per request. To create multiple opt-outs, send one request per opt-out.
Existing opt-outs are replaced
If you create an opt-out for a number that is already opted out on the same channel and asset, the existing record is replaced and
opt_out_timeis updated to the latest timestamp.
Rate Limit: 10 transactions per second.
Parameters
| Parameter name | Type | Mandatory | Example values | Description |
|---|---|---|---|---|
| optouts | array | Yes | N/A | An array containing one opt-out object. |
| number | string | Yes | +447807127121447807127121 | The phone number to opt out. Accepts either E.164 format (with + and country code) or a national number with country code. The number is normalised to E.164 in the response. |
| channel | string | No | SMS | The communication channel the opt-out applies to. Case-insensitive. Defaults to SMS if not given. |
| asset_id | string | No | num_3DNr8KIVDwMtQKYtYvRtQCXbc5x wbp_2k8U5Sdg3fM615QpOvEgzFiJZ1C | The UID of the inbound asset to associate the opt-out with. Use a num_ UID for SMS dedicated inbound numbers and a wbp_ UID for WhatsApp Business Profiles. The asset's channel must match the channel value.If not given, the opt-out is applied at account level and applies to all communications sent on the specified channel. |
Response fields
| Field name | Type | Description |
|---|---|---|
| total_submitted | integer | The number of opt-out entries submitted in the request. |
| total_succeeded | integer | The number of opt-out entries that were successfully created. |
| total_failed | integer | The number of opt-out entries that failed to be created. |
| items | array | An array containing the outcome of each submitted opt-out. |
| number | string | The phone number, normalised to E.164 format. |
| channel | string | The communication channel the opt-out applies to. Either SMS or WHATSAPP. |
| status | string | The outcome for this entry. Either success or failure. |
| message | string | A human-readable description of the outcome. |
| account_level_opt_out | boolean | Returned only when status is success.true - The opt-out applies to all communications sent from your account on this channel.false - The opt-out applies only to the specific inbound asset. |
| opt_out_type | string | Returned only when status is success.Always api_import for opt-outs created via this endpoint. |
| opt_out_time | string | Returned only when status is success.The time the opt-out was created, in ISO 8601 UTC format. |
HTTP 201 with failed entries
The endpoint returns HTTP
201 Createdwhenever the request body is well-formed, regardless of whether the opt-out was successfully created. Always inspecttotal_failedandresults[].statusto determine the outcome.
Sample requests
{
"optouts": [
{
"number": "447807127121"
}
]
}
{
"optouts": [
{
"number": "447807127122",
"channel": "sms",
"asset_id": "num_3DNr8KIVDwMtQKYtYvRtQCXbc5x"
}
]
}
{
"optouts": [
{
"number": "447807127122",
"channel": "whatsapp",
"asset_id": "wbp_2k8U5Sdg3fM615QpOvEgzFiJZ1C"
}
]
}
Sample responses
{
"total_submitted": 1,
"total_succeeded": 1,
"total_failed": 0,
"items": [
{
"number": "+447807127121",
"channel": "SMS",
"status": "success",
"message": "Successfully opted out at account level for SMS",
"account_level_opt_out": true,
"opt_out_type": "api_import",
"opt_out_time": "2026-05-28T12:01:29Z"
}
]
}
{
"total_submitted": 1,
"total_succeeded": 1,
"total_failed": 0,
"items": [
{
"number": "+447807127122",
"channel": "SMS",
"status": "success",
"message": "Successfully opted out for asset num_3DNr8KIVDwMtQKYtYvRtQCXbc5x",
"account_level_opt_out": false,
"opt_out_type": "api_import",
"opt_out_time": "2026-05-28T12:00:46Z"
}
]
}
{
"total_submitted": 1,
"total_succeeded": 0,
"total_failed": 1,
"items": [
{
"number": "sdc447807127121",
"channel": "SMS",
"status": "failure",
"message": "Invalid phone number. Number must be in E.164 format."
}
]
}
{
"total_submitted": 1,
"total_succeeded": 0,
"total_failed": 1,
"items": [
{
"number": "+447807127121",
"channel": "SMS",
"status": "failure",
"message": "Invalid asset ID"
}
]
}
{
"total_submitted": 1,
"total_succeeded": 0,
"total_failed": 1,
"items": [
{
"number": "+447807127122",
"channel": "WHATSAPP",
"status": "failure",
"message": "Channel mismatch: the specified asset does not match the requested channel"
}
]
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_VAL_001",
"error": "MISSING_REQUIRED_FIELD",
"message": "Required field 'optOuts[0].number' is missing",
"status": 400,
"timestamp": "2026-05-28T12:08:22.598046993Z",
"validation_errors": [
{
"field": "optOuts[0].number",
"message": "Phone number is required",
"rejected_value": null
}
]
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_REQ_002",
"error": "INVALID_REQUEST_BODY",
"message": "Invalid or malformed request body. Please check your JSON format and ensure all required fields are provided.",
"status": 400,
"timestamp": "2026-05-28T12:03:18.652549805Z",
"validation_errors": null
}
Delete an opt-out
Method: DELETE
Bulk deletion is supported
Unlike the create endpoint, DELETE accepts multiple numbers per request and processes each entry independently. Inspect
total_failedandresults[].statusto determine the outcome for each entry.
Rate Limit: 10 transactions per second.
Parameters
| Parameter name | Type | Mandatory | Example values | Description |
|---|---|---|---|---|
| numbers | array of strings | Yes | ["+447807127121", "+447807127122"] | The phone numbers to remove from opt-outs. Each entry accepts either E.164 format (with + and country code) or a national number with country code. |
| channel | string | No | SMS | The communication channel to remove opt-outs from. Case-insensitive. If not given, opt-outs are removed across both SMS and WHATSAPP channels. |
| asset_id | string | No | num_3DNr8KIVDwMtQKYtYvRtQCXbc5x wbp_2k8U5Sdg3fM615QpOvEgzFiJZ1C | The UID of the inbound asset to remove the opt-out from. Use a num_ UID for SMS dedicated inbound numbers and a wbp_ UID for WhatsApp Business Profiles. The asset's channel must match the channel value.If not given, all opt-outs for the number on the specified channel(s) are removed, including account-level opt-outs and opt-outs against any asset. |
Account-level and asset-level opt-outs are independent
If a number has both an account-level opt-out and asset-level opt-outs:
- Removing only the account-level opt-out (by specifying an
asset_idof an asset where no opt-out exists) leaves asset-level opt-outs intact.- Removing only an asset-level opt-out leaves the account-level opt-out intact.
- Omitting
asset_idremoves both account-level and all asset-level opt-outs for the number on the specified channel(s).
Response fields
| Field name | Type | Description |
|---|---|---|
| total_submitted | integer | The number of phone numbers submitted in the request. |
| total_succeeded | integer | The number of opt-outs that were successfully removed. |
| total_failed | integer | The number of entries that failed to be removed. |
| items | array | An array containing the outcome for each submitted number. |
| number | string | The phone number, normalised to E.164 format on success or returned as submitted on failure. |
| status | string | The outcome for this entry. Either success or failure. |
| message | string | A human-readable description of the outcome. |
Sample requests
{
"numbers": [
"+447807127121",
"+447807127122"
],
"channel": "SMS"
}
{
"numbers": [
"+447807127123"
],
"asset_id": "num_3DNr8KIVDwMtQKYtYvRtQCXbc5x",
"channel": "SMS"
}
Sample responses
{
"total_submitted": 2,
"total_succeeded": 2,
"total_failed": 0,
"items": [
{
"number": "+447807127121",
"status": "success",
"message": "Opt-out entry deleted successfully"
},
{
"number": "+447807127122",
"status": "success",
"message": "Opt-out entry deleted successfully"
}
]
}
{
"total_submitted": 1,
"total_succeeded": 0,
"total_failed": 1,
"items": [
{
"number": "+447807127123",
"status": "failure",
"message": "Number not found on SMS channel"
}
]
}
{
"total_submitted": 1,
"total_succeeded": 0,
"total_failed": 1,
"items": [
{
"number": "+447807127123",
"status": "failure",
"message": "Number not found for the specified SMS asset"
}
]
}
{
"total_submitted": 1,
"total_succeeded": 0,
"total_failed": 1,
"items": [
{
"number": "+447807127123a",
"status": "failure",
"message": "Invalid phone number. Number must be in E.164 format."
}
]
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_VAL_001",
"error": "MISSING_REQUIRED_FIELD",
"message": "Required field 'numbers' is missing",
"status": 400,
"timestamp": "2026-05-28T15:43:26.377057543Z",
"validation_errors": [
{
"field": "numbers",
"message": "The numbers list must not be empty",
"rejected_value": null
}
]
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_VAL_001",
"error": "VALIDATION_ERROR",
"message": "Channel mismatch: the specified asset does not match the requested channel",
"status": 400,
"timestamp": "2026-05-28T15:43:49.984931494Z",
"validation_errors": null
}
{
"trace_id": "no-trace-id",
"code": "ERR_CNT_REQ_002",
"error": "INVALID_REQUEST_BODY",
"message": "Invalid or malformed request body. Please check your JSON format and ensure all required fields are provided.",
"status": 400,
"timestamp": "2026-05-28T15:44:24.687216601Z",
"validation_errors": null
}