App Best Practices
Map to clinical interaction endpoints
Use clinical interactions to let users jump between Hint and your embedded experience.
Create a clinical interaction
Reference Create Partner Interaction. Interactions provide a durable pointer for the user to reopen your iframe later.
const createInteraction = async patientId => {
const response = await fetch(
`https://api.hint.com/v1/provider/patients/${patientId}/interactions`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: 'partner',
status: 'draft'
})
}
);
return response.json();
};Update a clinical interaction
Use Update Partner Interaction to update the interaction state (e.g., signed vs. draft) when your workflow completes.
const updateInteraction = async (patientId, interactionId, updates) => {
const response = await fetch(
`https://api.hint.com/v1/provider/patients/${patientId}/interactions/${interactionId}`,
{
method: 'PATCH',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(updates)
}
);
return response.json();
};Integrate with the Hint UI
Use the Hint Marketplace JS SDK to detect the current patient, respond to navigation changes, and close the iframe when your workflow ends. The SDK also exposes deep-link helpers (queryParams, fragment) so you can drive consistent navigation between Hint users.
Report your height on clinical surfaces
Clinical surfaces (clinical_interaction, clinical_chart) size the embed iframe only from your app's height reports. Include the Hint JS SDK on every embedded page — it reports height automatically via a ResizeObserver. Without it, your surface renders clipped to a ~150px strip inside the note window. This also applies to core_page surfaces with auto-adjust height disabled.
Using device capabilities (camera, microphone, geolocation)
Embedded surfaces run in a cross-origin iframe, so browsers block capabilities like navigator.mediaDevices.getUserMedia unless Hint delegates them to your app's origin. Delegation is opt-in per app: set browser_allow_list when updating your app (Update App) — for example {"app": {"browser_allow_list": ["camera", "microphone"]}}. Supported values are camera, microphone, and geolocation. Hint then renders your embed iframes with a matching Permissions Policy allow attribute.
- The end user still sees the browser's standard permission prompt — the list delegates the capability, it does not grant permission.
- The
allowattribute is rendered when a surface is embedded, so changes tobrowser_allow_listonly apply to newly opened surfaces — reload any already-open surface. - Without it,
getUserMediarejects immediately withNotAllowedErrorand no prompt is shown. - The handshake payload includes the current
browser_allow_list, so your app can preflight before callinggetUserMedia. On aNotAllowedError, check it first: if the capability is missing from the list, Hint hasn't delegated it (fix: the App Settings toggle); if it's present, the user denied the browser prompt (fix: the browser's site permissions). Both cases throw the same error, so this field is the only way to show the right message. - Current iOS honors the delegation (camera, microphone, and geolocation verified in iOS Safari). Older iOS versions may still block
getUserMediain cross-origin iframes, so a fallback such as<input type="file" accept="image/*" capture="environment">is still worth providing.
Security and PHI handling
- Treat the handshake
access_tokenas a secret and scope it to the session (do not log it). - Verify
X-Hint-Signaturefor the handshake payload using Webhooks Security. - Avoid storing or logging PHI unless you need it for the workflow. Prefer using IDs and fetching details on demand.
Updated 20 days ago

