Skip to main content

Custom Inboxes

Custom Inboxes let you slice your SendSeven conversation feed into focused groupings — by region, brand, department, customer segment, or any rule you like — and decide which team members see which conversations.

If you have ever opened SendSeven and thought "I just want to see the Augsburg WhatsApp number, not everything else", Custom Inboxes are for you.

What are Custom Inboxes?​

A Custom Inbox is a saved view of your conversations defined by three things:

  1. The channels and email connections it covers (WhatsApp numbers, Instagram accounts, Facebook pages, Telegram bots, live-chat widgets, and the email connections from Settings → Email).
  2. Optional contact rules — tags and/or custom fields a contact must match.
  3. Optional access rules — which users on your team can see this inbox.

When all three are combined, a conversation lands in the inbox automatically as soon as it meets the criteria. Nothing has to be manually filed or routed.

Opt-in feature

Workspaces that have not created any inbox will not see the Inboxes sidebar at all. Everything continues to work exactly as before — a single unified inbox. Custom Inboxes are purely additive.

When should you use them?​

A few scenarios where teams reach for Custom Inboxes:

  • Regional support teams — One inbox per location (Augsburg, Munich, Berlin), each scoped to that location's WhatsApp number. Agents only see conversations for their region.
  • Multi-brand workspaces — One inbox per brand, scoped to that brand's channels. The marketing team handling Brand A never sees messages for Brand B.
  • Departments under one roof — A Sales inbox, a Support inbox, and a Billing inbox, each routed by contact tag. The same WhatsApp number can feed all three; a contact tagged billing lands in the Billing inbox.
  • Per-address email triage — One inbox for everything that lands on support@, another for orders@, another for returns@ — even when all three addresses share the same email connection.
  • Agencies managing clients — One inbox per client account. Account managers only see the inboxes for their clients.
  • VIP segmentation — A "VIP Customers" inbox filtered by a vip tag or by a lifetime_value custom field above a threshold. Senior agents work this inbox first.

If you find yourself relying on filters or searches every morning to find the conversations that matter to you, that is a sign an inbox would save you time.

How an inbox is defined​

Every inbox has a name, its sources (channels and email connections) and optional rules (one tag rule plus up to 20 custom-field and contact-language rules). A conversation must always come from one of the inbox's sources. How the rules combine is up to you:

  • Match all rules (default, rule_match_mode: "all") — the conversation must satisfy every rule (AND).
  • Match any rule (rule_match_mode: "any") — satisfying at least one rule is enough (OR).

The tag rule counts as one rule, whatever its own tag mode, and every custom-field or language rule is one rule. With no rules at all, the inbox simply shows every conversation from its sources.

1. Channels and email connections​

Pick one or more sources the inbox should cover. The picker shows everything connected to your workspace — WhatsApp numbers, Instagram accounts, Facebook pages, Telegram bots, live-chat widgets, and the email connections you have configured under Settings → Email (with the can_receive_support capability).

From the customer's point of view there is no visible distinction between "channel" and "email connection" — they all live in the same picker on the inbox edit page.

A few things worth knowing:

  • The same channel or email connection can belong to multiple inboxes. Your main WhatsApp number can simultaneously feed a "Sales" inbox (filtered by the sales tag) and a "Support" inbox (filtered by the support tag).
  • To cover every channel and email connection, including ones you connect later, turn on All channels (all_channels: true in the API). The channel and email-connection lists are then ignored.
  • With All channels off, only the sources you pick are covered. An inbox with no sources picked shows no conversations.
  • The maximum is 100 sources per inbox.

Allowed recipients on an email connection​

Each email connection can receive on multiple addresses — its primary email_address, any accepted aliases, and (if enabled) a catchall. When you add an email connection to an inbox, you can optionally narrow it down with an Allowed recipients list — the subset of those addresses you want this inbox to actually catch.

  • Leave it empty and the inbox accepts every address the connection can receive on.
  • List specific addresses (like [email protected] or [email protected]) and the inbox only picks up messages sent to those addresses.
  • You can type addresses in manually as free text if you don't yet know the full alias list — for example, while a new alias is being provisioned. Entries are RFC-validated, normalized to lowercase, and deduplicated automatically.

Worked example. A fictional shoe retailer has a single mailbox connection [email protected] that receives mail on [email protected], [email protected], and [email protected]. They want:

  • A "Support" inbox that only sees [email protected] — they list that one address as the Allowed recipient.
  • A "Returns" inbox that only sees [email protected] — they list that address.
  • A general "Email — everything" inbox that catches the rest — they leave the Allowed recipients list empty.

All three inboxes share the same underlying email connection. The Allowed recipients list does the routing.

Threads that change address over time

When a conversation hops between addresses — for example, a customer first emails info@, your agent replies from support@, and the conversation continues on support@ — SendSeven advances the thread to follow your most recently used address. This is what lets an inbox like "All addresses on support@" capture migrated threads automatically. You don't have to do anything; it happens behind the scenes.

2. Contact tag rules (optional)​

Filter conversations by tags. A tag counts when it is on the conversation or on its contact. The tag mode (tag_filter_mode) decides how the listed tags combine inside this one rule:

ModeMeaning
Any (OR)Has at least one of the listed tags
All (AND)Has every listed tag
NoneHas none of the listed tags (exclusion)

Up to 50 tags per inbox. With no tags listed there is no tag rule, whatever the mode.

3. Contact custom-field rules (optional)​

Filter on the contact's custom-field values. Available operators:

OperatorUse it for
equals / not equalsExact-match comparisons (country equals DE)
containsCase-insensitive substring match on text fields (customer_notes contains complaint)
does not contain (not_contains)The opposite of contains: the value does not contain the text. Contacts with no value for the field also match
in listMatch any value from a list (status in [active, trial])
betweenA numeric or date range (shoe_size between 40 and 46)
is set / is not setWhether the field has a value at all

You can add up to 20 custom-field rules per inbox. With Match all rules every extra rule narrows the inbox; with Match any rule every extra rule widens it. is not set matches contacts that have no value for the field (or an empty one).

About the contains operator​

contains is a literal, case-insensitive substring match — useful when you want to catch any custom-field value that mentions a keyword rather than equals it exactly.

Worked example. The shoe retailer keeps a free-text customer_notes custom field on every contact. They create a Review Queue inbox with the rule customer_notes contains "complaint" so any contact whose notes mention a complaint is automatically funnelled to senior support.

  • Searching for box matches a stored value of matchbox (substring match anywhere in the string).
  • Searching for vip matches a stored value of VIP Customer (the match is case-insensitive).

A few constraints to be aware of:

  • contains only makes sense on text-typed custom fields. It is hidden for numeric, date, and boolean fields.
  • not_contains (does not contain) follows the same rules and is the exact inverse: customer_notes not_contains "complaint" matches every contact whose notes do not mention a complaint, including contacts with no notes at all. Combine it with is set under Match all rules if you only want contacts that have a value.
  • Both need a non-empty value; an empty or missing value returns 422 (operator 'not_contains' requires a non-empty string value).
  • The match is case-insensitive — VIP, vip, and Vip all match the same set of values.
  • It is a literal substring match — not regex, not glob. If you type %, _, *, or ?, they are treated as plain characters in the search string.
  • An empty search string is rejected — otherwise it would match every contact and the inbox would be useless.

Example. A shoe retailer creates an inbox called "Size 40-46 buyers" with:

  • Channels: their main WhatsApp number and Instagram account
  • Tag rule: any of customer, lead
  • Custom-field rule: shoe_size between 40 and 46

Now whenever a contact who matches those criteria sends a message on either channel, the conversation appears in that inbox — automatically and instantly.

Example: one inbox per location, plus the unassigned ones​

A consulting firm runs one shared live-chat widget and keeps the customer's branch in a select custom field Location (Augsburg, Kempten, Deggendorf, …). Each branch gets its own inbox on the live-chat channel. The Augsburg team should also pick up every enquiry whose location has not been set yet, so the Augsburg inbox uses Match any rule with:

  • Location equals Augsburg
  • Location is not set

A conversation lands in Augsburg when the contact's location is Augsburg or empty. Once someone sets the location to Kempten, the conversation moves to the Kempten inbox. The live-chat channel itself is still required in both modes: an Augsburg contact writing on WhatsApp only appears if WhatsApp is also one of the inbox's sources.

{
"name": "Augsburg",
"channel_ids": ["<live-chat channel id>"],
"rule_match_mode": "any",
"field_filters": [
{"custom_field_id": "<Location field id>", "operator": "eq", "value": "Augsburg"},
{"custom_field_id": "<Location field id>", "operator": "is_not_set"}
]
}

4. Contact language rule (optional)​

A field_filters entry can target the contact's language instead of a custom field. Set builtin_field: "language" and leave out custom_field_id (exactly one of the two must be set, otherwise 422). The rule counts as one rule, like a custom-field rule, and combines with the others per rule_match_mode.

OperatorvalueMatches
eq (is)one language codeThe contact's language is this language
ne (is not)one language codeAny other language, and contacts with no language (see below)
in (is one of)list of codes (max 100)Any of the listed languages
not_in (is none of)list of codes (max 100)None of the listed languages, and contacts with no language (see below)
is_set (is identified)omittedThe contact has a language
is_not_set (no language identified)omittedNo language is known for the contact, or the conversation has no contact
  • Codes are ISO language codes such as ar, de or pt-BR (2-3 letters, optional subtags, max 10 characters). They are saved lowercase with - (pt_BR becomes pt-br), and duplicates are removed. An invalid code returns 422.
  • Any listed language counts. A contact's languages are its preferred language plus every code in its languages list. eq / in match when any of them matches; ne / not_in match when none of them does; is_set means at least one is known; "no language" means both are empty. Codes are compared as whole entries: tr never matches str or tre.
  • Regional variants. A code without a region also matches its regional variants: ar matches ar, ar-SA and ar-EG. A code with a region matches only that region: pt-br does not match pt.
  • include_unidentified (boolean, default false) adds No language identified to the selected values. Language detection is not perfect, so this lets one rule say "Arabic or unknown": {"operator": "in", "value": ["ar"], "include_unidentified": true}. Because the "or" lives inside the rule, it still works under Match all rules next to other rules. With include_unidentified: true, in / not_in may have an empty list (in [] = only contacts without a language).
  • Negative operators. ne and not_in are the exact opposite of eq / in: "is not Arabic" also matches contacts without a language, unless you also set include_unidentified: true ("is not Arabic and not unknown").
  • include_unidentified is ignored for is_set / is_not_set and always returned as false for custom-field rules. not_in and include_unidentified: true are rejected (422) on custom-field rules; contains, not_contains and between are rejected on language rules.

Example: Arabic speakers on the Augsburg team, including contacts whose language is unknown.

{
"name": "Augsburg Arabic",
"channel_ids": ["<live-chat channel id>"],
"rule_match_mode": "all",
"field_filters": [
{"builtin_field": "language", "operator": "in", "value": ["ar"], "include_unidentified": true},
{"custom_field_id": "<Location field id>", "operator": "eq", "value": "Augsburg"}
]
}

A conversation appears when the contact is in Augsburg and speaks Arabic (any region) or has no language yet. Responses return every field_filters entry with custom_field_id, builtin_field and include_unidentified.

Filters are evaluated dynamically

There is no manual "move to inbox" step. A conversation appears in an inbox the moment the contact matches the filters, and disappears if the contact stops matching (for example, you remove a tag). This makes inboxes self-maintaining.

Access control — two independent axes​

This is the part most admins ask about, so it is worth slowing down for. SendSeven combines two completely independent toggles to decide whether a user sees an inbox and what they see inside it.

The two axes are:

  1. Inbox access mode — set per inbox. Is this inbox visible to all team members, or only to a specific list of users?
  2. Contact history visibility — set per user in team-member settings. When looking at a contact, does this user see all conversations across the workspace, or only the conversations from inboxes they have access to?

These two settings are independent. A user who is restricted on the contact-history axis can still be granted broad inbox access on the inbox axis, and vice versa.

Axis 1 — Inbox access mode​

Set when you create or edit an inbox.

  • All team members (default) — The inbox is public. Any team member with the right user-level setting can see it.
  • Specific users — The inbox is private. Only the users on this list can ever see it, even if their user-level setting is "All inboxes".

A private inbox can also be opened to team members holding a tag (for example everyone tagged billing). Members with any of the inbox's access tags see it in addition to the users on the list. See Skill-Based Routing.

Use Specific users for sensitive inboxes — VIP customers, executive escalations, legal — where you do not want every agent to even know the inbox exists.

Axis 2 — Contact visibility​

Set per team member in Settings → Team → user → Inbox access (API field contact_history_visibility). Three levels, from widest to narrowest:

LevelValueContacts the member seesConversation history on a contact
1all (default)Every contactEvery conversation
2accessible_onlyEvery contactOnly conversations from inboxes they can access, plus conversations assigned to them
3reachable_onlyOnly contacts they can reach (see below)Same as level 2

A contact is reachable for a level-3 member when at least one of these is true:

  • it matches the contact rules (contact tags, contact custom fields, contact language) of one of the member's accessible inboxes, combined with that inbox's rule_match_mode. Channels and conversation tags are ignored here;
  • the member is the contact's owner;
  • a conversation with the contact is assigned to the member;
  • the member is the active substitute of an absent colleague who reaches the contact directly (one level: the colleague's own substitutions don't pass on).

Level 3 hides nothing when any inbox the member can access has no contact rules (a channel-only inbox covers every contact), when the workspace has no custom inboxes, or on plans without custom inboxes (the stored level then applies again after an upgrade). GET /users/{user_id}/inbox-access lists those inboxes in rule_less_inbox_names.

Switching a member to Restricted inbox access without sending a level stores accessible_only; an explicit level always wins. Owners, Admins and workspace API tokens bypass every level. OAuth calls made on behalf of a member, including the MCP server connected by signing in, follow that member's level; the MCP server connected with an API key sees all contacts, like any API token.

This is independent of the inbox access mode. For example:

  • A team lead on All inboxes with level 2 sees every inbox in the live queue, but the contact view stays focused on their day-to-day channels.
  • A regional agent on Restricted with level 3 and an inbox rule "tag = Augsburg" only finds Augsburg contacts in the contact list, search, exports and pickers.

Level 2 and 3 also filter email reply history on the contact view.

See Contact visibility in the API for the exact behaviour of each endpoint.

Effective access — the truth table​

Inbox access modeUser-level inbox accessIs user listed on inbox?Can user see the inbox?
All team members (public)All inboxes—Yes
All team members (public)All inboxesListedYes
All team members (public)RestrictedListedYes
All team members (public)RestrictedNot listedNo
Specific users (private)All inboxesListedYes
Specific users (private)All inboxesNot listedNo
Specific users (private)RestrictedListedYes
Specific users (private)RestrictedNot listedNo
AnyAnyOwner or Admin roleYes (always)
Owner and Admin always see everything

Workspace Owner and Admin roles bypass every inbox restriction — both axes. They will always see every conversation in every inbox and every conversation in every contact's history. If you need to limit someone's visibility, give them a lower role first.

Creating an inbox​

You need the Owner or Admin role to create or edit inboxes.

  1. Go to Settings → Inboxes.
  2. Click Create inbox — this opens a dedicated page at /settings/inboxes/new.
  3. Give the inbox a clear name (Augsburg WhatsApp, VIP Customers, Brand A — Sales, Support@).
  4. On the Channels & Email tab, pick the channels and/or email connections it covers. For any email connection, optionally set its Allowed recipients to narrow down which addresses count.
  5. On the Filters tab, (optional) add tag rules and pick a matching mode.
  6. On the Filters tab, (optional) add custom-field rules — including the new contains operator for text fields.
  7. On the Filters tab, choose Match all rules or Match any rule.
  8. On the Access tab, choose All team members or Specific users and add users if needed.
  9. Click Save.

The inbox appears immediately in the left sidebar (on desktop) or in the inbox picker (on mobile) for anyone who has access. To edit an existing inbox, click it in the list — it opens at /settings/inboxes/:id with the same three tabs.

API fields​

Inboxes are managed under /api/v1/inboxes (GET needs conversations:read; POST, PATCH and PUT /inboxes/{id}/users need inboxes:create / inboxes:update; DELETE needs inboxes:delete).

FieldTypeNotes
namestringRequired. Max 255 characters.
access_modestringall (all team members) or specific (private).
all_channelsbooleanDefault false. true covers every channel and email connection; channel_ids and email_connections are ignored. false with no sources listed = the inbox shows nothing.
channel_idsstring[]Channels covered. Max 100 sources.
email_connectionsobject[]Email connections covered, with optional allowed recipients.
tag_idsstring[]Contact/conversation tag filter (max 50), combined with tag_filter_mode.
tag_filter_modestringany, all or none (has none of the tags). How the listed tags combine inside the tag rule.
field_filtersobject[]Custom-field and contact-language rules (max 20 in total). Each entry has custom_field_id or builtin_field ("language"), operator, value and include_unidentified (language rules only). See Contact language rule.
rule_match_modestringall (default) or any. How the tag rule and the field rules (custom-field and language) combine: all = every rule must match, any = at least one. The tag rule counts as one rule. Sources (channel_ids, email_connections, all_channels) are always required. On PATCH, omit it to keep the current value.
allowed_user_idsstring[]Users granted a specific inbox.
access_tag_idsstring[]Max 50. Only used with access_mode: "specific". Team members holding any of these tags see the inbox. Separate from tag_ids. See Skill-Based Routing.

A tag in tag_ids or access_tag_ids that does not belong to your workspace returns 422 ("One or more tag_ids do not belong to this tenant"). Responses always include all_channels, access_tag_ids and rule_match_mode.

Contact visibility in the API​

Everything below applies to calls made as a team member with level reachable_only that actually filters. Admins, Owners, workspace tokens and members on levels all / accessible_only are unaffected.

SurfaceBehaviour
GET /contacts, search, pickers, GET /contacts/duplicates, merge suggestionsOnly visible contacts. Counts and pagination cover visible contacts only.
Any /contacts/{contact_id}/... route, POST /messages with contact_id / contact_method_id, conversation create / check-existing / open-or-create / initiate, scheduled sends, flow starts, GET /notes?contact_id=, POST /lists/{list_id}/members, POST /verifications, POST /contact-tokens, WhatsApp template and WhatsApp Flow sends and previews, campaign and email previews, email content renders, flow node testsA hidden contact gets the same answer as a contact that does not exist (the route's usual 404, or 400 where that route reports an unknown contact as 400). A WhatsApp template preview with a hidden contact_id renders with sample data, exactly as for an unknown id.
Lists of recipients and runs: campaign and email campaign recipients, unsubscribes and preview recipients, list subscription activity, WhatsApp Flow sessions, flow runs, loop pauses, scheduled sendsRows of hidden contacts are left out. Totals stay the true totals.
Searches and ad-hoc audiences: POST /campaigns/preview/recipients and POST /email-campaigns/preview/recipients with search or audience_conditions, POST /lists/evaluate-count, POST /lists/{list_id}/evaluateRows of hidden contacts are left out, but total / count / total_contacts is the true total, so a filter can match a contact you can't see. visible_contact_count (where the response has it) tells how many you can see.
POST /contacts, PUT/PATCH /contacts/{contact_id}, POST/PATCH .../methodsWhen the phone, email or another identifier already belongs to a hidden contact: 409 with {"detail": {"detail": "contact_already_exists", "message": "This contact already exists"}}. No id or name is returned and nothing is written, in every duplicate mode.
Bulk actions (/contacts/bulk-actions/*), bulk deleteHidden ids are skipped like unknown ids; counts cover visible contacts only.
Contact exportExports visible contacts only.
Contact importA row whose identifiers match a hidden contact (even if another identifier matches a contact you can see) fails with code contact_already_exists and the message "This contact already exists". Nothing is created, merged or updated, in every duplicate mode.
Lists and segmentscontact_count stays the true total (campaigns send to everyone on the list). visible_contact_count (on GET /lists, GET /lists/{list_id}, POST /lists/{list_id}/count, POST /lists/evaluate-count) tells how many the caller can see; it is null when nothing is hidden. Member lists (GET /lists/{list_id}/contacts, POST /lists/{list_id}/evaluate) return visible contacts only, with total_contacts as the true total.
Campaign sends, outgoing webhooks, dashboard totalsNot filtered.
Inside a conversation you can openNot filtered. The conversation, its messages, real-time events and the transcript export show the contact's name, phone, email and channel IDs, even when the contact itself is hidden from you. The contact page, contact list and search still treat it as not found.
Workspace API tokensNot filtered: a token sees every contact, whoever created it (details). OAuth apps and the MCP server connected by signing in follow the authorizing member's level; the MCP server connected with an API key is an API token and sees all contacts.
Mention and other notifications to a memberNot sent when the member can't see the contact.

Setting a member's level​

GET /api/v1/users/{user_id}/inbox-access (scope team:read) and PUT (scope team:update) carry mode, inbox_ids and contact_history_visibility (all, accessible_only, reachable_only; any other value returns 422). Leave contact_history_visibility out of a PUT to keep the stored level. Responses also include rule_less_inbox_names: the member's accessible inboxes without contact rules. While that list is not empty, reachable_only hides nothing for this member. Invitations take the same field in member_settings.

Your own level​

GET /api/v1/users/me/contact-visibility (scope contacts:read):

{"level": "reachable_only", "limited": true}

level is the effective level (all for Owners, Admins and workspace API tokens; an OAuth app or the MCP server connected by signing in reports the authorizing member's level; the MCP server connected with an API key reports all). limited is true only when contacts are actually hidden from you.

Check before creating a contact​

POST /api/v1/contacts/visibility-preview (scope contacts:create) tells a limited member whether they will see a contact they are about to create. Nothing is written.

{
"tag_ids": ["tag-uuid"],
"custom_fields": {"store": "Augsburg"},
"phone": "+4982112345",
"owner_user_id": "my-user-id"
}

Response: {"visible": false}. All fields are optional. custom_fields takes field ids or field keys. The language is the one POST /contacts would store: language / languages when you send them, otherwise inferred from phone; with none of them the contact counts as "language unknown". Setting owner_user_id to your own user id always makes the contact visible to you, and POST /contacts accepts that from any member. Assignment and substitution don't count for a contact that doesn't exist yet. Callers who see every contact always get {"visible": true}.

When you create a contact you won't see​

If you create the contact anyway, it is saved, but from then on it behaves like any other hidden contact: GET /contacts/{contact_id}, GET /contacts/{contact_id}/available-channels and POST /conversations/open-or-create (and the other conversation start routes) all return 404 Contact not found. There is no exception for the member who created it, and open-or-create does not assign the new conversation to you, so starting a conversation does not make the contact reachable either.

To keep working with the contact, set owner_user_id to your own user id when you create it (in the app: Set me as owner). Otherwise an Admin can make you the owner or change your visibility level later.

Where the inbox list lives​

Desktop — the Inboxes sidebar​

On the conversations view, the Inboxes sidebar sits on the left side of the screen. A toggle at the top of the rail collapses the sidebar to a narrow icon-only rail to give you more room for the conversation list.

When collapsed, hovering the rail expands it as an overlay so you can pick an inbox without permanently expanding the rail again — there's a 300ms grace period before it retracts so you don't lose it the moment your mouse drifts off.

Mobile — the inbox pill​

On mobile, the conversation-list header shows an inbox pill with the name of the currently selected inbox. Tapping it opens a bottom-sheet drawer with the same inbox list as the desktop sidebar.

The current inbox is remembered​

Your most recently selected inbox is persisted in your browser (localStorage) and re-applied the next time you open SendSeven — so you don't have to re-pick your inbox every morning. A ?inbox_id=… query parameter in the URL always wins over the remembered value, which makes deep links from emails, dashboards, or bookmarks work predictably.

Managing user access​

There are two ways to manage which user sees which inbox. They do the same thing in the end — pick whichever is faster for the change you are making.

Route A — From the inbox​

Best when you want to grant one or two extra users access to a specific (often private) inbox.

  1. Open Settings → Inboxes.
  2. Click the inbox.
  3. Open the Access tab.
  4. Add the users who should see it.

Route B — From the team member​

Best when you want to restrict a single agent to a curated set of inboxes (for example, a regional agent who should only see two inboxes).

  1. Open Settings → Team.
  2. Click the team member.
  3. Open the Inbox access screen.
  4. Switch the user from All inboxes to Restricted to specific inboxes.
  5. Check the inboxes they should be able to see.
  6. (Optional) Pick the Contact visibility level: all contacts and history, all contacts with inbox-only history, or only reachable contacts.
Which route should I use?

Granting access to a private inbox? Use Route A — start from the inbox and add the people. Locking an agent into a narrow set of inboxes? Use Route B — start from the team member and define their world.

What changes for existing workspaces?​

Nothing, until you create your first inbox. Custom Inboxes are completely opt-in.

  • If you never visit Settings → Inboxes, the product looks and behaves exactly like before — one unified conversation list for everyone.
  • The moment you create your first inbox, the sidebar (desktop) or inbox pill (mobile) appears for the users who can see it.
  • "All Inboxes" at the top of the sidebar always shows the union of every inbox the current user can access. For an Owner or Admin, that is genuinely all conversations. For a restricted agent, it is the combined feed of just their inboxes.

When creating a new conversation manually, the channel picker is automatically filtered to channels the user can reach through their accessible inboxes. Restricted agents will never accidentally start a conversation on a channel they are not supposed to use.

Tips & best practices​

  • Fewer, broader inboxes scale better than many micro-inboxes. Five well-named inboxes are easier to navigate than thirty.
  • Use tags for behavioural / lifecycle filtering (vip, churn-risk, trial) and custom fields for stable attributes (region, shoe_size, plan_tier).
  • Reach for contains on free-text fields — customer_notes contains "complaint" is a great low-effort triage rule that doesn't require fully structured data.
  • Use Allowed recipients to fan a single email connection across several inboxes rather than creating a separate connection per address.
  • Name inboxes for the people who use them, not the rules behind them. Munich Support is better than WA-DE-MUC + tag:support.
  • Start with public inboxes. Make an inbox private only when there is a real reason to hide it from the wider team.
  • Restrict cautiously. It is tempting to lock every agent down, but most teams benefit from broad visibility. Restrict only when there is a clear reason (regional separation, multi-tenant agency setup, sensitive segments).
  • Audit periodically. Every few months, open Settings → Inboxes and prune inboxes that are no longer used.

Limitations​

A few honest caveats to be aware of:

  • Conversations can appear in multiple inboxes. Filters are evaluated independently, so a contact who matches two inboxes' rules will show up in both. This is intentional, not a bug.
  • Filtering is dynamic, not stamped on the conversation. Moving a channel into a different inbox immediately changes what shows up in each view — there is no historical "this conversation belonged to inbox X" record. If you re-organise inboxes, the old conversations follow the new rules.
  • contains and not_contains are text-only. The operators do not appear for numeric, date, or boolean custom fields.
  • Per-inbox limits:
    • Up to 100 channels / email connections
    • Up to 50 tag filters
    • Up to 20 custom-field rules
    • Up to 500 explicit user grants
  • Mobile parity. The SendSeven mobile app supports viewing inboxes; full creation and access-management parity is shipping in a follow-up release. For now, manage inboxes from the web app.

FAQ​

Do Custom Inboxes change anything for users who don't need them?​

No. If you do not create any inboxes, your workspace looks and behaves identically to before. Custom Inboxes are completely opt-in.

Can the same channel or email connection appear in more than one inbox?​

Yes. A single WhatsApp number, Instagram account, email connection, or any other source can belong to as many inboxes as you like. Each inbox just defines its own filter on top of the shared source — including, for email connections, its own Allowed recipients list.

What does an admin or owner see?​

Everything. Owner and Admin roles always see every conversation in every inbox, regardless of inbox-level or user-level restrictions. To narrow someone's view, give them a lower role first.

If I remove a tag from a contact, does the conversation leave the inbox?​

Yes. Filters are evaluated dynamically, so the conversation will leave inboxes whose filters no longer match and may appear in others whose filters now match. There is no manual reassignment step.

Can I see "everything" even with inboxes set up?​

Yes — the All Inboxes view at the top of the sidebar shows the combined feed of every inbox you have access to. For Owners and Admins that is the entire workspace. For restricted users it is the union of the inboxes they are allowed to see.

What happens to a private inbox if its only user is removed from the workspace?​

The inbox still exists but no one (other than Owners and Admins) can see it until you add new users to its Access list. You can re-open it from Settings → Inboxes and add another user.

Do inboxes affect campaigns, automation flows, or webhooks?​

No. Custom Inboxes are a viewing and access layer over conversations. They do not change how campaigns are sent, how flows are triggered, or which webhook events fire. Every conversation still exists in the underlying workspace — inboxes just control who looks at what.

Why is "Contact visibility" a separate setting from "Inbox access"?​

Because the two questions are different. Inbox access controls the live queue — what shows up in the user's sidebar and conversations list day to day. Contact history visibility controls what shows up when someone digs into a single contact's past. Some teams want broad day-to-day restriction but full historical context (a quality reviewer who needs to read a contact's full timeline). Other teams want the opposite — broad live access but a focused per-contact view (a regional agent who only needs their own region's history surfaced). Splitting the two toggles lets you set each axis independently.

Will levels 2 and 3 hide historical email threads on a contact?​

Yes — older email threads on email connections the user is not part of will be hidden from the contact view. The channel-membership check is the same one used elsewhere in Custom Inboxes; nothing is special-cased for email. Owners and Admins bypass the filter and always see everything.

Is contains case-sensitive?​

No — it is always case-insensitive. vip, VIP, and Vip are treated as the same search. If you need a true exact match (case included), use equals instead.

Can I do wildcard or regex matches with contains?​

No. contains (and not_contains) is a literal substring match. Characters like %, _, *, and ? are matched as themselves, not as wildcards.

Next steps​

  • Tags & Lists — set up the tags you will use in inbox rules.
  • Custom Fields — define the contact attributes you can filter inboxes by.
  • Manage Contacts — keep contact data accurate so inbox filters stay useful.