# Bulk Remove Campaign Leads

> Remove many leads from a campaign that is not active.

Requires an API key with the `write` scope.

Removes up to 5,000 leads from the campaign in one call and cancels their pending sends. The leads stay in your lead list. Ids that are not in the campaign are ignored. The campaign must not be `active`: pause it first. The request runs inside the call; send larger lists in batches.


## Path Parameters

<ParamField path="campaign_id" type="string" required>The campaign.</ParamField>

## Request Body

<ParamField body="leadIds" type="string[]" required>1 to 5,000 lead ids.</ParamField>

## Response

<ResponseField name="data" type="object">
  <Expandable title="Result">
    <ResponseField name="removed" type="integer">How many leads were in the campaign and are now removed.</ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
```bash cURL
curl -X POST "https://api.foxreach.io/api/v1/campaigns/cmcamp1/leads/bulk-remove" \
  -H "X-API-Key: otr_your_key" \
  -H "Content-Type: application/json" \
  -d '{"leadIds": ["cmlead1", "cmlead2"]}'
```

```python Python SDK
from foxreach import FoxReach

client = FoxReach(api_key="otr_your_key")
result = client.campaigns.bulk_remove_leads("cmcamp1", ["cmlead1", "cmlead2"])
```

```typescript TypeScript SDK
import { FoxReach } from "foxreach";

const client = new FoxReach({ apiKey: "otr_your_key" });
const result = await client.campaigns.bulkRemoveLeads("cmcamp1", ["cmlead1", "cmlead2"]);
```
</RequestExample>

<ResponseExample>
```json
{
  "data": { "removed": 2 }
}
```
</ResponseExample>

## Errors

| Status | Description |
|--------|-------------|
| `401` | Missing, invalid, revoked or expired API key |
| `403` | API key does not have the required scope: `write` |
| `400` | The campaign is active |
| `404` | Campaign not found in this workspace |
| `422` | Empty list or more than 5,000 ids |

## Rate Limit

- **100 requests per minute, shared by every `bulk` call in your workspace.** Fixed 60-second window.
- Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (unix epoch seconds) and `X-RateLimit-Bucket` (`bulk`).
- A `429` response includes a `Retry-After` header (seconds until the bucket resets).

For client-side patterns (`Retry-After`, exponential backoff, monitoring `X-RateLimit-Remaining`), see [Rate Limiting](/rate-limiting).
