# Subscribers API

> Discover how to manage subscribers programmatically using the Broadcast API, including creating, reading, updating, and deleting subscriber data.

Source: https://sendbroadcast.net/docs/api-subscribers

The Subscribers API allows you to programmatically manage your subscriber list. It supports comprehensive filtering capabilities to enable efficient querying and external system synchronization.

## Required Permissions

All endpoints require authentication via an API token with appropriate permissions:

- List and read subscribers (Read)
- Create, update, and redact subscribers (Write)

## Common Use Cases

The filtering capabilities are particularly useful for:

- **External System Synchronization**: Sync inactive users with your CRM by filtering `is_active=false`
- **Segment Management**: Export specific subscriber segments based on tags, source, or activity status
- **Data Cleanup**: Identify inactive subscribers using `is_active=false`
- **Analytics and Reporting**: Generate reports for subscribers by date ranges or custom attributes
- **Compliance**: Efficiently retrieve subscription status for regulatory reporting

## Subscriber Object

The subscriber object contains the following fields:

| Field | Description |
| --- | --- |
| `id` | The ID of the subscriber |
| `email` | The email address of the subscriber |
| `first_name` | The first name of the subscriber |
| `last_name` | The last name of the subscriber |
| `ip_address` | The IP address of the subscriber |
| `is_active` | Whether the subscriber is active |
| `source` | The source of the subscriber |
| `subscribed_at` | The date and time the subscriber was subscribed |
| `unsubscribed_at` | The date and time the subscriber was unsubscribed |
| `confirmed_at` | The date and time the subscriber confirmed via double opt-in (null if unconfirmed or not applicable) |
| `confirmation_status` | Confirmation state: `"confirmed"` or `"unconfirmed"`. Derived from `confirmed_at`. |
| `created_at` | The date and time the subscriber was created |
| `tags` | An array of tags associated with the subscriber |
| `custom_data` | A JSON object, with key-value pairs |
| `topics` | Read only. Each [Subscriber Topics](https://sendbroadcast.net/docs/subscriber-topics) topic's stored value, keyed by its custom data key or tag: `true`, `false`, or `null` for no value |

## List Subscribers

```
GET /api/v1/subscribers.json
```

### Parameters

#### Pagination
- `page`: The page number to return (default is 1)

#### Filtering Parameters

The following filtering parameters can be used to filter the subscribers list:

**Active Status Filtering:**

- `is_active`: Filter by active status
  - `true`: Subscribers marked as active
  - `false`: Subscribers marked as inactive

**Confirmation Status Filtering:**

- `confirmation_status`: Filter by confirmation status
  - `confirmed`: Subscribers who have confirmed via double opt-in
  - `unconfirmed`: Subscribers who have not yet confirmed

**Source Filtering:**

- `source`: Filter by how the subscriber was added (e.g., `api_subscription`, `opt_in_form`, `import`)

**Date Range Filtering:**

- `created_after`: Filter subscribers created after this timestamp (ISO 8601, e.g. `2026-01-24T00:00:00Z`)
- `created_before`: Filter subscribers created before this timestamp (ISO 8601, e.g. `2026-01-24T23:59:59Z`)

Either form works: a bare date (`2026-01-24`, taken as midnight) or a full timestamp
(`2026-01-24T09:30:00Z`). Unix seconds are accepted too.

Warning

A value that cannot be read is **ignored** rather than rejected: the request succeeds without that filter and still returns `200`, reporting the reason as a `parameter_ignored` entry in `warnings`.

That fails in the direction that costs you. A filter’s job is to _remove_ rows, so a dropped filter returns **more** than you asked for: a job syncing “subscribers since yesterday” receives the entire list, and an unfiltered result looks exactly like a filter that matched everything. Check the `warnings` array before acting on a large response.

**Email Pattern Filtering:**

- `email`: Filter subscribers whose email contains the specified text (partial match, case-insensitive)

**Tag-Based Filtering:**

- `tags[]`: Filter subscribers by tags (supports multiple tags with AND logic)

**Tag Filtering Logic:**

When filtering by multiple tags, subscribers must have **ALL** specified tags to be included in the results.

**Example:** If you have subscribers with these tags:

- Alice: `["premium", "newsletter"]`
- Bob: `["premium", "vip"]`
- Carol: `["newsletter", "trial"]`
- Dave: `["basic"]`

Request `tags[]=premium&tags[]=newsletter` returns only Alice:

- ✅ Alice has both `premium` and `newsletter` (matches all required tags)
- ❌ Bob has `premium` but not `newsletter`
- ❌ Carol has `newsletter` but not `premium`
- ❌ Dave has neither `premium` nor `newsletter`

**Custom Data Filtering:**

- `custom_data[field_name]`: Filter by custom JSONB field values

### Request Examples

**Basic request:**

```
GET /api/v1/subscribers.json?page=1
```

**Filter by active status:**

```
GET /api/v1/subscribers.json?is_active=true
```

**Filter by source and active status:**

```
GET /api/v1/subscribers.json?is_active=true&source=api_subscription
```

**Filter by date range:**

```
GET /api/v1/subscribers.json?created_after=2024-01-01T00:00:00Z&created_before=2024-12-31T23:59:59Z
```

**Filter by email pattern:**

```
GET /api/v1/subscribers.json?email=gmail.com
```

**Filter by tags (subscribers with ALL specified tags):**

```
GET /api/v1/subscribers.json?tags[]=premium&tags[]=newsletter
```

**Filter by custom data:**

```
GET /api/v1/subscribers.json?custom_data[plan]=enterprise
```

**Combined filtering:**

```
GET /api/v1/subscribers.json?is_active=true&source=api_subscription&created_after=2024-01-01T00:00:00Z&tags[]=premium
```

### Response

```json
{
  "subscribers": [
    {
      "id": "123",
      "email": "user@example.com",
      "first_name": "John",
      "last_name": "Doe",
      "ip_address": "192.168.1.1",
      "is_active": true,
      "source": "api_subscription",
      "subscribed_at": "2024-03-20T10:00:00Z",
      "unsubscribed_at": null,
      "confirmed_at": null,
      "confirmation_status": "unconfirmed",
      "created_at": "2024-03-20T10:00:00Z",
      "tags": ["newsletter", "product-updates"],
      "custom_data": { "some_key": "some value" }
    }
  ],
  "pagination": {
    "total": 1500,
    "count": 250,
    "from": 1,
    "to": 250,
    "current": 1,
    "total_pages": 6
  }
}
```

## Find Subscriber

This endpoint can be used to find a subscriber by email address and to return the details stored in your Broadcast database.

```
GET /api/v1/subscribers/find.json
```

### Parameters

- `email` (required): Email address of the subscriber

### Request

```bash
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  https://your-broadcast-domain.com/api/v1/subscribers/find.json?email=user@example.com
```

### Response

```json
{
  "id": "123",
  "email": "user@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "ip_address": "192.168.1.1",
  "is_active": true,
  "source": "api_subscription",
  "subscribed_at": "2024-03-20T10:00:00Z",
  "unsubscribed_at": null,
  "confirmed_at": null,
  "confirmation_status": "unconfirmed",
  "created_at": "2024-03-20T10:00:00Z",
  "tags": ["newsletter", "product-updates"],
  "custom_data": { "some_key": "some value" }
}
```

## Create Subscriber

This endpoint can be used to create a new subscriber.

### Parameters

The following parameters need to be "namespaced" under the `subscriber` key. See the cURL example for an example.

- `email` (required): Email address of the subscriber
- `first_name`: First name of the subscriber
- `last_name`: Last name of the subscriber
- `is_active`: Whether the subscriber is active (default: true)
- `tags`: Array of tags to add to the subscriber
- `custom_data`: JSON object with custom key-value pairs
- `source`: The source of the subscriber (e.g., `opt_in_form`, `api_subscription`, `import`). Defaults to `api_subscription` if not specified.
- `subscribed_at`: The date and time when the subscriber originally subscribed (ISO 8601 format). Useful for migrations to preserve original subscription dates.
- `ip_address`: The IP address of the subscriber. Useful for migrations or when capturing the subscriber's IP from your own system.

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "subscriber": {
      "email": "user@example.com",
      "first_name": "John",
      "last_name": "Doe",
      "tags": ["newsletter", "product-updates"],
      "custom_data": {
        "my_custom_data": "data value"
      }
    }
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers.json
```

**Migration example (preserving original metadata):**

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "subscriber": {
      "email": "user@example.com",
      "first_name": "John",
      "last_name": "Doe",
      "source": "opt_in_form",
      "subscribed_at": "2024-01-15T10:30:00Z",
      "ip_address": "192.168.1.100"
    }
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers.json
```

Note that when adding a `tags` array, you must send an array of strings.

Also note that `is_active` is automatically set to true when you add a subscriber. If the subscriber was previously set as not active, this will be overwritten and the subscriber will be changed to having `is_active` as true. The exception is a create with `unsubscribed_at`, below.

### Response

The response code will be 201 (Created) if the subscriber was created successfully.

If a subscriber already exists in the system (eg. such as if a subscriber is added and is unsubscribed), the response will also be 201. Note that in this case, the system will assume that the subscriber has re-subscribed and will set the unsubscribed_at field as null, unless the request sends `unsubscribed_at`. Any attributes passed along to the API will also be updated at the same time.

If the request is invalid, the response code will be 422 (Unprocessable Entity). The error message will be returned in the response body.

Example of an error response:

```json
{
  "errors": {
    "email": ["has already been taken"]
  }
}
```

### Migrating already-confirmed subscribers (admin API tokens only)

When migrating from another platform, you can carry over a subscriber's existing
confirmation state instead of re-confirming them: pass `confirmed_at` (an ISO 8601
timestamp) inside the `subscriber` object on create. This is accepted **only with
an admin API token**: requests using a regular channel token ignore the field and
return an `unrecognized_parameter` warning explaining the restriction.

```http
POST /api/v1/subscribers?broadcast_channel_id=123

{
  "subscriber": {
    "email": "migrated@example.com",
    "confirmed_at": "2024-06-01T10:00:00Z"
  }
}
```

- An unparseable `confirmed_at` fails the request with `422`: a migration must
  never silently import subscribers as unconfirmed.
- If `double_opt_in` is passed together with `confirmed_at`, the subscriber is
  created as confirmed and no confirmation email is sent; the response carries a
  `parameter_ignored` warning for `double_opt_in`.

### Migrating unsubscribed subscribers

To bring over people who already opted out, send `unsubscribed_at` (an ISO 8601
timestamp) inside the `subscriber` object on create. Any API token can do this.
The subscriber is stored as unsubscribed in the same request: inactive, on the
channel's unsubscribe list, and with an unsubscribe entry in their history. There
is no moment in which they are an active subscriber.

```http
POST /api/v1/subscribers

{
  "subscriber": {
    "email": "opted-out@example.com",
    "unsubscribed_at": "2025-03-14T09:30:00Z"
  }
}
```

- No confirmation email is sent. If `double_opt_in` is passed too, the response
  carries a `parameter_ignored` warning for it.
- A tag in the request does not start a tag-triggered sequence.
- A new subscriber fires only the `subscriber.created` webhook, not
  `subscriber.unsubscribed`.
- The request fails with `422` when `unsubscribed_at` is not a timestamp, is in
  the future, or comes with `"is_active": true`.
- `unsubscribed_at` is accepted on create only. To unsubscribe an existing
  subscriber, use the unsubscribe endpoint.

## Create Subscriber with Double Opt-In

Create a subscriber that requires email confirmation before becoming active. The subscriber is created in an unconfirmed state and a confirmation email is sent using your channel's default confirmation template.

### Parameters

- `double_opt_in` (required): Set to `true` to enable double opt-in. Can also be an object with options (see below).
- `confirmation_template_id` (optional): ID of a confirmation template whose email body is sent and whose page copy (heading and body, customizable per page state) drives the [confirmation page](https://sendbroadcast.net/docs/confirmation-pages). Can also be passed inside the `double_opt_in` object. If not provided, the channel's default confirmation template is used.

> **Note:** If `confirmation_template_id` is not provided **and** the channel has no default confirmation template, the API responds with `422 Unprocessable Content` and the error message `"No default confirmation template configured for this channel. Create one under Templates > Confirmation, or pass confirmation_template_id."`

All standard subscriber parameters (`email`, `first_name`, `last_name`, `tags`, etc.) are also accepted.

#### Extended `double_opt_in` options

Instead of passing `true`, you can pass an object to customize the confirmation email:

- `reply_to` (optional): Reply-to email address for the confirmation email
- `confirmation_template_id` (optional): ID of a confirmation template whose email body is sent and whose page copy drives the [confirmation page](https://sendbroadcast.net/docs/confirmation-pages)
- `include_unsubscribe_link` (optional, boolean): Whether to include the unsubscribe link and footer in the confirmation email. Default: `true`. Set to `false` to suppress the unsubscribe link, email footer, and List-Unsubscribe header.

```json
{
  "double_opt_in": {
    "reply_to": "support@example.com",
    "confirmation_template_id": 456,
    "include_unsubscribe_link": false
  }
}
```

Both forms are accepted: `"double_opt_in": true` and `"double_opt_in": { ... }`. The `confirmation_template_id` can be passed either as a top-level parameter or inside the `double_opt_in` object.

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "subscriber": {
      "email": "user@example.com",
      "first_name": "John",
      "last_name": "Doe"
    },
    "double_opt_in": true
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers.json
```

### Response

```json
{
  "id": 123,
  "email": "user@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "confirmed_at": null,
  "is_active": true,
  "confirmation_status": "pending",
  "confirmation_url": "https://your-broadcast-domain.com/confirm/abc123token"
}
```

The response includes `confirmation_status` and `confirmation_url`. The subscriber's `confirmed_at` will be `null` until they click the confirmation link.

### Behavior

- **New subscriber**: Created with `confirmed_at` set to null. A confirmation email is sent.
- **Existing confirmed subscriber**: The `double_opt_in` parameter is ignored. The subscriber is returned as-is.
- **Existing unconfirmed subscriber**: A new confirmation is created and a fresh confirmation email is sent.

### Using a specific confirmation template

**Nested form (preferred):**

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "subscriber": {
      "email": "user@example.com"
    },
    "double_opt_in": { "confirmation_template_id": 456 }
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers.json
```

**Top-level form (also supported):**

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "subscriber": {
      "email": "user@example.com"
    },
    "double_opt_in": true,
    "confirmation_template_id": 456
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers.json
```

The template must be a confirmation template (not a general template) and must belong to the same channel. See [Email Templates](https://sendbroadcast.net/docs/templates) for more on managing confirmation templates.

## Update Subscriber

This endpoint can be used to update a subscriber's details.

### Parameters

- `email` (required): The email address of the subscriber you want to update. This is used to identify the subscriber record.
- `subscriber` (required): An object containing the fields you want to update.

The following fields can be updated inside the `subscriber` object:

- `email`: New email address (only if you want to change it)
- `first_name`: First name of the subscriber
- `last_name`: Last name of the subscriber
- `is_active`: Whether the subscriber is active
- `tags`: Array of tags (replaces existing tags)
- `custom_data`: JSON object with custom key-value pairs
- `source`: The source of the subscriber (e.g., `opt_in_form`, `api_subscription`, `import`)
- `subscribed_at`: The original subscription date (ISO 8601 format)
- `ip_address`: The IP address of the subscriber

- `custom_data_mode` (optional, top level): `replace` (default) stores `custom_data` exactly as sent, so keys you leave out are removed. `merge` changes only the keys you send and keeps the rest; a `null` value deletes that key. Use `merge` to change one [Subscriber Topics](https://sendbroadcast.net/docs/subscriber-topics) value without resending the whole object.

### Request Examples

**Updating subscriber details (most common):**

```bash
curl -X PATCH \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com",
    "subscriber": {
      "first_name": "Jane",
      "last_name": "Smith"
    }
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers.json
```

**Changing a subscriber's email address:**

When changing the email address, use the top-level `email` to identify the subscriber and `subscriber.email` for the new email:

```bash
curl -X PATCH \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com",
    "subscriber": {
      "email": "newemail@example.com"
    }
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers.json
```

**Changing one topic value and keeping the rest of custom_data:**

```bash
curl -X PATCH \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com",
    "custom_data_mode": "merge",
    "subscriber": {
      "custom_data": { "sub_offers": false, "old_field": null }
    }
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers.json
```

### Important Notes

- The top-level `email` parameter is always required to identify which subscriber to update.
- The `subscriber.email` field is only needed if you want to change the subscriber's email address.
- This endpoint does not follow typical RESTful conventions (e.g., `/subscribers/:id`). Instead, the subscriber is identified by their email address in the request body.

### Response

The response code will be 200 (OK) and will return the subscriber JSON object.

If the request is invalid, the response code will be 422 (Unprocessable Entity). The error message will be returned in the response body.

## Deactivate Subscriber

You can deactivate a subscriber using the following endpoint:

```
POST /api/v1/subscribers/deactivate.json
```

### Parameters

- `email` (required): Email address of the subscriber to deactivate

The parameter can be either passed directly or namespaced under the `subscriber` key. See the cURL example for an example.

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com"
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers/deactivate.json
```

### Response

The response code will be 200 (OK) if the subscriber was successfully deactivated.

## Activate Subscriber

This endpoint allows you to reactivate a previously deactivated subscriber.

```
POST /api/v1/subscribers/activate.json
```

### Parameters

- `email` (required): Email address of the subscriber to activate

The parameter can be either passed directly or namespaced under the `subscriber` key. See the cURL example for an example.

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com"
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers/activate.json
```

### Response

The response code will be 200 (OK) if the subscriber was successfully activated.

## Add Tags To Subscriber

This endpoint allows you to add one or more tags to a subscriber.

```
POST /api/v1/subscribers/add_tag.json
```

### Parameters

- `email` (required): Email address of the subscriber
- `tags` (required): An array of tags to add to the subscriber

The parameter can be either passed directly or namespaced under the `subscriber` key. See the cURL example for an example.

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com",
    "tags": ["newsletter", "product-updates"]
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers/add_tag.json
```

### Response

The response code will be 200 (OK) if the tags were successfully added.

## Remove Tags From Subscriber

This endpoint allows you to remove one or more tags from a subscriber.

```
DELETE /api/v1/subscribers/remove_tag.json
```

### Parameters

- `email` (required): Email address of the subscriber
- `tags` (required): An array of tags to remove from the subscriber

The parameter can be either passed directly or namespaced under the `subscriber` key. See the cURL example for an example.

### Request

```bash
curl -X DELETE \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com",
    "tags": ["newsletter"]
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers/remove_tag.json
```

### Response

The response code will be 200 (OK) if the tags were successfully removed.

## Unsubscribe Subscriber

This endpoint allows you to unsubscribe a subscriber from your list. This sets the `unsubscribed_at` timestamp and marks the subscriber as inactive (`is_active: false`).

```
POST /api/v1/subscribers/unsubscribe.json
```

### Parameters

- `email` (required): Email address of the subscriber to unsubscribe

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com"
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers/unsubscribe.json
```

### Response

The response code will be 200 (OK) if the subscriber was successfully unsubscribed. The response includes the updated subscriber object with the `unsubscribed_at` timestamp set.

```json
{
  "id": "123",
  "email": "user@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "ip_address": "192.168.1.1",
  "is_active": false,
  "source": "api_subscription",
  "subscribed_at": "2024-03-20T10:00:00Z",
  "unsubscribed_at": "2024-03-25T15:30:00Z",
  "confirmed_at": null,
  "confirmation_status": "unconfirmed",
  "created_at": "2024-03-20T10:00:00Z",
  "tags": ["newsletter", "product-updates"],
  "custom_data": { "some_key": "some value" }
}
```

## Resubscribe Subscriber

This endpoint allows you to resubscribe a previously unsubscribed subscriber. This clears the `unsubscribed_at` timestamp and marks the subscriber as active (`is_active: true`).

```
POST /api/v1/subscribers/resubscribe.json
```

### Parameters

- `email` (required): Email address of the subscriber to resubscribe

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com"
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers/resubscribe.json
```

### Response

The response code will be 200 (OK) if the subscriber was successfully resubscribed. The response includes the updated subscriber object with the `unsubscribed_at` field set to null.

```json
{
  "id": "123",
  "email": "user@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "ip_address": "192.168.1.1",
  "is_active": true,
  "source": "api_subscription",
  "subscribed_at": "2024-03-20T10:00:00Z",
  "unsubscribed_at": null,
  "confirmed_at": null,
  "confirmation_status": "unconfirmed",
  "created_at": "2024-03-20T10:00:00Z",
  "tags": ["newsletter", "product-updates"],
  "custom_data": { "some_key": "some value" }
}
```

### Important Notes

- **Dual Field Management**:
  - **Unsubscribe** sets `unsubscribed_at` timestamp AND marks subscriber as inactive (`is_active: false`)
  - **Resubscribe** clears `unsubscribed_at` (sets to `null`) AND marks subscriber as active (`is_active: true`)
- **Difference from Activate/Deactivate**: The unsubscribe/resubscribe endpoints manage both subscription status (`unsubscribed_at` field) and activity status (`is_active` field), while activate/deactivate endpoints only manage the activity status (`is_active` field).

  **When to use Unsubscribe/Resubscribe:**
  - Subscriber formally opts out of all communications (legal unsubscribe)
  - Compliance with anti-spam regulations (CAN-SPAM, GDPR, etc.)
  - Permanent removal from mailing lists
  - User clicks "unsubscribe" link in emails

  **When to use Activate/Deactivate:**
  - Temporary pause of communications (subscriber vacation, busy period)
  - System-level deactivation (bounced emails, complaints, fraud detection)
  - Subscriber wants to pause but maintain their subscription status
  - Administrative actions that don't constitute formal unsubscription
  - A/B testing scenarios where you temporarily exclude certain users
- **Webhook Events**: Both endpoints trigger appropriate webhook events (`subscriber.unsubscribed` and `subscriber.resubscribed`) if you have webhooks configured.
- **Subscriber History**: Both actions are logged in the subscriber's history for audit purposes.
- **Idempotent Operations**: These endpoints are safe to call multiple times - unsubscribing an already unsubscribed subscriber or resubscribing an already subscribed subscriber will not cause errors.

## Redact Subscriber

This endpoint allows you to permanently redact a subscriber's personally identifiable information (PII) while preserving campaign statistics. This is typically used for GDPR compliance or data privacy requirements.

**⚠️ Warning: This action is irreversible. Once a subscriber is redacted, their personal data cannot be recovered.**

```
POST /api/v1/subscribers/redact.json
```

### What Gets Redacted

When a subscriber is redacted, the following information is permanently removed or anonymized:

- **Email address**: Replaced with an anonymized identifier (`redacted-{id}@privacy-compliant.local`)
- **First and last names**: Set to `null`
- **Custom data fields**: Cleared completely
- **IP addresses**: Removed
- **Preferences**: Cleared

### What Gets Preserved

The following data is preserved to maintain campaign analytics and statistical integrity:

- **Campaign statistics and metrics**: Open rates, click rates, delivery statistics
- **Sequence performance data**: Automation engagement metrics
- **Subscriber ID and timestamps**: For referential integrity in reports
- **Aggregate reporting data**: Overall campaign performance remains accurate

### Parameters

- `email` (required): Email address of the subscriber to redact

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "email": "user@example.com"
  }' \
  https://your-broadcast-domain.com/api/v1/subscribers/redact.json
```

### Response

#### Success Response (200 OK)

```json
{
  "message": "Subscriber successfully redacted"
}
```

#### Error Response (422 Unprocessable Entity)

```json
{
  "error": "Failed to redact subscriber: [error details]"
}
```

#### Not Found Response (404 Not Found)

```json
{
  "error": "Subscriber not found"
}
```

### Important Considerations

- **Irreversible Action**: Once redacted, subscriber data cannot be restored
- **Campaign Statistics**: All historical email metrics remain intact for reporting
- **Compliance**: Ideal for GDPR "right to be forgotten" requests
- **Database Integrity**: The system maintains referential integrity across all related records
- **Audit Trail**: The redaction action is logged for compliance purposes
- **Gone from the API**: A redacted subscriber is never returned again. Listing leaves it out, finding, updating or redacting it by its placeholder email returns `404 Not Found`, and creating a subscriber with the placeholder email returns `422 Unprocessable Entity` instead of reopening the erased record
- **Write Permission Required**: Requires an API token with write permissions

### Common Use Cases

- **GDPR Compliance**: Responding to "right to be forgotten" requests
- **Data Minimization**: Regularly cleaning PII while preserving analytics
- **Privacy Compliance**: Meeting regulatory requirements for data retention
- **Customer Requests**: Honoring explicit data deletion requests
