The HALO App Catalog serves as a centralized repository for healthcare applications that extend the capabilities of clinical systems such as Electronic Medical Records (EMRs). A primary goal of the App Catalog is to provide healthcare providers across Canada with access to jurisdictionally approved third-party applications, streamlining the discovery, configuration, and deployment of applications to improve patient care and clinical workflows.
The pan-Canadian framework of HALO ensures that jurisdictions can adapt the App Catalog, while remaining aligned with broader national standards for interoperability and connectivity. Jurisdictions may tailor the App Catalog to meet local regulatory requirements and healthcare needs.
From the perspective of Point of Care (PoC) systems, the App Catalog provides a standardized method to retrieve and display applications, enabling integration into clinical workflows. The specification defines how PoC systems can interpret the detailed metadata for each application (e.g., name, description, developer information, etc.), to facilitate the HALO App Launch flow. The technical and approval process to register an app within a PoC vendor system is outside the scope of this guide and may require processes unique to that PoC vendor.
The app lifecycle (i.e., how an app is registered, updated, and removed from the catalog) is beyond the scope of this specification.
Currently FHIR® does not provide suitable resources to represent the App Catalog without significant profiling of several resources. FHIR® resources are mainly designed to handle clinical and administrative data related to patients, healthcare providers, and medical treatments, whereas the focus of the data expressed by the App Catalog relates to metadata & application management.
The App Catalog includes information about each application's capabilities, including supported interactions. Although FHIR® provides the CapabilityStatement resource, it is intended to document a set of capabilities (behaviours) of a FHIR® Server or Client for a particular version of FHIR® that may be used as a statement of actual server functionality or a statement of required or desired server implementation, not for managing applications or providing metadata about their use within a broader technical infrastructure.
Two distinct translation concepts apply to the HALO App Catalog:
Catalog Metadata Translation: translation of application metadata in the catalog response.
Application Runtime Translation: translation of the application after launch.
These concepts are independent. It is possible that a catalog will present an application in a user’s preferred language even if the application itself does not support that language after launch. Similarly, an application may support languages at runtime that are not reflected in the catalog metadata representation.
The App Catalog SHALL support translation of application metadata, with English and French as required primary languages. Translatable metadata elements SHALL be rendered in the most appropriate available language for each application as defined in the Accept-Language request header section below.
App Catalog implementations SHOULD support translation for at least name, description, and descriptionShort, and in addition jurisdictions MAY define which elements should be translated.
As the App Catalog provider, the jurisdiction is responsible for ensuring translated metadata is available. The jurisdiction may obtain translations through any means they see fit, such as vendor submission during onboarding, AI-assisted translation, or other internal processes as needed.
Language Negotiation
Language negotiation SHALL follow standard HTTP semantics including Accept-Language request header and Content-Language response header (as defined in RFC 9110), using BCP 47 language tags (RFC 5646).
Accept-Language Request Header
Consumers SHOULD send the Accept-Language header to indicate preferred languages, including fallback preferences where applicable.
For example: Accept-Language: fr-CA, fr;q=0.9, en;q=0.8
On a per-application basis, the catalog SHALL evaluate Accept-Language in priority order and return the best available translation for each app. If none of the requested languages are available for an application, or if the header is absent, the catalog SHALL fall back to another available language for that entry. How this fallback language is selected is up to the jurisdiction.
Content-Language Response Header
The App Catalog SHALL include the Content-Language response header to indicate the language or languages represented in the catalog response.
Because language selection is performed independently for each application entry, a single response MAY contain metadata rendered in multiple languages. In such cases, the Content-Language header SHALL include all languages present in the response.
To identify the specific language used for a particular application
entry, HALO introduces the contentLanguage element, reflecting the
semantics of the HTTP Content-Language response header. This element
SHALL indicate the language in which that specific application entry’s
catalog metadata is represented.
Application runtime translation refers to the languages supported by the application after launch. The App Catalog does not mandate which languages an application must support at runtime; however, it does provide a mechanism for which languages are supported to be communicated during discovery.
It is possible for an App to provide translations within the catalog for
languages that it does not support at runtime, for example to maximize
discoverability for multilingual users. Consumers of the catalog MAY
leverage the languagesSupported element to improve the browsing
experience for users, for example by supporting client-side filtering or
sorting based on runtime language support.
The App Catalog MAY include information to facilitate a secure App registration process and a streamlined user experience, providing metadata elements to support App registration with the PoC's trusted Authorization Server. HALO introduces the registrationModes and preassignedCredentials elements holding the App registration details.
HALO defines an order of preference for how applications register and authenticate, favoring automated, scalable methods over manual ones. For registration, Dynamic Client Registration (DCR) is preferred. Preassigned Client IDs and out-of-band registration are supported as interim mechanisms, subject to deprecation in favor of DCR as systems mature. PoC systems SHOULD support all registration and authentication patterns.
For authentication, applications with a secure backend register as confidential clients, preferably using asymmetric JWKS keys rather than shared secrets. Applications without a secure backend operate as public clients and rely on PKCE.
App Registration and Authentication
For the complete App registration and authentication guidance, see the App Registration and Authentication section of the Design Considerations page.
The App Catalog MAY include an intents element to declare the UI contexts or workflows that an application supports during a SMART launch. By publishing intents in the App Catalog, applications inform PoC systems of the intent values that can be used at launch time (e.g., "create-case" vs. "view-case"), enabling the PoC system to present targeted launch options to end users.
The PoC system conveys the selected intent as a launch context parameter in the token response, indicating which specific UI context or workflow the application should display. If the intents element is absent or empty, or if the PoC system provides an intent value that the application does not recognize, the application SHOULD apply a default UI context. For information on the intent launch context parameter in SMART on FHIR, see App Launch Intent.
In the SoFA flow, the PoC system is expected to use the intents advertised by the App Catalog to determine the appropriate launch intent for the selected application workflow. When initiating the launch context, the PoC system populates the $set-context intent parameter with that value so that the SoFA Authorization Server can return the corresponding intent claim in the token response after launch.
An implementing system SHALL provide access to the HALO App Catalog through the following API endpoint:
GET [base]/apps
This endpoint allows a consuming system to retrieve a list of available applications from the catalog.
Note: This endpoint may be further defined in a future release of this specification as additional design decisions are finalized.
Securing the App Catalog
For information on securing the App Catalog, see the Securing the App Catalog section of the Design Considerations page.
This section describes the JSON structure of the App Catalog including datatypes, constraints, element descriptions, and examples.
The datatypes used in the App Catalog are listed below.
| Datatype | Description |
|---|---|
string |
A basic text field, commonly used for URLs, names, IDs and descriptions. A string may have a specific length of characters which will be defined in the tables below. |
array |
An array of values, used when multiple values are required, such as tags or lists of URLs. |
object |
A structured field containing key-value pairs, often used for complex fields. |
boolean |
A binary datatype that can hold one of two values: true or false. |
Each application within the catalog provides key metadata, including a unique identifier (UUID), a descriptive name, and detailed information such as the app’s functionality, languages supported, privacy policies, and terms of service. These elements also include technical capabilities, such as supported FHIR interactions and launch URLs for integration into clinical workflows. The metadata ensures that healthcare providers can easily discover, assess, and integrate applications that meet their specific needs.
Note that versioning of applications in the App Catalog is managed through separate deployments of each app. When a new version of an application is introduced, it is treated as a distinct deployment in the catalog. This ensures that the metadata for each version remains independent, allowing healthcare providers to maintain or adopt specific versions according to their needs.
| Field | Datatype | Requirement | Description | Example |
|---|---|---|---|---|
id |
string(36) |
Mandatory | A unique identifier (See RFC 4122) that serves as the authoritative reference for a specific application within the App Catalog. | "fcf9956c-f952-40e0-8e24-a65d56118db2" |
name |
string(150) |
Mandatory | A descriptive and easily recognizable name for the application, limited to between 3 and 150 characters. | "Heart Health Monitor" |
description |
string |
Mandatory | A detailed description of the application's functionality for the end user. | "A comprehensive application for monitoring and managing heart health." |
descriptionShort |
string |
Mandatory | Short description used for tooltip hover or where space is limited (i.e. app list). | "Monitor heart health" |
contentLanguage |
string |
Mandatory | The language in which this application entry’s catalog metadata is rendered, represented as a BCP 47 language tag using ISO 639-1 and/or ISO 639-3 language codes. | "en-CA" |
languagesSupported |
array |
Optional | The list of languages supported by the application post launch, as BCP 47 language tags using ISO 639-1 and/or ISO 639-3 codes. | ["en-CA", "fr-CA"] |
tags |
array |
Optional | Tags categorize the app and enhance its discoverability. These tags typically represent the audience or functionality of the app (e.g., the type of user or health area it supports). It is recommended that the maintainer of the app catalog put in place a process to standardize tags to reduce deviations in spelling/format. Examples might include: "reports", "Clinical Research", "Data Visualization", "Disease Management", "Genomics", "Medication", "Patient Engagement", "Population Health", "Risk Calculation", "FHIR® Tools", "COVID-19", "Telehealth", "Cardiac Apps". | ["cardiology", "monitoring", "health"] |
helpUrl |
string(2048) |
Optional | URL pointing to the help manual or user support page. | "https://example.com/help-manual" |
iconUrl |
string(2048) |
Mandatory | URL pointing to the application’s icon. | "https://example.com/icons/heart-health.png" |
screenshots |
array |
Optional | URLs pointing to screenshots of the application. These images should provide a visual preview of the app’s interface and functionality. | ["https://example.com/screen1.png", "https://example.com/screen2.png"] |
privacyPolicyUrl |
string(2048) |
Mandatory | URL pointing to the privacy policy of the application. | "https://example.com/privacy/heart-health" |
termsOfServiceUrl |
string(2048) |
Mandatory | URL pointing to the terms of service, outlining the terms and conditions of the app, including the license. | "https://example.com/terms/heart-health" |
launchUrl |
string |
Mandatory | The base launch URL for the SMART application. | "https://halo.example.com/launch/heart-health" |
eligibilityCriteria |
string(2048) |
Optional | Text defined by the App Developer outlining the intended user(s) of the application. | The audience for this app is General Practitioners and Nurses. |
contacts |
array |
Mandatory | Contact methods for users to get support, including email, phone numbers, and URLs to chat support. | See the contacts element |
publisher |
object |
Mandatory | Information about the application publisher. | See the publisher element |
isEnrolling |
boolean |
Optional | Parameter to identify if the application allows to enrol new users. | true |
registrationModes |
array |
Optional | Identifies the supported registration mode or modes. Acceptable values include “dcr” and “preassigned”. If omitted, the App and PoC are expected to negotiate registration out of band, and cannot take advantage of the registration support offered by the App Catalog. | ["dcr", "preassigned"] |
preassignedCredentials |
object |
Conditional | Contains fixed registration details for preassigned clients. SHALL only be present when registrationModes includes “preassigned”. | See the preassignedCredentials element |
scopes |
array |
Optional | Provides a list of SMART on FHIR scopes that the SMART app may request upon launch. PoC applications using the SMART on FHIR Accelerator (SoFA) flows leverage this list to determine the context and resources to prepopulate in the SoFA FHIR server. | See the scopes element |
intents |
array |
Optional | UI contexts or workflows that an application supports during launch, via the intent launch context parameter. | See the intents element |
contacts elementThe contacts element provides details on how users can reach the publisher or support team for inquiries, troubleshooting, or assistance related to the application. Each contact entry may include an email address, phone number, or URL, offering multiple communication channels.
Each application SHALL include at least one contact entry with an email address and at least one contact entry with a URL. This MAY be accomplished using a single contact entry that includes both the email and the URL, or with multiple contact entries.
| Field | Datatype | Requirement | Description | Example |
|---|---|---|---|---|
title |
string(150) |
Mandatory | A human-readable name of the contact. | "Customer Support" |
email |
string(150) |
Optional | An email where a user can get help with a given app. | "support@example.com" |
phone |
string(30) |
Optional | A phone number where a user can get help with a given app. | "+1 111 222 3333" |
url |
string(2048) |
Optional | A URL where a user can get help with a given app, such as a support page or chat bot. | "https://example.com" |
publisher elementThe publisher element provides information about the organization or entity responsible for the application. This includes the publisher's unique identifier, human-readable name, and optionally, a URL directing users to the publisher's website.
| Field | Datatype | Requirement | Description | Example |
|---|---|---|---|---|
id |
string(36) |
Mandatory | The id identifying the app publisher. | "6b4929be-a7c0-4a38-4a8e-53338dbcb7f5" |
name |
string(150) |
Mandatory | The human-readable name of the app publisher. | "Example Company Inc." |
url |
string(2048) |
Optional | The URL to the publisher's website. | "https://example.com" |
preassignedCredentials elementThe preassignedCredentials object contains the authentication and authorization settings supported by the application to interact with the authorization server.
| Field | Datatype | Requirement | Description | Example |
|---|---|---|---|---|
clientId |
string | Mandatory | The OAuth 2.0 client identifier preassigned by the jurisdiction for client_id registration by the PoC system with its Authorization Server. | "1bf0b8e8-c481-44c6-9574-7d732b4524a8" |
grantTypes |
array | Mandatory | The OAuth 2.0 grant type(s) to be enabled for the app by the PoC system when applying the preassigned registration. The acceptable values for SMART Apps include "authorization_code" and "refresh_token". | ["authorization_code"] |
tokenEndpointAuthMethod |
string | Mandatory | The token endpoint authentication method the app is expected to use when authenticating to the Authorization Server. Acceptable values include "client_secret_post", "client_secret_basic", "private_key_jwt", and "none". | "private_key_jwt" |
jwksUri |
string | Conditional | The URL pointing to the app's public JSON Web Key Set. Required when token_endpoint_auth_method is private_key_jwt. | "https://app.example/jwks" |
redirectUris |
array | Conditional | The authorized callback URLs. Required if grantTypes includes "authorization_code". | ["https://app.example/callback"] |
postLogoutRedirectUris |
array | Optional | The URI or URIs the client application may use as redirect targets after logout. Only applicable when grantTypes includes "authorization_code". | ["https://app.example/bye"] |
clientId
The OAuth 2.0 client identifier preassigned by the jurisdiction for client_id registration by the PoC system with its Authorization Server.
clientId is required when registrationModes includes preassigned.
To maintain identifier uniqueness across the App Catalog, the use of a Universally Unique Identifier (UUID) format is recommended.
The jurisdictional authority is responsible for assigning the clientId or formalizing an agreed-upon identifier with the application vendor.
To streamline the onboarding process and enhance the security posture, vendors are expected to support jwksUri. This approach leverages asymmetric cryptography for authentication, removing the operational burden of out-of-band client secret management.
grantTypes
The grantTypes element contains an array of strings, each representing a requested grant type. The acceptable values for SMART Apps include authorization_code and refresh_token. The value refresh_token if present, it must be paired with authorization_code.
Note: Currently HALO does not include additional guidance for client_credentials grant type and may be addressed in the future.
tokenEndpointAuthMethod
The tokenEndpointAuthMethod element contains the authentication method the app is expected to use when authenticating to the Authorization Server token endpoint.
private_key_jwt is the preferred option. See detailed guidance in the App Registration and Authentication section of the Design Considerations page.client_secret_basic and client_secret_post may be used by clients who are unable to support asymmetric authentication using JWKSnone is used for public or native apps that do not have a secure backend to securely store a secret or host a JWKS URI.jwksUri
jwksUri is required if the App is supporting private_key_jwt token endpoint authentication method.
Static JWKS (inline key sets without URI) are not supported by the App Catalog. To facilitate seamless key rotation and prevent the exposure of long-lived cryptographic material within the catalog, a jwksUri must be provided. This ensures that key updates do not require manual, out-of-band coordination between the vendor and the jurisdiction.
scopes elementThe scopes element provides a mechanism for the publishers of SMART Apps within the App Catalog to communicate which SMART on FHIR scopes their applications will require. This list SHALL only contain scopes that follow the rules defined within the Scopes and Launch Context of the SMART App Launch 2.1 specification.
While these scopes will ultimately need to be registered with the authorization server ahead of time, these are also intended to be leveraged by the Point of Care application during the SMART on FHIR Accelerator (SoFA) Launch process as a mechanism for determining which resources it needs to prepopulate within the SoFA FHIR server. For more detailed guidance on how Point of Care solutions should implement this decision logic, please see the Operation: $set-context page.
When parsing the list of scopes from the catalog entry for a given application, vendors SHOULD use this information to assess the application's compatibility with their current implementation. For instance, the application might request resources that the PoC system is unable to map to FHIR at this time.
FHIR Resource Scopes
Scopes in this format are comprised of 3 segments. The interaction level prefix, the resource type, and the REST API Interaction suffix.
For example:
patient/Observation.crus: Permission to create, read, update, and search Observations belonging to the current patient in context.user/Patient.rs: Permission to read and search all Patients that the current user has access to.system/Practitioner.rs: Permission to read and search all Practitioners in the system.Note: SMART on FHIR provides guidelines for specifying the exact subset of resources to which an app requires access. This is achieved through finer-grained resource constraints, which leverage FHIR search parameters to preemptively filter the requested resource types. However, due to the complexity of these search parameters, vendors are not currently expected to process them and MAY instead implement mechanisms to ignore them when present. Future releases of HALO may include additional guidance for PoC vendors on how to handle these scopes as a mechanism for limiting the amount of data that is prepopulated within the SoFA FHIR server.
For more information, see Scopes for requesting FHIR Resources within the SMART App Launch specification.
Context Scopes
Context scopes are scopes that allow the SMART on FHIR app to request that the authorization server provide it with various aspects of the current clinical context within the PoC. These scopes follow a simpler syntax of a fixed "launch" prefix followed by an optional resource type.
By default, in an EHR launch, the launch scope is used when the SMART app receives the ?launch=... parameter in the launch URL. This scope instructs the authorization server to include relevant context in the access token response. Optionally, apps may request specific launch scopes suffixed with a resource type, providing a hint to the server about which specific context to include.
When these more specific scopes are defined for an app in the catalog, PoC vendors initiating a SoFA launch SHALL use these scopes to determine the minimum context that must be set during the $set-context operation (see Operation: $set-context).
If only the launch scope is provided, PoC vendors initiating a SoFA launch SHALL, at a minimum, include the current patient, practitioner, organization, and location in the $set-context operation, provided that they are present within the user's current context.
For example:
launch: Permission to obtain the launch context from the launching PoC application.launch/Patient: The app needs to know the ID of the patient in context at launch time.launch/Encounter: The app needs to know the ID of the encounter in context at launch time.launch/Organization: The app needs to know the ID of the organization the user is acting within at launch timeNote: The process by which apps request information about the current user is outlined in the Identity Scopes section below.
For more information, see Scopes for requesting context data within the SMART App Launch specification.
Identity Scopes
In SMART on FHIR, SMART apps can request information about the user currently launching the application by including a combination of the openid and fhirUser scopes. In traditional OAuth 2.0 and OpenID Connect (OIDC), the openid scope signals to the authorization server that the client expects an ID Token to be included in the access token response. In the SMART on FHIR context, adding the fhirUser scope indicates that the app is requesting the server to include a fhirUser claim in the ID Token. This claim contains a reference to the FHIR resource representing the current user.
For more information, see Scopes for requesting identity data within the SMART App Launch specification.
offline_access Scope
The offline_access scope in SMART on FHIR is used by client applications to request a long-lived refresh_token. When included in the authorization request and subsequently granted by the authorization server, this scope enables the application to obtain new access tokens even after the user has logged out or their session has expired. Essentially, this means the application is permitted to maintain continuous interaction with the FHIR server without requiring repeated explicit user re-authorization.
See the Scopes for requesting a refresh token and Refresh access token sections of the SMART App Launch specification for more details on the offline_access scope.
Within the HALO framework, which supports both standard SMART on FHIR and the SoFA (SMART on FHIR Accelerator) flow, handling of the offline_access scope depends on the chosen integration pathway:
Standard SMART on FHIR Flow: The Point of Care (PoC) system's Identity Provider (IdP) is responsible for managing refresh tokens and handling long-term access to resources on behalf of the application.
SoFA Flow: Jurisdictional-level infrastructure handles the issuance and management of refresh tokens. Specifically, the inclusion of the offline_access scope indicates that the SMART application may continue to write data back to the jurisdictionally hosted SoFA FHIR server even after the user has closed the app or logged out of the PoC. Consequently, the PoC system has an ongoing responsibility to maintain the mappings originally established through the $set-context operation (See the Operation: $set-context page). These persistent mappings ensure that data written back to the SoFA can be accurately reconciled and associated with the correct clinical context in the PoC, facilitating seamless updates or notifications related to patient data and clinical workflows.
intents elementThe intents element is an array of intent objects, each describing a single UI context or workflow that the application supports. Each intent object contains the following fields:
| Field | Datatype | Requirement | Description | Example |
|---|---|---|---|---|
name |
string | Mandatory | A unique value that the PoC system passes to the application at launch time to indicate the desired UI context or workflow. | "create-case" |
description |
string | Mandatory | The description of the UI context or workflow that the intent represents. | "Launch the create case workflow for the currently selected patient/order" |
Below is an example response from the app catalog endpoint. For simplicity, only a single result is shown here. In practice, this response will contain a list of available apps within the jurisdiction and is likely to include multiple results.
[
{
"id": "fcf9956c-f952-40e0-8e24-a65d56118db2",
"name": "Heart Health Monitor",
"description": "A comprehensive application for monitoring and managing heart health.",
"descriptionShort": "Monitor heart health",
"contentLanguage" : "en-CA",
"languagesSupported": [
"en-CA",
"fr-CA"
],
"tags": [
"cardiology",
"monitoring",
"health"
],
"helpUrl": "https://heart.example.com/help-manual",
"iconUrl": "https://heart.example.com/icons/heart-health.png",
"screenshots": [
"https://heart.example.com/screen1.png",
"https://heart.example.com/screen2.png",
"https://heart.example.com/screen3.png"
],
"privacyPolicyUrl": "https://heart.example.com/privacy/heart-health",
"termsOfServiceUrl": "https://heart.example.com/terms/heart-health",
"launchUrl": "https://heart.example.com/launch/heart-health",
"eligibilityCriteria": "The audience for this app is General Practitioners and Nurses.",
"contacts": [
{
"email": "support@example.com",
"title": "Customer Support"
},
{
"url": "https://heart.example.com",
"title": "Online Chat"
},
{
"phone": "+01 111 222 3333",
"title": "24 Hour Emergency Line"
}
],
"isEnrolling": true,
"registrationModes": [
"dcr",
"preassigned"
],
"preassignedCredentials": {
"clientId": "heart-health-monitor-client-id",
"grantTypes": [
"authorization_code",
"refresh_token"
],
"tokenEndpointAuthMethod": "private_key_jwt",
"jwksUri": "https://app.example.com/jwks.json",
"redirectUris": [
"https://app.example.com/callback"
],
"postLogoutRedirectUris": [
"https://app.example.com/logout-callback"
]
},
"scopes": [
"openid",
"fhirUser",
"launch",
"launch/Patient",
"launch/Organization",
"launch/Location",
"user/Practitioner.r",
"user/Organization.r",
"user/Location.r",
"patient/Patient.r",
"patient/Observation.rs",
"patient/Condition.rs",
"offline_access"
],
"intents": [
{
"name": "create-case",
"description": "Launch the create case workflow for the currently selected patient/order"
},
{
"name": "view-case",
"description": "Launch the view case workflow for the currently selected patient/order"
},
{
"name": "update-case",
"description": "Launch the update case workflow for the currently selected patient/order"
}
]
}
]
Usage note: every effort has been made to ensure that the examples are correct and useful, but they are not a normative part of the specification.