# Consent and membership

> Subscriptions, opt-outs, suppression, and testing membership of a list or another segment.

Source: https://www.sendlang.com/docs/sendql/consent
Section: SendQL

Deliverability rules are not a separate system bolted onto SendQL. They are terms
in the language, and they read like English.

## Consent

Four forms, covering the four questions worth asking:

```sendql
subscribed to "product-updates"
```

```sendql
opted out of "promos"
```

```sendql
unsubscribed from all
```

```sendql
suppressed
```

A **topic** is a consent grouping — a subscription a contact can opt into or out
of independently of every other. `subscribed to "marketing"` and `opted out of
"marketing"` are not quite negations of each other: the first asks about a
positive opt-in, the second about an explicit opt-out, and a contact who has done
neither is in neither set.

`unsubscribed from all` is the global opt-out — the "unsubscribe from everything"
link, not a per-topic preference.

**`suppressed` is different in kind**, and it is the one to understand. A
suppressed contact is one you *cannot* mail: a hard bounce, a spam complaint, a
manual block. It is not a preference, it is a deliverability fact, and ignoring
it is how a sender damages its reputation.

Which is why almost every segment you write should end the same way:

```sendql
attr.plan = "trial" and not suppressed
```

Get in the habit. `not suppressed` costs six characters.

## Membership

Two forms, both taking a quoted key:

```sendql
in list "beta-testers"
```

```sendql
in segment "power-users"
```

A **list** is a named bag of contacts — something you add people to, by hand or
from a workflow (`add to list "engaged"`).

A **segment** is a saved SendQL query. `in segment "power-users"` composes one
segment into another, which is how you keep a complicated definition in one place
instead of copy-pasting a predicate into nine campaigns:

```sendql
in segment "power-users" and not exists(activity.login within 30d)
```

Both compose with `not`:

```sendql
in list "beta-testers" and not in segment "power-users"
```

## They are strings, so they can be anything

Topics, lists and segments are all **quoted strings**, never bare identifiers.
That is a deliberate design decision with a pleasant consequence: their names are
not constrained by the language's grammar at all.

```sendql
subscribed to "timeout" and in list "count"
```

Both of those names are [reserved words](/docs/reference/reserved-words), and
both are perfectly fine, because a quoted string can never be confused with a
keyword. Hyphens, spaces and punctuation are equally unproblematic —
`"product-updates"` needs no escaping or special handling.

## A realistic deliverability preamble

Putting the consent terms together with the rest of the language, a
production-grade marketing segment usually looks something like this:

```sendql
// Reachable, engaged, opted-in — and demonstrably not a lost cause.
subscribed to "marketing"
  and not suppressed
  and not unsubscribed from all
  and count(bounce within 90d) = 0
  and count(complaint) = 0
  and count(open within 60d) >= 1
```

The last three lines are worth stealing. Filtering out recent bouncers and anyone
who has *ever* complained, and requiring a single open in two months, is most of
what list hygiene actually is — and here it is just five more terms in the same
expression, checked by the same type checker as everything else.
