Skip to main content
covers the concepts behind this page.
The user determines who receives the message. The tenant determines which of that user’s contexts Courier builds it from: whose brand, whose defaults, whose content. You can target a single user in a tenant’s context, fan out to every member of a tenant, or walk a tenant hierarchy up or down. The tenant goes in one of two places, and both behave identically. Put it on the recipient as to.tenant_id, or on the message as context.tenant_id. Pick one and put it behind a shared helper, because tracking down a message that rendered with the wrong brand is a great deal harder when two call sites disagree about where the tenant lives.

Prerequisites

Send to a user with tenant context

Set context.tenant_id on a recipient to attach the tenant’s metadata, preferences, and branding to their message. User-level preferences and profile data take precedence over the tenant’s. The template holds the content. Pass the variables it expects in data, and reference tenant values like {$.tenant.name} from inside the template, where the tenant context resolves them.
A user does not need to be a member of the tenant to receive a message in its context. This is useful when the tenant holds branding or credentials but you are not fanning out to members.

Send to every member of a tenant

Put a tenant_id in to and Courier looks up the tenant’s members and sends to each one.

Send to multiple users with shared context

When sending to an array of users, set a shared tenant at the message level with message.context.tenant_id. Every recipient inherits it. Override it for a specific recipient by setting context.tenant_id on that entry, which takes precedence over the message-level context.
Here user_123 and user_456 get Acme Corp’s context, while user_456 gets Beta Inc’s.

Handle users in multiple tenants

Courier infers the tenant for a user who belongs to exactly one tenant, so specifying it is optional for them. A user with two or more memberships must have context.tenant_id set, or the send returns Tenant Context Not Found.
In the tenant/<template_id> format, tenant is the literal word rather than your tenant ID, which goes in context.tenant_id. has the full format.

Fan out across a hierarchy

Set include_children: true to also send to users in a tenant’s descendant tenants, or include_parent: true to walk upward through its ancestors.
Courier traverses up to four levels of the hierarchy in either direction.
On Go and C#, include_children and include_parent aren’t in the typed recipient models yet, so the tabs above set them as extra fields on the recipient. Every other operation on this page has a fully typed Go and C# form.

Segment delivery data by customer

Courier records the tenant on the message at providers[].reference.tenantId, so you can group logs and delivery data by customer after the fact. Read it from the or from a . A send that never named a tenant carries no reference, which is one more reason to route every multi-tenant send through the same helper.

Limits & behavior

None of these raise an error, which is what makes them worth knowing before you ship.
  • Courier can apply a tenant you did not name. If the user belongs to exactly one tenant and the send specifies none, Courier loads that tenant’s context anyway. See , and turn it off in workspace settings if you would rather send unscoped.
  • A tenant-scoped inbox message is invisible to a client signed in without the tenant. The send reports success and the feed stays empty. Pass the same tenantId to signIn that your sends carry.
  • Hierarchy traversal stops at four levels. The window starts at the tenant you sent to rather than at the root, so a fifth ancestor’s settings never reach the message.

Verify

1

Send with a branded tenant

Send with a tenant that has a brand_id set, and confirm the message renders with that tenant’s brand (see ).
2

Check the message log

Confirm the send used the tenant’s preferences, not the workspace defaults.
3

Confirm fan-out delivery

For a fan-out send, confirm each expected member received a copy.