docs/platform/inbox/configuration/inbox-with-context.mdx
Contexts let you scope each <Inbox /> instance to a specific environment, tenant, or app within your product. When combined with workflow-level contexts, they ensure that each <Inbox /> displays only the notifications relevant to that specific context.
<Inbox/>The <Inbox /> filters notifications by context type and id. Each entry in the context object resolves to a key like tenant:acme. The Inbox only shows notifications whose trigger used the same set of keys.
Nested data is optional metadata for personalization. It is stored on the context entity but does not affect which notifications appear in the Inbox.
| Workflow Context | Inbox Context | Displayed? |
|---|---|---|
{ "tenant": "acme" } | { "tenant": "acme" } | Yes |
{ "tenant": { "id": "acme", "data": { "name": "Acme" } } } | { "tenant": { "id": "acme" } } | Yes |
{ "tenant": "acme" } | { "tenant": { "id": "acme" } } | Yes |
{} | {} | Yes |
{} | { "tenant": "acme" } | No |
{ "tenant": "acme" } | { "tenant": "globex" } | No |
{ "tenant": "acme" } | {} | No |
{ "tenant": "acme", "app": "first" } | { "tenant": "acme" } | No |
<Inbox/>If a new context is passed from the <Inbox /> that doesn’t already exist, Novu will automatically find or create it. This means you don’t have to manually set up contexts before using them, they are created just in time.
If a context already exists, Inbox session initialization reuses it without updating stored data. This prevents unintentional overwrites from the client. To change existing context metadata, update it through the Contexts API, Novu dashboard, or a server-side workflow trigger with inline data.
This is particularly useful for:
You can view all automatically created contexts under the Contexts section of your Novu dashboard.
You can filter the <Inbox /> notifications to a specific context, by passing a context prop to the <Inbox /> component.
This prop's value defines the filter for that session, and it will only request and show notifications that match this context.
import { Inbox } from '@novu/react';
<Inbox
applicationIdentifier="APPLICATION_IDENTIFIER"
subscriber="SUBSCRIBER_ID"
context={{
tenant: {
"id": "acme-corp",
"data": {
"name": "Acme Corporation",
"plan": "enterprise",
}
},
}}
/>
When a workflow is triggered with the same context type and id, as seen below
Then, the notifications will be delivered to the <Inbox />.
Because the context prop is set on the client-side, a malicious user could potentially tamper with it to view notifications from a different tenant.
To prevent this, you must fetch the context details and contextHash from your server and pass them to the Inbox component.
When HMAC is enabled on your in-app integration, subscriberHash is always required. contextHash is also required if you pass a context prop to <Inbox />. If you do not pass context, you only need subscriberHash.
contextHash is separate from notification matching. It verifies the exact context object you pass to <Inbox />, including any data fields. Hash the same object you send to the component.
import { createHmac } from 'crypto';
import { canonicalize } from '@tufjs/canonical-json';
const context = {
tenant: {
id: "acme-corp",
data: {
name: "Acme Corporation",
plan: "enterprise",
},
},
};
const contextHash = createHmac('sha256', "NOVU_SECRET_KEY")
.update(canonicalize(context))
.digest('hex');
import { Inbox } from '@novu/react';
const { user } = currentUser();
const subscriberHash = user?.novuSubscriberHash;
const contextHash = user?.novuContextHash;
const context = {
tenant: {
id: "acme-corp",
data: {
name: "Acme Corporation",
plan: "enterprise",
},
},
};
<Inbox
applicationIdentifier="YOUR_APPLICATION_IDENTIFIER"
subscriber="YOUR_SUBSCRIBER_ID"
subscriberHash={subscriberHash}
context={context}
contextHash={contextHash}
/>
Frequently asked questions related to context in the Inbox component.
<AccordionGroup>
<Accordion title="Why are in-app notifications sent successfully but not showing in the Inbox?">
The Inbox filters by context type and id. The context prop on <Inbox /> must include the same type/id pairs used when the workflow was triggered. Nested data does not need to match.
A common cause: you started passing `context` on workflow triggers but did not update `<Inbox />` to use the same context ids. The in-app channel job can still complete with status "Success" in the activity feed, but the notification is scoped to a different context and will not appear in an Inbox session that does not match.
Check that:
1. If you trigger **with** context, initialize `<Inbox />` with the **same** context type/id pairs.
2. If you trigger **without** context, do not pass a `context` prop to `<Inbox />`.
3. When a user switches tenants or orgs in your app, re-render `<Inbox />` with the updated context.
See the context matching table above for all combinations.
`data` is optional metadata stored on the context. Use it for personalization, not for filtering.
If you use `contextHash`, hash the exact `context` object you pass to `<Inbox />`. That is separate from notification matching.