Browse the docs

SendQL

Consent and membership

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

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

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, 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.