Roles & Access Context
Understand the partner roles Hint assigns to each user, and handle Hint platform-support sessions correctly with access_context.
Every embedded surface load carries two pieces of access information in the Marketplace handshake: the user's partner roles and an access context. This guide explains where each comes from, how Hint decides them, and what your app is required to do with them.
How roles reach your app
Role assignment is controlled entirely on the Hint side. You declare the roles your app supports; Hint resolves which of those roles a given user has and includes them in the handshake payload as user.partner_roles (an array of role-name strings). Your app never manages role assignment itself - it reads partner_roles and applies its own in-app RBAC.
{
"user": {
"id": "user-BtAH8TTXCo6P",
"email": "[email protected]",
"partner_roles": ["admin"]
},
"access_context": "standard"
}
Roles live in the handshake, not the JS SDK
partner_rolesandaccess_contextare delivered in the signed server-to-server handshake payload only. They are not exposed onHintSDK.userin the browser. Read them on your server when the handshake arrives and persist them with the session.
Configuring your roles
You declare your app's roles through your App configuration (PATCH /partner/products/:id/app). Each role has:
- name - the identifier sent in
partner_roles(e.g.admin,member). - description - a short, human-readable explanation of what the role can do (e.g. "Full access including billing configuration and user management"). Hint surfaces these descriptions to the practice admin during install and in the practice's App Settings, so they understand what each role grants.
Alongside the role list you also declare:
- admin role - which of your roles is the admin equivalent. It is the role applied to practice admins when Hint grants them access, and the role sent for Hint platform-support sessions (see below).
- non-admin role - the equivalent for non-admin practice users.
These two are your suggested defaults. They are not applied to a practice on their own. The mapping Hint actually uses is stored on each installation and is only set if the install request supplies it (admin_role_mapping and non_admin_role_mapping). When the install request omits them, users are still granted access - but with no role at all, and the practice has to assign roles by hand before your app becomes usable. If your app depends on roles, supply the mappings at install time.
Role mappings are per installationThe mapping lives on the practice's installation, not on your app configuration. Changing your app's default roles later does not flow back into practices that already installed you - existing installations keep the mapping they were created with.
How Hint assigns roles
Roles are assigned to a user once, and resolved again on every surface load.
Grant time - how a user ends up with a role
A user gets an access record for your app, carrying zero or more of your roles, when:
- Your app is installed. Every existing practice member is granted access, and the installing admin is granted your admin role so they can use and configure the app the moment installation completes.
- A new team member joins the practice, if the practice has "Automatically grant access to new team members" enabled in your app's Access Settings. The role applied is the installation's configured mapping for that user's type (practice admin or non-admin).
- A practice admin adds or edits a user by hand in your app's Manage Users tab. An explicit assignment always wins over the mapping.
If the installation has no mapping configured for a user's type, the user still gets an access record - just with an empty role list.
Resolution time - what your handshake receives
On every surface load Hint resolves roles in a single step: it reads the user's access record and intersects the roles on it with the roles your app currently declares.
If you rename or remove a role, every user mapped to the old name resolves to an empty role list until the practice reassigns them. Add a replacement role and have practices migrate rather than renaming in place.
When a user cannot access your surface
A user can lack access in two ways, and only one of them stops before your handshake.
| State | What Hint does | What your app sees |
|---|---|---|
| No access record for your app | Returns 403 and renders its own message in the surface | Nothing. Your handshake URL is never called. |
| Access record, but no role your app currently declares | Loads the surface | A handshake with an empty partner_roles array |
| Access record with at least one declared role | Loads the surface | A handshake with a non-empty partner_roles |
The 403 is Hint's to handle, the empty array is yours.
You do not need to build a screen for the 403. Hint renders its own message in the surface, and your app is never called.
For the empty array, your app renders its own state - "You do not have access to this application, please contact your administrator" or similar. Do not error out.
Either way the practice fixes it in the same place: open Marketplace, open your product, then the Manage Users tab, add the user if they are missing, and pick a Partner Role. A user who has access but no role shows as N/A in that column.
access_context - required capability
Every handshake includes an access_context attribute describing what kind of session it is:
| Value | Meaning |
|---|---|
standard | A regular practice user accessing the app with their assigned role. This is the default. |
platform_support | A Hint employee accessing the app in a platform-operator capacity. |
{
"user": { "id": "user-9dQ2rk", "email": "[email protected]", "partner_roles": ["admin"] },
"access_context": "platform_support"
}platform_support sessions occur when a Hint employee opens your surface to help a practice - for example, when a practice reports a support issue to Hint, or when a Hint team member is training a practice on your app. This is delegation, not impersonation: the Hint employee is acting in their own capacity as a platform operator, not pretending to be a practice user. The role sent alongside is always your designated admin role, so support has full visibility.
access_context is session metadata, not a role. Your app must handle platform_support sessions distinctly from standard ones:
- Do not provision a persistent user in the practice's account for the session. These sessions are ephemeral. Treat them the way you treat a session from your own support team - store session state only, keyed by the practice, and do not create a customer user record from the handshake
user. - Scope access to that practice with admin-level (or read-only, if your product prefers) visibility. Do not expose data from other practices.
- Attribute audit-log entries to a platform-support session, not to a customer user, so your logs distinguish vendor-initiated access from customer activity.
- Surface a visible indicator, such as a "Hint support session" banner, so it is clear the account is being viewed by Hint.
Why this mattersIn healthcare, vendor access to a customer's environment carries specific BAA and compliance implications. Distinguishing platform-support sessions from customer sessions keeps audit trails accurate and access appropriately scoped.
Decode the handshake permissively: access_context may gain additional values over time (e.g. other platform contexts), so treat any unrecognized value as non-standard and default to your most conservative handling.
Updated 17 days ago

