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

# Remove Recipients

> Take one recipient (or a batch) off a list without erasing their opt-out history

Removal is a soft state. A removed recipient stops getting release emails but keeps their row, so a later [upsert](/api-reference/mailing-lists/upsert-recipients) or add puts them back, and a contact who unsubscribed themselves can never be removed-then-re-added as a way around their opt-out.

Two forms:

* **Single** — `DELETE /email/lists/{list_id}/recipients/{identifier}`, where `identifier` is matched as an email address first (case-insensitive), then as an `external_id`.
* **Batch** — `POST /email/lists/{list_id}/recipients/remove` with `emails` and/or `external_ids`, up to 1000 identifiers.

Both are idempotent.

## Authentication

This endpoint requires an API token passed as a Bearer token in the `Authorization` header.

```bash theme={null}
Authorization: Bearer YOUR_API_TOKEN
```

## Single removal

### Path Parameters

<ParamField path="list_id" type="string" required>
  The mailing list's unique identifier (UUID).
</ParamField>

<ParamField path="identifier" type="string" required>
  An email address or an `external_id`. URL-encode it (`@` is fine as is in most clients).
</ParamField>

### Request

```bash cURL theme={null}
curl -X DELETE "https://api.shipstar.ai/api/v1/email/lists/a1b2c3d4-e5f6-7890-abcd-ef1234567890/recipients/usr_42" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
```

### Response

<ResponseField name="status" type="string" required>
  `removed` (was active), `already_removed`, or `unsubscribed` (left untouched).
</ResponseField>

```json 200 theme={null}
{"status": "removed"}
```

## Batch removal

`POST /email/lists/{list_id}/recipients/remove`

### Body

<ParamField body="emails" type="string[]">Email addresses to remove</ParamField>
<ParamField body="external_ids" type="string[]">External ids to remove</ParamField>

At least one of the two, at most 1000 identifiers in total.

### Request

```bash cURL theme={null}
curl -X POST "https://api.shipstar.ai/api/v1/email/lists/a1b2c3d4-e5f6-7890-abcd-ef1234567890/recipients/remove" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"external_ids": ["usr_42", "usr_43"], "emails": ["old@example.com"]}'
```

### Response

<ResponseField name="removed" type="integer" required>Active recipients now removed</ResponseField>
<ResponseField name="already_removed" type="integer" required>Identifiers that were already removed</ResponseField>
<ResponseField name="skipped_unsubscribed" type="integer" required>Identifiers matching unsubscribed recipients (untouched)</ResponseField>
<ResponseField name="not_found" type="string[]" required>Identifiers that matched nothing on this list</ResponseField>

```json 200 theme={null}
{
  "removed": 2,
  "already_removed": 0,
  "skipped_unsubscribed": 0,
  "not_found": ["old@example.com"]
}
```

## Errors

| Status | Description |
| - | - |
| 401 | Invalid or expired API token |
| 404 | Mailing list not found in the token's project, or (single form) no recipient matches the identifier |
| 422 | Batch body has neither `emails` nor `external_ids`, or more than 1000 identifiers |

## Rate Limits

Both forms are limited to 30 requests per minute per IP.
