A contact group is the only thing Leed will address an email to. Everything else you can slice your contacts by — a segment token in Engage, a filter you typed into All Contacts, the results of a CSV import — is a view. Views are for reading. A group is a saved object with an id, and the composer’s Recipient Group field lists groups and nothing else.
What a group stores
A group holds four things: a name, an optional description, a list of filters, and a list of upload batches. That is all. It does not hold contacts.
Membership is resolved live, on every read. When the composer previews recipients, when a send fans out, when Engage shows you the group as a segment — each of those runs the same query against your contacts using the group’s stored criteria. The practical consequence is the useful one: a group is a rule, not a snapshot. A contact captured tomorrow who matches the filters is in tomorrow’s send, with no action from you. It also cuts the other way — a contact whose title changes out of range silently leaves the group.
The groups themselves are stored under a contact-group: key per workspace, which is why they survive independently of the contacts they describe: deleting every contact leaves the group intact and empty.
Building a group
From Engage
Open Engage → Contact Filters and choose New contact group. The inline form asks for a Name (required) and a Description, then gives you the full filter builder under Membership filters. The right rail previews members live as you edit, showing the matching count and a sample of the people in it.
The preview is the same resolution the saved group will use, including the case the form’s own copy would otherwise hide: leave every filter blank and the group matches every contact. That is occasionally what you want and is more often an accident, so read the count before you save.
From the legacy Email Marketing screen
The older surface still works and is where most existing groups were built. Go to /emails and pick the Groups tab for the list plus a New Contact Group control, or filter the All Contacts tab and save your current filters as a group in one step. /emails is reachable only by typing the URL — it is not in the tab rail — and it is listed alongside the other survivors in legacy URLs that still work.
Both surfaces drive the same filter builder and write the same object. Use whichever you are already in.
Filters
Nine fields can be filtered on. Six of them are offered by the visual builder; three exist in the schema and resolve correctly but can only be set through the API.
| Filter | Stored field | Type | Operators | Matches | In the filter builder? |
|---|---|---|---|---|---|
| Emails | email | String | LIKE %value% | Any part of the email address — .com, @acme, a full address | Yes |
| Titles | title | String | LIKE %value% | Any part of the job title | Yes |
| Companies | company_name | String | LIKE %value% | Any part of the company name | Yes |
| Competitive Products | competitive_products | String | LIKE %value% | Any part of the competitive-products field on the contact’s company | Yes |
| Company Size | company_size | Number | = > >= < <= | Headcount recorded on the company | Yes |
| Company Revenue | company_revenue | Number | = > >= < <= | Revenue recorded on the company | Yes |
| — | company_sic_codes | String | LIKE %value% | Any part of the SIC codes on the company | API only |
| — | company_industry | String | LIKE %value% | Any part of the industry on the company | API only |
| — | current_customer | Boolean | exact match | Whether the company is flagged as a current customer | API only |
| Uploads | (not a filter) | Batch list | intersection | Membership of a named CSV import — see below | Yes |
String matching is always a substring match and is case-insensitive in the way SQLite’s LIKE is; there is no “starts with”, no “equals” and no wildcard of your own. A number filter left at zero is treated as unset and dropped, so you cannot filter for exactly zero employees. An empty string filter is likewise ignored, which is why the builder can emit all six filter objects at once without them doing anything.
Every filter is ANDed
Upload batches narrow, they do not widen
The Uploads selector is not a filter. Each entry restricts membership to contacts that appear in that named import — and selecting two entries restricts membership to contacts that appear in both, which for two separate imports is normally nobody.
To mail two imports, select one batch and send, then the other. To mail them as one audience, drop the Uploads selector entirely and build the group on a field the two imports share. A CSV import becomes a selectable batch automatically; importing contacts covers column mapping, duplicates and what a re-import does to existing values.
Groups versus Engage segments
Engage’s Contact Filters section offers a row of segment tokens. Only one of them is a mailable object.
| Thing | Where it appears | Saved? | Can receive an email? | Member limit |
|---|---|---|---|---|
| All contacts | Engage segment token | No — a built-in view | No | The screen paginates |
| Hot leads | Engage segment token | No — computed from scores | No | 1,000 shown |
| Stalled | Engage segment token | No — computed from scores | No | 1,000 shown |
| A persona | Engage segment token | The persona is saved; the view is not | No | 1,000 shown |
| A committee role | Engage segment token | No — computed | No | 1,000 shown |
| A contact group | Engage segment token and the composer’s Recipient Group | Yes | Yes | 1,000 shown in Engage; no limit on a send |
| An upload batch | A selectable input to a group | Yes, as a batch | Only through a group that selects it | none |
The 1,000 is worth reading carefully, because it applies to the view and not to the group. When Engage renders a contact group as a segment it resolves at most 1,000 members, so a group of 4,000 shows you a thousand of them. A send addressed to that same group resolves all 4,000. If a group looks capped in Engage and uncapped in the composer, both numbers are correct.
Where Hot and Stalled come from, and what a persona is scored on, is in engage scores. The rest of the Contact Filters surface is described in Engage workspace.
Who is actually in a group
Two different subtractions apply, at two different moments, and confusing them is the most common source of “my audience is smaller than I expected”.
Locked contacts are excluded from membership. Your plan sets how many contacts your workspace can see; the visible window is the oldest contacts you captured, up to that number. Anything past it is locked — not deleted, not hidden from your bill, just unreadable and unmailable through every route. Locked contacts are excluded from the group’s members and from its count. The API returns both numbers — the visible count and the true match count — which is how the CMS can tell you how many are locked rather than silently shrinking your audience. Usage and limits explains the window and why the oldest survive rather than the newest.
Opted-out and hard-bounced contacts stay in the group. They match the filters, so they are members, and they are counted in the Recipient Preview. They are removed at send time instead — first when the batch is created, then again per recipient. This is why the Recipients number in Sent Emails can be lower than the number the composer previewed, and it is working as intended: the group describes an audience, and consent is applied to the send.
flowchart TD A["Every contact you have captured"] --> B["Visible window<br/>oldest N, where N is your plan's contact quota"] B --> C["Filters, ANDed<br/>including every value inside one filter"] C --> D["Upload batches, intersected<br/>a contact must be in all selected batches"] D --> E[["Group members<br/>this is the Recipient Preview number"]] E --> F["Drop do-not-contact<br/>at the API — 400 if nothing survives"] F --> G["Drop opted-out<br/>at fan-out"] G --> H["Drop hard-bounced<br/>at fan-out"] H --> I[["Recipients<br/>this is the Sent Emails number"]] A -. "locked contacts stop here" .-> Z(["Counted as locked,<br/>never listed, never mailed"])
Six independent narrowings, in that order. When an audience comes out the wrong size, work down the chain rather than re-reading the filters — the answer is usually stage two or stage five.
Editing and deleting
Open a group to preview its current members, adjust its filters, or delete it. Edits take effect immediately and retroactively: because membership resolves live, changing a filter changes who the next send goes to, with no republish step. Sends that already went out are unaffected — they recorded their recipients at fan-out.
Deleting is a soft delete. The group is marked deleted, the deletion is written to the audit trail, and the record is tracked so the change propagates; the contacts themselves are untouched. A group that a past send used stays linked from that row in Sent Emails.
| Action | Privilege | Minimum role |
|---|---|---|
| List and preview groups | contact:read | Read Only |
| Create or edit a group | contact:write | Content Publisher |
| Delete a group | contact:delete | Content Publisher |
That threshold catches people out: a Content Writer who can build a form cannot build an audience. Contact privileges sit one rung higher than page-authoring privileges, and the only way to grant them without promoting someone is the API-only contact override. The full matrix is in the privilege matrix.
Once a group exists, it is the input to a send — sending a marketing email picks up at the composer’s Recipient Group field. The contacts inside it — where they came from, what a record holds, and how to work with one person rather than a list — are covered in contacts, and what happens to somebody who opts out is in unsubscribes and opt-outs.