---
title: Suppressions Reference
path: reference/suppressions
status: published
---

# Suppressions Reference

Every endpoint for bounces, spam reports, global unsubscribes, and suppression groups. For the guide-level walk-through, see [Suppressions](../tutorials/suppressions); for the conceptual overview, [Suppressions (concept)](../concepts/suppressions).

**Base paths:**
- `/v3/suppression/bounces` — hard/soft bounce list
- `/v3/suppression/spam_reports` — spam complaints
- `/v3/asm/suppressions/global` — global unsubscribes
- `/v3/asm/groups` — suppression groups and their per-group lists

**Required permission:** `suppressions.read` for reads, `suppressions.write` for writes.

## Bounces

### GET /v3/suppression/bounces

List bounces.

**Query parameters:**

| Parameter | Notes |
|-----------|-------|
| `limit` | 1–500 (default 50) |
| `offset` | Pagination offset |
| `start_time` | Unix timestamp |
| `end_time` | Unix timestamp |
| `email` | Filter by specific email |

**Response (200):**

```json
{
  "bounces": [
    {
      "email": "invalid@example.com",
      "created": 1714060800,
      "reason": "550 5.1.1 User unknown",
      "bounce_type": "hard",
      "status": "5.1.1"
    }
  ],
  "total": 152
}
```

### GET /v3/suppression/bounces/{email}

Get a specific bounce record.

**Response (200):** `[BounceResponse]` (may be multiple entries if the address bounced more than once).

**Errors:** 404 if not in the list.

### POST /v3/suppression/bounces

Add a bounce manually.

**Request body:**

| Field | Type | Required | Notes |
|-------|------|---------|-------|
| `email` | string | Yes | |
| `bounce_type` | string | No | `hard` (default), `soft`, `block` |
| `reason` | string | No | Free-form |

**Response (201):** the created record.

### POST /v3/suppression/bounces/import

Bulk import from CSV. Columns: `email`, `reason` (optional).

**Content-Type:** `text/csv`.

**Response (200):**

```json
{
  "imported": 1482,
  "skipped": 12,
  "errors": [
    {"row": 44, "email": "not-an-email", "error": "Invalid email format"}
  ]
}
```

### DELETE /v3/suppression/bounces/{email}

Remove a bounce. Future sends to this address are allowed again.

**Response (204):** no body.

### DELETE /v3/suppression/bounces

Bulk delete.

**Query parameters:**

| Parameter | Required | Notes |
|-----------|---------|-------|
| `delete_all` | Yes | Must be `true` |

**Response (204):** no body.

## Spam reports

Endpoints mirror bounces.

### GET /v3/suppression/spam_reports

| Query | Notes |
|-------|-------|
| `limit`, `offset`, `start_time`, `end_time`, `email` | Same semantics as bounces |

**Response (200):**

```json
{
  "spam_reports": [
    {"email": "abuser@example.com", "created": 1714060800, "source": "feedback_loop"}
  ],
  "total": 20
}
```

### GET /v3/suppression/spam_reports/{email}

Get a specific report.

### POST /v3/suppression/spam_reports

Add manually. Body: `{email, source}`.

### POST /v3/suppression/spam_reports/import

Bulk import. CSV columns: `email`, `source` (optional).

### DELETE /v3/suppression/spam_reports/{email}

Remove a report.

## Global unsubscribes

### GET /v3/asm/suppressions/global

List all addresses globally unsubscribed from this tenant's mail.

**Query parameters:** `limit`, `offset`, `start_time`, `end_time`.

**Response (200):**

```json
{"recipient_emails": ["user@example.com"], "total": 1}
```

### GET /v3/asm/suppressions/global/{email}

Check whether a specific address is globally unsubscribed.

**Response (200):** `{"recipient_email": "user@example.com"}` if yes, `404` if no.

### POST /v3/asm/suppressions/global

Add addresses to the global unsubscribe list.

**Request body:**

```json
{"recipient_emails": ["user@example.com", "other@example.com"]}
```

**Response (201):** `{"recipient_emails": [...]}` — the addresses that were added.

### POST /v3/asm/suppressions/global/import

Bulk import. CSV column: `email`.

### DELETE /v3/asm/suppressions/global/{email}

Remove from global unsubscribe list (re-subscribe).

## Suppression groups

### GET /v3/asm/groups

List all groups.

**Response (200):**

```json
{
  "suppression_groups": [
    {
      "id": 123,
      "name": "Newsletter",
      "description": "Our weekly digest",
      "is_default": false,
      "unsubscribes": 42,
      "created_at": "2026-04-23T10:00:00Z"
    }
  ]
}
```

### POST /v3/asm/groups

Create a group.

**Request body:**

| Field | Type | Required | Notes |
|-------|------|---------|-------|
| `name` | string | Yes | 1–100 chars, unique within tenant |
| `description` | string | No | 0–500 chars |
| `is_default` | boolean | No | If true, used when send specifies no `asm.group_id` |

**Response (201):** the created group.

### GET /v3/asm/groups/{group_id}

Get a single group.

### PATCH /v3/asm/groups/{group_id}

Update a group's fields.

### DELETE /v3/asm/groups/{group_id}

Delete a group and all its suppressions.

**Response (204):** no body.

### GET /v3/asm/groups/{group_id}/suppressions

List addresses suppressed in a group.

**Query parameters:** `page`, `page_size`.

**Response (200):**

```json
{"recipient_emails": ["opted-out@example.com"], "total": 1}
```

### POST /v3/asm/groups/{group_id}/suppressions

Add addresses to a group.

**Request body:**

```json
{"recipient_emails": ["opt-out@example.com"]}
```

**Response (201):** `{"recipient_emails": [...]}`.

### DELETE /v3/asm/groups/{group_id}/suppressions/{email}

Remove from a group (re-subscribe).

**Response (204):** no body.

## Bounce types

| `bounce_type` | Meaning |
|---------------|---------|
| `hard` | Permanent failure (invalid address). Stays suppressed until manually removed. |
| `soft` | Temporary failure (mailbox full). Can be manually removed if the issue resolves. |
| `block` | Sender reputation block (ISP reject). May resolve over time. |

## Related

- [Suppressions (guide)](../tutorials/suppressions)
- [Suppressions (concept)](../concepts/suppressions)
- [Bounce Handling](../concepts/bounce-handling)
- [Feedback Loops](../concepts/feedback-loops)
