---
title: "Add a group suppression"
method: POST
path: "/email_unsubscribe_groups/{id}/suppressions"
tags: ["Email Unsubscribe Groups"]
---

# Add a group suppression

`POST /email_unsubscribe_groups/{id}/suppressions`

Creates a suppression with `reason: unsubscribe`, `source: manual`,
`group_id: <this group>`. All other body fields are ignored; only
`to` is read. Idempotent (same dedupe key → `200`, no new event).

## Request body

- AddGroupSuppressionRequest — Only `to` is read; all other fields are ignored (`reason: unsubscribe`, `source: manual`, `group_id: <group>` are forced).
  - `to` string, required

## Response `200`

Idempotent — already existed.

- EmailBlockResponse
  - `data` EmailBlock, required — Suppression record. Schema fields hidden by the view: `account_id`, `bounce_category`, `dsn_code`, `meta`.
    - `id` string, uuid, required
    - `record_type` 'email_block', required — View-only discriminator.
    - `domain_id` string, uuid, nullable — `null` ⇒ account scope. Stored on the row; exposed here.
    - `group_id` string, uuid, nullable — `null` ⇒ global; set ⇒ group-scoped opt-out.
    - `from` string, nullable — `null` ⇒ not address-scope. (schema: from_address)
    - `to` string, required — Normalized recipient. (schema: to_address)
    - `reason` 'hard_bounce' | 'spam_complaint' | 'unsubscribe' | 'invalid' | 'manual_block', required
    - `source` 'feedback' | 'manual' | 'import' | 'system', required
    - `scope` 'account' | 'domain' | 'address', required — Derived server-side from `domain_id`/`from`; never trusted from the caller.
    - `status` 'active' | 'expired' | 'removed', required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `expires_at` string, date-time, nullable — Optional expiration time. An active row stops matching send-time suppression checks as soon as `expires_at <= now()`. A maintenance worker later transitions the row to `status: expired` and appends an `expired` audit event (normally within 15 minutes).

## Other responses

- `201` — Created.
- `401` — Missing or invalid gateway auth.
- `404` — Resource not found (cross-account lookups and malformed UUIDs also return 404 — no leak).
- `406` — Framework-rendered error (e.g. 406 Not Acceptable, 405 Method Not Allowed, 415 Unsupported Media Type). HTTP status matches the error and the body `code` carries that same status (e.g. `"406"`, not a hardcoded `"500"`). The explicit `500.json` clause still emits `code: "500"` for genuine 500s.
- `422` — Validation error (changeset or internal `Params`). One error object per field, `source.pointer /data/attributes/<field>`.

## Changes

> 93 revisions in range; 1 not diffed.

- **2026-07-07** `6ef0ae248bf7` — 1 info
  - endpoint added
- **2026-07-02** `224ed0d8a5c3` — 1 breaking
  - api path removed without deprecation

[Change history](https://skmtc.dev/team-telnyx/apis/telnyx-api-2/changes/email_unsubscribe_groups/:id/suppressions/post.md)

---

[API](https://skmtc.dev/team-telnyx/apis/telnyx-api-2.md) · [All operations](https://skmtc.dev/team-telnyx/apis/telnyx-api-2/llms.txt) · [OpenAPI document](https://skmtc.dev/team-telnyx/apis/telnyx-api-2/revisions/88481995b4ca?raw)
