Skip to main content
A tenant is one of your customer organizations: the company, account, or workspace that a group of your users belongs to. If you sell to businesses, you already have this object in your own database, under one of those names.
One field on the send names the organization. Courier applies that tenant’s brand, defaults, and content, so one template goes out looking like it came from each of your customers.

What tenants are for

Every customer sees their own logo, colors, and sender identity. Attach a to the tenant and Courier applies it whenever you send to a user in that tenant, with no change to the template.
A tenant carries default for its topics. One customer starts opted out of product announcements, another makes billing alerts required. Their users can still change their own.
A overrides the workspace template for that tenant only. Use it when a customer needs different wording, an extra legal line, or their own layout.
Send to a tenant_id instead of a user and Courier fans out to its members. Tenants can nest through parent_tenant_id, so a send can walk the hierarchy up or down. See .
A tenant doesn’t have to be a company. It maps to whatever unit your product bills or brands: a team, a project, a store, a region.

What you store on a tenant

Anything that is true about a customer organization rather than about a particular notification. Without a tenant, all of that gets looked up and assembled in front of every send. With one, you pass an id and Courier resolves the rest. Put event-specific values in data. Put customer-level values in the tenant’s properties. A support address that arrives in data on every send is one that belongs in properties once.

What a tenant isn’t

A tenant isn’t a way to group recipients. If what you want is “send this to these people”, use a . A tenant scopes branding and settings to one customer. To send to a group of users, use a list or an audience. A tenant isn’t an environment. Use to separate test traffic from production. Tenants divide your customers, not your pipeline. Tenant membership isn’t permissions. Being in a tenant decides which context Courier builds a message from, and nothing about what that user may do. Authorization stays in your application.

How it works

You address a user, and name the tenant that user is acting in. See for the resolution order. Anything the tenant doesn’t define falls through to the workspace default, so you only configure the differences. A user can belong to as many tenants as you need, and each membership is independent. Someone who works with two of your customers can have alerts on at Acme and off at Beta. They see Acme’s branding in one email and Beta’s in the next, with a separate inbox feed on each side.

How tenant context resolves

Courier can apply a tenant you didn’t name. If a user belongs to exactly one tenant and your send doesn’t specify one, Courier loads that tenant’s context anyway. This is a workspace setting, useful for console, list, and audience sends where the tenant isn’t explicit in the request. See . A tenant-scoped inbox message appears only to a client signed in with that tenant. A message sent with tenant_id: "acme-corp" shows up once the client calls signIn with the same tenantId. Signing in without it returns an empty feed for that tenant, even though the send succeeded. Tenant hierarchy merges up to four levels. Courier loads tenant context as a four-layer sliding window, starting at the tenant you sent to rather than the root. In a five-deep tree, the top tenant’s settings don’t apply to a leaf send.

Limits & behavior

Channels, providers, and API keys are shared across tenants. Configure a provider such as SendGrid once, and every tenant uses it. A customer’s own Slack token or Teams webhook can still live in the tenant’s user_profile, which merges into the recipient at send time.

FAQ

Tenants serve multiple customer organizations from one account, as in B2B SaaS or white-label products. A single-customer app needs one workspace and no tenants.
A tenant inherits every workspace template by default. Create a only for the messages that customer needs to differ.
If the user belongs to exactly one tenant, Courier infers it. With two or more memberships you must set context.tenant_id, or the send fails with Tenant Context Not Found. See .
Either to.tenant_id on the recipient or message.context.tenant_id. Both behave identically, so pick one and put it behind a shared helper. uses the context form throughout.