# Intervengine > This file is intended for LLM consumption. > Generated: 2026-04-07T21:09:18.441Z > Documents: 163 --- ## Get an activity type `GET /activity_types/{id}` Get an activity type. --- ## Search activity types `POST /activity_types/search` Search activity types. --- ## Close a extra `PUT /admin/extras/{id}/close` **[Requires Coach or Connector Access]** Close a extra --- ## Close a extra `PUT /admin/groups/{id}/close` **[Requires Coach or Connector Access]** Close a group --- ## Close a tag `PUT /admin/tags/{id}/close` **[Requires Coach or Connector Access]** Close a tag --- ## Create a dynamic activity plan `POST /admin/activity_plans` **[Requires Coach or Connector Access]** Create a dynamic one-off activity plan for a participant. This endpoint creates a dynamic activity plan based on the given data. It will create an activity type with measure types based on the card items and responses, then create an activity plan for the participant. Each card item can contain a question, a content or both(a mixture of both content and question). **Content Card:** ```json { "participantId": "47", "fromDate": "2025-11-01", "toDate": "2025-12-31", "card": { "title": "Card Title ", "description": "Dynamic Card Test", "imageUrl": "https://firebasestorage.googleapis.com/v0/b/intervengine-development.appspot.com/o/assets%2F9a48a0cb-2663-4871-95b8-c48f33c1ff6f..png?alt=media&token=06d34e59-55d1-4ab2-8b21-5e6465b9d2d0", "items": [ { "title": "Item title or Question", "description": "Item or Question Description", "content": { "contentElements": [ { "asset": { "type": "image", "url": "https://firebasestorage.googleapis.com/v0/b/intervengine-development.appspot.com/o/assets%2Fdb5af013-bc1b-4aa7-a0b8-ea35593cc49e..png?alt=media&token=78c68ad6-402b-4c5d-aa52-db3b38a90bbe" }, "text": null }, { "asset": null, "text": "This is a sample content text element." } ] } } ], "uiConfigs": { "cardLayout": "STANDARD", "endButtonLabel": "Done", "imageAspectRatio": "STANDARD", "isSinglePage": false, "nextButtonLabel": "Next", "startButtonLabel": "Begin" } } } ``` **Question Card:** ```json { "participantId": "47", "fromDate": "2025-11-01", "toDate": "2025-12-31", "card": { "title": "Your Favourite Cuisine", "description": "This card will ask about your favourite cousin. The modal window will pop up when the card is opened.", "imageUrl": "https://firebasestorage.googleapis.com/v0/b/intervengine-development.appspot.com/o/assets%2F9a48a0cb-2663-4871-95b8-c48f33c1ff6f..png?alt=media&token=06d34e59-55d1-4ab2-8b21-5e6465b9d2d0", "items": [ { "title": "What is your favourite cuisine style — Japanese, Italian, or Chinese?", "description": "Item or Question Description", "responses": [ "Japanese", "Italian", "Chinese" ] } ], "uiConfigs": { "startButtonLabel": "Start Now", "endButtonLabel": "Submit" } } } ``` --- ## Create a new extra `POST /admin/extras` **[Requires Coach or Connector Access]** Create a new extra field. Allowed **extraGroups** are 'PARTICIPANT', 'PARTICIPANT_INFERENCE' and 'PARTICIPANT_SYMPTOMS' The **extraDataType** is the data type of the extra value. Allowed extraTypes are 'B' (boolean), 'S' (string), 'N' (number), 'T' (datetime) and 'J' (JSON) If **isLog** is true, the history of the extra value will be maintained as a log otherwise it will be overwritten by a new value. If **isHidden** is true, the extra field will not be exposed to user. If **isReadOnly** is true, the value is not editable If **script** is provided, the script will be executed when the extra values in a group are saved. The script should be a valid javascript code. i.e) /participants/\{user_id\}/extras/\{extra_group\} endpoint will trigger the script execution. ```js (function() { var total = 0.0; // extraValues is read from the 'extraValues' from the request parameters for (var i = 0; i < extraValues.length; i++) { var extra = extraValues[i]; if (extra.value !== "") { total += parseFloat(extra.value); } } // returns the score to populate 'SCORE' extra field or the one the script belongs to return total * (extras.length / extraValues.length); })(); ``` --- ## Create a new group `POST /admin/groups` **[Requires Coach or Connector Access]** Create a new group. --- ## Create new tags and link `POST /admin/tags/new_and_link/participant` **[Requires Coach or Connector Access]** Create new tags and link to participant. Create new tags and then link them to a participant. If the tag already exists it will be ignored. It returns an array of the tag IDs if they were created successfully. This is a convenient endpoint which combines POST /tags and PUT /tags/link/participant together. --- ## Create a new tag `POST /admin/tags` **[Requires Coach or Connector Access]** Create a new tag If the decayingDuration is provided, then the tag will be automatically closed after the given duration. i.e) If the decayingDuration is 1w (1 week), then the assigned tag will be decayed and removed after 1 week from the assigned date. A decaying tag is currently applicable only for the participant tags. --- ## Link groups to participant `PUT /admin/groups/link/participant` **[Requires Coach or Connector Access]** Link groups to participant. Add (Link) the given group ids to a participant. The existing group ids will be ignored. --- ## Unlink tags to participant `DELETE /admin/tags/link/participants` **[Requires Coach or Connector Access]** Unlink tags to participant --- ## Open a extra `PUT /admin/extras/{id}/open` **[Requires Coach or Connector Access]** Open a extra --- ## Open a group `PUT /admin/groups/{id}/open` **[Requires Coach or Connector Access]** Open a group --- ## Open a tag `PUT /admin/tags/{id}/open` **[Requires Coach or Connector Access]** Open a tag --- ## Search extras `POST /admin/extras/search` **[Requires Coach or Connector Access]** Search extras --- ## Search groups `POST /admin/groups/search` **[Requires Coach or Connector Access]** Search groups --- ## Search participants `POST /admin/participants/search` **[Requires Coach or Connector Access]** Search participants. This requires admin access token which is issued by the coach or connector login --- ## Search tags `POST /admin/tags/search` **[Requires Coach or Connector Access]** Search tags --- ## Post a chat message `POST /admin/chat_sessions/{id}/chat_messages` Post a new chat message in the current session on behalf of a coach user. Channels supported: - APP: Send message to participant via in-app messaging (ChannelID 1) - EMAIL: Send message to participant via email. Not shown in the chat (ChannelID 4) - SMS: Send message to participant via SMS (ChannelID 5) - CARD: Send message to participant via a card message in App (ChannelID 6) - PUSH_NOTIFICATION_ONLY: Send message to participant via push notification. Not shown in the chat (ChannelID 7) 'subject' should be included for EMAIL and PUSH_NOTIFICATION_ONLY channels. --- ## Start a new chat session `POST /admin/chat_sessions` Create and Start a new chat session for the coach and participant. If the session between the coach and participant already exists, it will return the existing session id instead. --- ## Link tags to participant `PUT /admin/tags/link/participant` **[Requires Coach or Connector Access]** Link tags to participant. Add (Link) the given tag ids to a participant. The existing tag ids will be ignored. --- ## Change a extra `PUT /admin/extras/{id}` **[Requires Coach or Connector Access]** Change a extra --- ## Change a group `PUT /admin/groups/{id}` **[Requires Coach or Connector Access]** Change a group --- ## Change a tag `PUT /admin/tags/{id}` **[Requires Coach or Connector Access]** Change a tag --- ## View a extra `GET /admin/extras/{id}` **[Requires Coach or Connector Access]** View a extra field --- ## View a group `GET /admin/groups/{id}` **[Requires Coach or Connector Access]** View a group --- ## View a tag `GET /admin/tags/{id}` **[Requires Coach or Connector Access]** View a tag field --- ## Signin with email `POST /auth/email` Signin with email/password to get the access token --- ## Signin with external ID `POST /auth/external` Signin with external profile ID to get the access token. **Application Connector's access token** is required for this endpoint. When the application connector's access token is provided, it will be used to authenticate the external profile on the user's behalf. In this way, the external user does not need to sign in with username/password or key/secret to get the access token. --- ## Signin with key `POST /auth/key` Signin with key/secret to get the access token --- ## Request password reset link `POST /auth/reset_password` Request password reset link --- ## Refresh token `POST /auth/token/refresh` Refresh token to get the new access token --- ## Upgrade to custom token `POST /auth/token/upgrade` Upgrade the external OIDC ID Token to a Firebase Custom Token which can be used in acquiring for the access token The External OIDC ID Token is the token that is issued by the external OIDC provider (Auth0,KeyCloak, etc) which is used to authenticate the user in the external OIDC provider. This token can be used to upgrade to a Firebase custom token which can be used to exchange for an access token to Intervengine Platform. The External OIDC Provider should be configured in the Firebase Console to accept the token from the external OIDC provider. --- ## Create bulk leads (Beta) `POST /bulk-leads` Create bulk leads. --- ## Search contents `POST /contents/search` Search Contents --- ## View content `GET /contents/{id}` View a content --- ## Search embeddable cards `POST /participants/{user_id}/embeddable_cards/search` Search embeddable cards assigned to the participant --- ## Create event `POST /events` Create an external event The event will be processed asynchronously and the response will be returned immediately. In order to send the event, the request must contain the following headers: - X-Api-Key: The API key to identify the caller - X-Signature: The HMAC signature of the request body The HMAC signature is generated by hashing the request body with the given secret key. Ask the administrator for the secret key. Here are examples of how to generate the HMAC signature In Go: ```go "crypto/hmac" "crypto/sha256" "encoding/hex" ) func generateHMAC(secret, body string) string { mac := hmac.New(sha256.New, []byte(secret)) mac.Write([]byte(body)) return hex.EncodeToString(mac.Sum(nil)) } ``` In Python: ```python def generate_hmac(secret, body): return hmac.new(secret.encode(), body.encode(), hashlib.sha256).hexdigest() ``` In Node.js: ```javascript const crypto = require('crypto'); function generateHMAC(secret, body) { return crypto.createHmac('sha256', secret).update(body).digest('hex'); } ``` In Ruby: ```ruby require 'openssl' def generate_hmac(secret, body) OpenSSL::HMAC.hexdigest('SHA256', secret, body) end ``` In Java: ```java public class HMACGenerator { public static String generateHMAC(String secret, String body) { try { Mac mac = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); mac.init(secretKeySpec); byte[] hash = mac.doFinal(body.getBytes()); return new String(hash); } catch (Exception e) { e.printStackTrace(); return null; } ``` --- ## Search extras `POST /extras/search` Search all available extra fields --- ## Intervengine Application API ## A RESTful API for the Intervengine application. **®Intervengine** recreates personalised coaching experiences through engaging digital journeys, achieving behaviour change at a fraction of the cost of traditional coaching. Improve the health and wellbeing of your customers, patients, employees or members with our behaviour change tools, evidence-based content library and self-service journey builder. Create and manage your health and wellness programmes and configure adaptive digital journeys that can sense and respond to each person’s unique goals and coaching needs. ### Changes from 1.3.2 The ActivityValue schema has been updated. MeasureTypeContent has now been integrated into ActivityValue, allowing you to create questionnaires that include a mix of both questions and content. Please refer to the ActivityValue and MeasureTypeContent schema documentation for more details. - MeasureTypeContent has been embedded in ActivityValue. This represents a single page content - Removed the redundant valueDataType field in ActivityValue schema. Use measureDataType instead. - Removed the experimental contentId field in ActivityValue schema. Use the embedded content instead. ### Changes from 1.3.0 Request parameters changed at api/v1/participants/\{user_id\}/enrolments - Added 'interventionStartFrom' and 'interventionEndAt' fields to a journey enrolment parameter. This will be used to set the preferred intervention start and end hours for the participant. - Deprecated preferredReminderHour and preferredReminderMin fields from the journey enrolment parameter. ### Changes from 1.2.x **Deprecated Endpoints** - POST /admin/participants (User /participants to create a new participant instead) - GET /participants/\{user_id\}/activity_plans/\{id\}/data - GET /participants/\{user_id\}/activity_plans/all/latest - PUT /participants/\{user_id\}/survey_responses - PUT /participants/\{user_id\}/activity_responses (Use PUT /participants/\{user_id\}/activity_plan_cards/\{id\}/responses instead) - PUT /participants/\{user_id\}/responses/undo Use (DELETE /participants/\{user_id\}/activity_plan_cards/\{id\}/responses instead) **New Endpoints** The following new endpoints have been added. Please refer to the API documentation for more details - GET /participants/\{user_id\}/chat_sessions/\{id\} - POST /participants/\{user_id\}/chat_sessions/search - POST /participants/\{user_id\}/chat_messages/search - POST /participants/\{user_id\}/chat_messages - POST /participants/\{user_id\}/chat_unread_messages/search **Participant Schema** - 'participantTags'' field has changed to 'tags' - 'participantExtras' field has changed to 'extras' - 'participantGroups' field has changed to 'groups' ** Changes in PATCH /participants/\{user_id\}/profile_photo endpoint** 'file' field has changed to 'filename' by default. This can be changed by providing 'name' field to change the name of the form file field if required ![Intervengine Journey](https://i0.wp.com/intervengine.com/wp-content/uploads/2023/11/Website_Journey_Graph-1.png?w=1600&ssl=1) Security Scheme Type: apiKey Header parameter name: X-API-Key Security Scheme Type: http HTTP Authorization Scheme: bearer Bearer format: JWT ### Contact Intervengine Dev Team: [andy@intervengine.com](mailto:andy@intervengine.com) URL: [https://intervengine.com](https://intervengine.com) ### Terms of Service ### License Proprietary --- ## Create a new lead (Beta) `POST /leads` Create a new lead. --- ## Setup a nudge journey `POST /nudges` Setup a nudge journey for the participant. This will create a nudge journey and enrol the participant to the journey. --- ## Request a nudge for a participant `GET /nudges/for/{user_id}` Request a nudge for the participant. This will generate a series of nudges based on the participant activity data. --- ## Approve chat session member `PUT /participants/{user_id}/chat_sessions/{session_id}/members/{id}/approve` Approve a chat session member. This will approve the member to join the chat session. 'id'' is the session member id --- ## Consent terms and conditions `POST /participants/{user_id}/consent` Consent terms and conditions --- ## Create a new token `POST /participants/{user_id}/tokens` Create a new token for the participant. A token can contain any key value data in the payload. --- ## Create new participant `POST /participants` Create new participant. No Access token is required for this endpoint --- ## Delete participant `DELETE /participants/{user_id}` Delete participant --- ## Enrol in journey `POST /participants/{user_id}/enrolments` Enrol and Start a journey. --- ## Get activity data `GET /participants/{user_id}/activities/{id}/data` Get activity data. Fetch the participant's all activity data between from date and to date for a given activity type. The response contains the activity type and its measure types along with activity data during the given timeframe. The maximum date range is allowed to be 1 year. --- ## Get participant by external ID `GET /participants/{external_id}/by/external_id` Get participant by external ID --- ## Get health measures `GET /participants/{user_id}/health_measures/{id}/data` Get health measure data. Fetch the participant's all health measure data between from date and to date for a given activity type. The response contains the health measure types during the given timeframe. The maximum date range is allowed to be 1 year. --- ## Get all latest activities `GET /participants/{user_id}/activities/all/latest` Get activity data. Fetches a list of participant's latest activities. Currently, it returns only the GENERAL_ACTIVITY type. The query option groups can be used to filter the data by the activityType group. The available groups are PYSHICAL | RESPONSE | ADHERENCE | MEASUREMENT eg) /activities/all/latest?groups=ADHERENCE,MEASUREMENT If groups are not provided, then it will just return the latest activity data regardless of its activityType group. --- ## Get all latest health measures `GET /participants/{user_id}/health_measures/all/latest` Get all the latest health measures --- ## Get participant `GET /participants/{user_id}` Get participant --- ## Hide activity plan card `PUT /participants/{user_id}/activity_plan_cards/{id}/hide` Hide activity plan card, Marked the card invisible to the participant --- ## Join chat session `PUT /participants/{user_id}/chat_sessions/{id}/join` Join a chat session with session id [Requires Coach Access Token] If the chat session is locked then the coach needs to be approved by the coach or other participants in the chat session. --- ## Leave a chat session `PUT /participants/{user_id}/chat_sessions/{id}/leave` Leave a chat session with session id [Requires Coach Access Token] --- ## Lock chat session `PUT /participants/{user_id}/chat_sessions/{id}/lock` Lock a chat session with session id Requires the coach access token. This will lock the chat session so that no one can join the chat session without the approval from the coach or participant who are already in the chat session. --- ## Pause journey `PUT /participants/{user_id}/enrolments/{id}/pause` Pause the enrolled journey. --- ## Reject chat session member `PUT /participants/{user_id}/chat_sessions/{session_id}/members/{id}/reject` Reject a chat session member. This will reject the member to join the chat session. 'id'' is the session member id --- ## Remove participant extra `DELETE /participants/{user_id}/extras` Remove participant extra. This will detach the extra field(s) from the participant. --- ## Report on activity plan (ad-hoc report) `POST /participants/{user_id}/activity_plans/{id}/responses` Report on activity plan for the participant --- ## Report activity `PUT /participants/{user_id}/activity_plan_cards/{id}/responses` Report activity for the activity plan card 'responses' field is optional and can be null if there is no response for the activity card such as a content card. In this case, it will just mark the content card as read. --- ## Report health measure. `POST /participants/{user_id}/health_measures` :::caution deprecated This endpoint has been deprecated and may be replaced or removed in future versions of the API. ::: Report health measure for the participant. Deprecated, use /activity_plans/\{id\}/responses --- ## Resume journey `PUT /participants/{user_id}/enrolments/{id}/resume` Resume the paused journey. --- ## Revoke a token `DELETE /participants/{user_id}/tokens/{id}` Revoke an existing token for the participant. --- ## Search activity plans `POST /participants/{user_id}/activity_plans/search` Search activity plans 'include_data'' is an optional query parameter to include the activity plan card data in the response. --- ## Search activity plan cards `POST /participants/{user_id}/activity_plan_cards/search` Search activity plan cards assigned to the participant --- ## Search journeys `POST /participants/{user_id}/journeys/search` Search self-enrollable journeys with a specific criteria. When the "isEnrolled" property is null or not included, all journeys, both enrolled and non-enrolled, will be returned. If "isEnrolled" is set to true, the search result will include only the journeys that the participant is currently enrolled in. In this case, the 'latestJourneyId' can be higher than journeyId. This means that there is a newer version of the journey and can be upgraded by specifiying "journeyIdToUpgrade": "$\{latestJourneyId\}" in the enrolment request payload. If it is same id (i.e same version) then leave 'journeyIdToUpgrade' to null. Conversely, if "isEnrolled" is set to false, the search result will include only the non-enrolled journeys available for the participant, i.e., all journeys that can be enrolled by the participant. By default, the search will return only self-enrolled journeys. To include non-self-enrolled (prescribed) journeys in the search results, set 'includePrescribed' to true in the query option. --- ## Search chat messages `POST /participants/{user_id}/chat_messages/search` Search chat messages in the session --- ## Search chat sessions `POST /participants/{user_id}/chat_sessions/search` Search chat sessions with criteria --- ## Search chat unread messages `POST /participants/{user_id}/chat_unread_messages/search` Search chat unread messages for the participant --- ## Post chat message `POST /participants/{user_id}/chat_messages` Post a new chat message in the session. A participant can post a message to the chat session members(coach or other participants) in the session. If the current authenticated user is an admin or connector then the message will be posted as the participant with \{user_id\}. --- ## Show activity plan card `PUT /participants/{user_id}/activity_plan_cards/{id}/show` Show activity plan card. Marked the card visible to the participant --- ## Start journey `PUT /participants/{user_id}/enrolments/{id}/start` Start the enrolled journey. --- ## Stop journey `PUT /participants/{user_id}/enrolments/{id}/stop` Stop the enrolled journey. --- ## Open chat session stream `GET /participants/{user_id}/chat_sessions/{id}/stream` Open a new chat session stream to listen for new chat events on a single chat session from the server. This is a supplementary endpoint to the /participants/\{user_id\}/stream endpoint to support the secondary stream for chat messages. This will be useful to create an application which requires a separate stream for a main participant stream and a specific chat session. For example, - a main stream for dealing with the participant's activity cards and an incoming chat message but remains unread until the participant open the chat session. - a second stream for a specific chat session to listen for new chat messages in the chat session and mark the message as read - the second stream should be closed when the participant leaves the chat session or switches to another session The server sends the Server Sent Event in plain text to the client in this format when there is an event. ` data: \{"eventType": "MESSAGE_SENT", payload: [.....] \} ` EventTypes **KEEP_ALIVE** This will be issued every 15 seconds to the client so the connection is kept open. you can simply ignore this. **MESSAGE_SENT** This will be issued when there is a message sent from the server. This can be used for building a chat application The payload for this event can be found from api/v1/docs#/schemas/ChatMessage **CHAT_SESSION_MEMBER_REQUESTED** This will be issued when a coach tried to join a locked chat session. **CHAT_SESSION_MEMBER_JOINED** This will be issued when a new member joins the chat session. **CHAT_SESSION_MEMBER_LEFT** This will be issued when a member leaves the chat session. payload for these events will have the following structure ` \{ "sessionId": "string", "participantId": "string", "memberId": "string", "memberType": "string", "memberName": "string", "photoUrl": "string or null" \} ` **CHAT_SESSION_MEMBER_APPROVED** This will be issued when an existing session member approves the coach to join the chat session. **CHAT_SESSION_MEMBER_REJECTED** This will be issued when an existing session member rejects the coach to join the chat session. The payload for these events will have the following structure ` \{ "sessionId": "string", "participantId": "string", "memberId": "string", "memberType": "string", "memberName": "string", "approvedBy": "string", // or "rejectedBy": "string" \} ` ** It is recommended to use EventSourcePolly from https://github.com/Yaffle/EventSource This will extend the EventSource to have Headers for the auth token. ```js sse = new EventSourcePolyfill(streamURL, { headers: { "Authorization": "Bearer ${authToken}", "X-API-Key": "${apiKey}" } }); ``` --- ## Open participant stream `GET /participants/{user_id}/stream` Open a new participant stream to listen for new events from the server. The server sends the Server Sent Event in plain text to the client in this format when there is an event. ` data: \{"eventType": "ACTION_PLAN_CARDS_ADDED", payload: [.....] \} ` EventTypes **KEEP_ALIVE** This will be issued every 15 seconds to the client so the connection is kept open. you can simply ignore this. **MESSAGE_SENT** This will be issued when there is a message sent from the server. This can be used for building a chat application The payload for this event can be found from api/v1/docs#/schemas/ChatMessage **ACTION_PLAN_CARDS_ADDED** This will be issued when a new activity card is created from the backend. This is the event to render a card ( one-off activity or a message card ) or cards (if the payload has more than one item) The payload of this event can be found from the /activity_plan_cards/search **ACTION_PLAN_CARD_RESPONDED** This will be issued when a participant responds to an activity card. The payload of this event can be found from the /activity_plan_cards/search **CHAT_SESSION_MEMBER_REQUESTED** This will be issued when a coach tried to join a locked chat session. **CHAT_SESSION_MEMBER_JOINED** This will be issued when a new member joins the chat session. **CHAT_SESSION_MEMBER_LEFT** This will be issued when a member leaves the chat session. payload for these events will have the following structure ` \{ "sessionId": "string", "participantId": "string", "memberId": "string", "memberType": "string", "memberName": "string", "photoUrl": "string or null" \} ` **CHAT_SESSION_MEMBER_APPROVED** This will be issued when an existing session member approves the coach to join the chat session. **CHAT_SESSION_MEMBER_REJECTED** This will be issued when an existing session member rejects the coach to join the chat session. The payload for these events will have the following structure ` \{ "sessionId": "string", "participantId": "string", "memberId": "string", "memberType": "string", "memberName": "string", "approvedBy": "string", // or "rejectedBy": "string" \} ` **PARTICIPANT_EXTRA_VALUE_CHANGED** This will be issued when a participant extra value is changed. The payload for these events will have the following structure ` \{ "updatedAt": "2025-09-30T22:06:08Z", "extraCode": "EXTRA_A_2S21", "extraGroup": "PARTICIPANT", "extraName": "Extra A", "extraValue": "Testing SSE", "id": "3", // extra ID "participantId": "40" \} ` ** It is recommended to use EventSourcePolly from https://github.com/Yaffle/EventSource This will extend the EventSource to have Headers for the auth token. ```js sse = new EventSourcePolyfill(streamURL, { headers: { "Authorization": "Bearer ${authToken}", "X-API-Key": "${apiKey}" } }); ``` --- ## Undo activity reporting `DELETE /participants/{user_id}/activity_plan_cards/{id}/responses` Undo activity reporting for the activity plan card --- ## Undo Health Measure reporting `DELETE /participants/{user_id}/health_measures/{id}` Undo reporting for the Health Measure --- ## Unlock chat session `PUT /participants/{user_id}/chat_sessions/{id}/unlock` Unlock a chat session with session id Requires the coach access token. The chat session will be public and anyone can join the chat session. --- ## Change participant email `PATCH /participants/{user_id}/email` Change participant email --- ## Change participant's external ID `PATCH /participants/{user_id}/externalId` Change participant external ID. This is used to link the participant with an external system. --- ## Save participant extra value `PATCH /participants/{user_id}/extras` Save a participant extra value --- ## Save participant extra values `PATCH /participants/{user_id}/extras/{extra_group}` Save participant multiple extra values in a group --- ## Change participant mobile `PATCH /participants/{user_id}/mobile` Change participant mobile Change the participant's mobie number. The mobile number should starts with +\{country_code\} and the mobile number should not have the leading 0 eg) +6421234567 --- ## Change participant password `PATCH /participants/{user_id}/password` Change participant password --- ## Change participant preferences `PATCH /participants/{user_id}/preferences` Change participant preferences --- ## Change participant profile photo `PATCH /participants/{user_id}/profile_photo` Change participant profile photo 'filename' field is expected in form data as a name of form file field. If form 'name' is provided then it will use that name as the name of the form file field instead. Example in cURL: curl --request PATCH \ --url http://localhost:8080/api/v1/participants/1/profile_photo \ --header 'Accept: application/json, application/problem+json' \ --header 'Authorization: Bearer \{bearer_token\}' \ --header 'Content-Type: multipart/form-data' \ --header 'X-API-Key: \{api_key\}' \ --form filename=@gopher8.png --form name=profile_photo --- ## Change participant `PUT /participants/{user_id}` Change participant profile --- ## View activity plan `GET /participants/{user_id}/activity_plans/{id}` View an activity plan --- ## View chat session `GET /participants/{user_id}/chat_sessions/{id}` View a chat session with session id --- ## Validate an identity token `GET /tokens/{id}` Validate an IDENTITY token and return the associated participant ID. This is a public endpoint that does not require authentication. Returns 404 if the token is not found or is not an IDENTITY type. Returns 400 if the token is expired, revoked, or missing participantId in payload. --- ## App Overview # Intervengine App The Intervengine App is the participant-facing mobile application. It delivers cards, tracks health data, and connects participants with their coaches - all configured and managed from the Portal. The app is white-labeled per organization with custom branding, colors, and fonts. It is available on iOS and Android. [Try the Demo App →](https://intervengine-demo.app.link) ## Key Capabilities - **Adaptive Journeys** - receive personalized cards that adapt based on responses, health data, and progress - **Health Tracking** - record health measures and view device-collected biomarkers like steps, sleep, and heart rate - **Coach Messaging** - communicate with coaches in real-time chats - **Self-Paced Content** - access educational materials, videos, and resources at any time ## How Cards Reach the App Cards are the core unit of content in Intervengine. Coaches create cards in the Portal, then deliver them to participants either manually via activity plans or automatically via Journeys. The app receives these cards and presents them on the Feed for participants to view and complete. ### [Feed](./feed) The main home screen. View and complete assigned cards - health measures, health area cards, recurring cards, and one-off cards. ### [Explore](./explore) Browse and self-enroll in journeys, revisit recent content, and manage active enrollments. ### [Progress](./progress) Health measures, device scores, device biomarkers, and activity results tracked over time. ### [Chats](./chats) Message coaches and receive automated journey messages in organized chats. ### [Settings](./settings) Profile, sign-in credentials, reminder times, legal documents, and account management. :::info Integrations The app connects with third-party services to extend its capabilities. Device health data is collected via [Sahha](/integrations/sahha), guided exercise content is delivered through [KinesteX](/integrations/kinestex). ::: :::tip Build Your Own App Organizations can build a fully custom app experience using the [React Native SDK](/sdk/sdk-intro). The SDK provides access to the same Intervengine backend - cards, journeys, health data, and messaging - within your own app. ::: --- ## Chats # Chats Chats is the communication hub - message coaches and receive automated journey messages. :::info Participants cannot initiate chats. Only coaches and journeys can start a chat with a participant. Multiple coaches can each have their own chat with the same participant, and multiple coaches can participate in the same chat. ::: ## Overview Conversations are organized into **chats**. Each chat is a separate thread. ### Coach Chats Direct conversations with assigned coaches: - **Two-way communication** - Both can send messages once the chat is started - **Full text input** - Type any message ### Journey Chats Automated messages from journeys: - **Structured flow** - Predefined message sequence - **No text input** - Input field hidden - **Responses** - Participants can select response options to interact with the Journey - **Automated delivery** - Triggered by journey states Includes welcome messages, progress updates, reminders, and tips. --- ## Configuration Reference # Configuration Reference All configuration values are compile-time constants. Changing them requires a rebuild of the app. ## App | Config | Type | Default | Description | | ------------------------------- | ---- | ------- | -------------------------------------------------------------- | | `SHOW_FOREGROUND_NOTIFICATIONS` | bool | `true` | Display push notifications while the app is in the foreground. | ## Feed | Config | Type | Default | Description | | --------------------------------- | ---- | --------- | --------------------------------------------------------------------------------------------------------------- | | `HOME_SCREEN_TEMPLATE` | enum | `V2` | Home screen layout. `V1` includes an inline calendar, `V2` is a scrollable feed with a separate history screen. | | `IS_MULTI_ORG` | bool | `false` | Whether the app supports multiple organisations. | | `SORT_HOME_MOST_RECENT` | bool | `true` | If true, cards are sorted newest-first. If false, oldest-first. | | `SHOW_HOME_HEALTH_MEASURES_FIRST` | bool | `true` | If true, the Health Measures section appears at the top of the feed. If false, at the bottom. | | `SHOW_HOME_FOOTER` | bool | `true` | Display the "That's all for now!" message at the bottom of the feed. | | `DISPLAY_CUSTOM_HOME_TITLE` | bool | `false` | Replace the default "Home" title with a custom widget. | | `DISPLAY_CUSTOM_HOME_FOOTER` | bool | `false` | Show a custom footer widget below the feed content. | | `DISPLAY_TODO_ICON` | bool | `false` | Display the app icon in the feed header. | | `DISPLAY_TODO_DATE` | bool | `true` | Show the current date in the feed title (e.g. "Home (Thu Feb 12)"). | | `HOME_HEALTH_SCORES` | list | `[SAHHA]` | Which health score sections to show on the feed. Options: `SAHHA`, `SYMPTOMS`. | ## Activity Cards | Config | Type | Default | Description | | -------------------------------- | ---- | ------- | ------------------------------------------------------------------------------------------------------ | | `HIDE_SUBTITLE_IN_ACTIVITY_CARD` | bool | `true` | Hide the type/schedule subtitle line (e.g. "Content - Morning - Goal Name") on activity cards. | | `USE_SUBJECTIVE_ACTION_ICON` | bool | `true` | If true, Yes/No responses use distinct icons (check for Yes, X for No). If false, both use check. | | `FULL_WIDTH_ACTIVITY_CARDS` | bool | `false` | If true, cards render edge-to-edge without side padding. If false, cards appear as floating cards. | | `SQUARE_BORDER_ACTIVITY_CARDS` | bool | `false` | If true, cards have square corners. If false, cards have rounded corners. | | `FULL_WIDTH_CATEGORICAL_BUTTONS` | bool | `false` | If true, categorical response buttons span the full card width. | | `USE_ROUNDED_BUTTONS` | bool | `true` | Whether buttons use rounded styling. | | `ALLOW_CARD_DISMISS` | bool | `true` | Whether users can swipe cards to dismiss them. Only applies to cards where `isDismissible` is enabled. | ## Progress | Config | Type | Default | Description | | ---------------------------- | ---- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `PROGRESS_CHARTS_ORDER` | list | `[HealthMeasure, Biomarker, ActivityPlan]` | Order of chart sections on the Progress screen. Options: `HealthMeasure`, `Biomarker`, `ActivityPlan`, `OneOff`. | | `PROGRESS_CHART_DATE_RANGES` | list | `[ONE_WEEK, FOUR_WEEKS, THREE_MONTHS, SIX_MONTHS]` | Date range filter tabs. Options: `ONE_WEEK`, `FOUR_WEEKS`, `THREE_MONTHS`, `SIX_MONTHS`, `ONE_YEAR`. | | `SHOW_ONE_OFF_ACTION_CHARTS` | bool | `false` | Whether to include one-off activities in progress charts. | | `ONE_OFF_CHART_FILTERS` | list | `[]` | Chart filters for one-off activity charts. | ## Authentication | Config | Type | Default | Description | | ----------------------------- | ---- | ---------------- | ------------------------------------------------------------------------------ | | `AUTH_STRATEGIES` | list | `[PHONE, EMAIL]` | Which authentication methods are available. Order determines display priority. | | `ALLOW_SIGN_UP` | bool | `true` | Whether new user registration (self-registration) is available. | | `SHOW_SIGN_UP_OPTION_FIRST` | bool | `false` | If true, the sign-up form is shown by default instead of the login form. | | `INCLUDE_GENDER_IN_SIGN_UP` | bool | `true` | Whether to include a gender field in the sign-up form. | | `INCLUDE_DOB_IN_SIGN_UP` | bool | `true` | Whether to include a date of birth field in the sign-up form. | | `ENABLE_BIOMETRIC_LOCAL_AUTH` | bool | `false` | Enable biometric authentication (Face ID / fingerprint). | | `ALLOW_CONSENT_CANCELLATION` | bool | `true` | Whether users can back out of the consent screen. | ## Onboarding and Alerts | Config | Type | Default | Description | | ----------------------------- | ---- | ------- | ---------------------------------------------------------- | | `SHOW_INTRODUCTION_SCREENS` | bool | `true` | Show the onboarding/introduction flow on first launch. | | `SHOW_COMPLIANCE_POPUP` | bool | `false` | Display a compliance warning before opening external URLs. | | `SHOW_CUSTOM_APP_START_ALERT` | bool | `false` | Show a custom alert dialog on every app start. | | `SHOW_FIRST_APP_START_ALERT` | bool | `false` | Show a one-time alert on the very first app launch. | ## Sahha Integration | Config | Type | Default | Description | | ---------------------------- | ---- | ------------------- | --------------------------------------------------------------------------------------------------------------------- | | `ENABLE_SAHHA_INTEGRATION` | bool | `true` | Master toggle for Sahha SDK health data integration. | | `USE_SAHHA_UI_WIDGETS` | bool | `true` | Use Sahha's built-in UI widgets for displaying health data. | | `ENABLED_SAHHA_SENSORS` | list | 12 sensors | Which device sensors to request data from (heart rate, HRV, blood pressure, glucose, floors, activity, sleep, steps). | | `ENABLED_HEALTH_BIOMARKERS` | list | 11 biomarkers | Which biomarker types to display in charts and summaries. | | `ENABLED_SAHHA_SCORES` | list | `[activity, sleep]` | Which Sahha wellness scores to fetch and display. | | `ENABLED_SAHHA_INTEGRATIONS` | map | `{GARMIN: false}` | Third-party device integrations. Currently only Garmin is supported. | | `INFERENCE_SCORE_CHART_TYPE` | enum | `LINEAR` | Score display style. `LINEAR` (horizontal bar) or `RADIAL` (circular gauge). | | `SHOW_INFERENCE_IN_PROGRESS` | bool | `true` | If true, inference scores appear on the Progress screen. If false, they appear on the Feed. | --- ## Explore # Explore Explore is the discovery and management hub for journeys. Browse available journeys, revisit recent content, and control active enrollments. ## Discover - Browse journeys marked as **self-enrollable**. Tap a journey to view details, then tap **Enroll** to start receiving cards in your Feed. - Access previously accessed content, sorted by last viewed. Useful for revisiting educational materials or shared resources. ## Manage Control active journey enrollments. Pause, resume, stop, or restart journeys as needed. - **Pause** - temporarily stops the journey - **Resume** - continues the journey from where it was paused - **Stop** - ends the journey (can be restarted) - **Restart** - begins the journey again from the start --- ## Feed # Feed The Feed is the main home screen - where participants view, complete, and track their assigned cards. Cards are assigned either manually by coaches from the Portal or automatically via Journeys. See the [Configuration Reference](./configuration#feed) for feed layout and card display options. Cards on the Feed are organised into three sections: - **Health Measure Cards** - shown as individual cards - **Health Area Cards** - grouped by health area - **Recurring Cards** - grouped by time of day - **One-Off Cards** - shown as individual cards ## Fullscreen Cards Fullscreen cards take priority over everything else. When an unanswered fullscreen card exists, it takes over the entire home screen, replacing the normal feed. The card's title and response controls are displayed in a full-page layout. Participants must respond before the regular feed becomes visible again. If multiple fullscreen cards are pending, they are shown one at a time in scheduled order. Fullscreen cards are never shown in the regular feed list or in Feed History. ## Health Measure Cards Health Measure cards appear in their own section on the Feed rather than as regular cards. The section displays a summary dashboard of tracked health metrics inside a single card, with a heading that links to the full Progress screen. Each row shows an icon for the measure type, the measure name, and the most recent reported value. If a value has been recorded, the time since the last entry and the unit of measurement are shown beneath it. If no data has been recorded yet, a placeholder is displayed. Tapping a row navigates to the Add Health Measure screen for that measure type, where participants can record a new reading. The section only appears if health measures are configured - otherwise it is hidden entirely. ## Health Area Cards Cards assigned to a health area are grouped under headings showing the health area name, sorted by their configured display order. Within each health area, cards are sorted by the health area's configured sort field and direction. Each health area can use one of three display styles: ### Carousel Cards scroll horizontally, each showing the card image, name, and description. This is the default style. ### Compact List All cards appear as rows inside a single card with thumbnail images, card names, and completion indicators. ### List Cards appear as full-size individual cards stacked vertically. ## Recurring Cards Recurring cards that are not assigned to a health area are grouped under time-of-day headings - Morning, Midday, Afternoon, Evening, and Night - displayed in chronological order. Each group appears as a compact list inside a single card showing a thumbnail image (if available), the card name, and a completion indicator. Tapping a row opens the card for the participant to respond. ## One-Off Cards One-off cards that are not assigned to a health area appear as individual cards below the other sections, sorted with the most recently created first and incomplete cards before completed ones. One-off cards use different layouts depending on their configuration: - **Standard** - full-width header image, type label, card name, description, and response controls. The header image is hidden after completion. - **Compact** - full-width header image with a response button overlaid on the image, with title and description below. Falls back to Standard if no image is set. - **Slim** - side-by-side layout with text on the left and a small square image on the right. Completed cards show a checkmark instead of the description. Once completed, Standard and Compact cards switch to a condensed view showing the card name, a check icon, and a summary of the response. ## Dismissing and Undoing If enabled, participants can swipe a card to the left to reveal a Dismiss button. Dismissed cards are hidden from the Feed but remain visible in Feed History. Completed cards can also be swiped to reveal an Undo button to retract the response. ## Persistent Cards Some cards are marked as persistent. These remain visible on the Feed even after a participant has responded, allowing multiple responses over time. ## External Link If configured, an external link icon appears in the feed header. This can direct participants to external services such as appointment booking or a shop page. ## Feed History Feed History provides a calendar-based view of all cards across any date. Tap the clock icon in the top-left corner of the Feed to open it. A week-strip calendar at the top can be expanded to a full month view by dragging down. Tap any date to view that day's cards, or swipe left and right to move between weeks. Cards are grouped by time of day, just like recurring cards on the Feed. Each row shows a thumbnail image, the card name, and a completion indicator. - **Completed cards** appear on the date they were completed - **Incomplete cards** appear on every date between their scheduled date and expiration date (or today if no expiration is set) - **Recurring cards** appear on the date they were scheduled Dismissed cards appear faded out in Feed History with a badge showing the count of hidden cards. Tapping a hidden card lets participants toggle its visibility back on. Participants can tap any card in Feed History to open it and submit or re-submit a response, even on past days. --- ## Onboarding # Onboarding The onboarding flow guides new participants through account setup and app introduction. See the [Configuration Reference](./configuration#authentication) for authentication and sign-up options. ## Splash & Welcome Screens The splash screen displays while the app loads. By default, shows the app icon unless a custom splash screen is configured. A series of introductory screens are then presented on first launch. ## Sign In Participants are presented to the welcome screen and must accept the Privacy Policy and Terms & Conditions, they can then can attempt to sign in using their mobile number or email address (If enabled). ### What Happens Next After entering their mobile or email, the system checks if the user exists: - **Existing user** - asked to verify via a one-time verification code or their email password, then directed to the home screen - **New user with self-registration enabled** - prompted to set up their profile, sign in and accept consent - **New user with self-registration disabled** - shown an error and returned to the Welcome Screen ### Consent New participants that have not signed in before are prompted to review and accept Privacy Policy and Terms & Conditions. ## After Onboarding On successful sign in: 1. Participant is directed to the Feed 2. The `PARTICIPANT_CONSENTED` journey signal fires 3. Any onboarding journeys begin delivery --- ## Progress # Progress Progress tracks participant health data and activity results across four sections. See the [Configuration Reference](./configuration#progress) for chart ordering and date range options. ## Your Health Measures Results from completed Activity Cards, including self-reported health measure entries such as weight, mood, and pain levels. ## Device Scores High-level health scores derived from device sensor data, such as overall activity and sleep quality scores. Score modals are displayed using [Sahha Widgets](https://docs.sahha.ai/docs/products/widgets) - pre-built UI components that render score charts, arcs, and contributing factors directly in the app. :::info Requires the [Sahha integration](/integrations/sahha) and participant health permissions to be enabled. ::: ## Device Biomarkers Detailed health metrics collected automatically from device sensors, including steps, sleep, heart rate, HRV, blood pressure, glucose, and floors climbed. :::info Requires the Sahha integration and participant health permissions to be enabled. ::: ## Your Activities Responses and scores from completed Activity Cards, including surveys, check-ins, and assessments. --- ## Settings # Settings Participants manage their personal information, notification preferences, and access legal documents from Settings. ## Update Profile, Update Phone Update Password or Delete Account Participants can: - View and update their profile information or Permanently delete their account. (This requires phone verification, after which all personal data is removed from the backend and the local cache is cleared.) - View and update theirmobile number used for SMS authentication. - View and update their password used for email authentication. :::warning Account deletion is permanent and irreversible. ::: ## Reminders Participants set preferred times for four daily reminder slots: Morning, Midday, Afternoon, and Evening. Cards scheduled for a given slot are delivered at the participant's chosen time. :::info Coaches configure which days and times activities are scheduled, but the delivery time is controlled by the participant's reminder settings. ::: ## Privacy Policy & Terms & Conditions View the Privacy Policy & Terms & Conditions accepted during onboarding. See [Privacy - Intervengine](https://intervengine.com/privacy/) and [Terms - Intervengine](https://intervengine.com/terms/). ## About Intervengine Displays the current app version and build number. ## Sign Out Signs out and returns to the onboarding screen. :::tip Signing out doesn't delete data. Sign back in anytime to continue. ::: --- ## Style Reference # Style Reference Style values that are typically customized per client. These are compile-time constants and require a rebuild to change. ## Brand Colors | Config | Default | Description | | ----------------- | ------------------------- | -------------------------------------------------------------- | | `PRIMARY_COLOR` | `rgb(0, 10, 46)` navy | App bar, feed background, avatars. The main brand color. | | `SECONDARY_COLOR` | `rgb(115, 237, 230)` teal | Active navbar tab highlight. | | `UTILITY_COLOR` | `rgb(53, 92, 222)` blue | Buttons, links, switches, loading spinners, and form controls. | ## Fonts | Config | Default | Description | | -------------------- | ---------- | --------------------------- | | `FONT_FAMILY` | `'Averta'` | Base font used app-wide. | | `HEADER_FONT_FAMILY` | `'Averta'` | Screen titles, card titles. | ## Theme Mode | Config | Default | Description | | ------------------------------ | --------------- | ---------------------------------------------------------------------------------------------- | | `IS_NAV_BAR_DARK_MODE` | `true` | Dark styling on the app bar. | | `IS_HOME_DARK_MODE` | `true` | Dark background and light text on the feed screen. | | `HOME_SCREEN_BACKGROUND_COLOR` | `PRIMARY_COLOR` | Feed screen background. Override separately for a different background than the primary color. | ## Cards | Config | Default | Description | | ----------------------- | ------------------------ | --------------------------------------------------------- | | `CARD_BACKGROUND_COLOR` | `white` | Activity card surface color. | | `CARD_BORDER_COLOR` | `transparent` | Card border. Set to a color to add visible card outlines. | | `SUCCESS_COLOR` | `rgb(40, 117, 68)` green | Completed activity check icon color. | ## Buttons | Config | Default | Description | | ------------------------------ | ----------------- | ---------------------------------- | | `SELECTED_BUTTON_COLOR` | `UTILITY_COLOR` | Active/selected button background. | | `SELECTED_BUTTON_TEXT_COLOR` | `white` | Active button text. | | `UNSELECTED_BUTTON_COLOR` | `white` | Inactive button background. | | `UNSELECTED_BUTTON_TEXT_COLOR` | `rgb(29, 37, 45)` | Inactive button text. | ## Navbar | Config | Default | Description | | ----------------------- | ------------------------- | -------------------------- | | `NAVBAR_ACTIVE_COLOR` | `SECONDARY_COLOR` | Selected tab icon/label. | | `NAVBAR_INACTIVE_COLOR` | `rgb(136, 139, 141)` grey | Unselected tab icon/label. | ## Charts | Config | Default | Description | | -------------- | ------- | -------------------------------------------------------------------------- | | `CHART_COLORS` | `[]` | Custom palette for progress chart categories. Empty uses library defaults. | --- ## App Configuration Best Practices # App Configuration Best Practices Recommendations for administrators and coaches setting up the Intervengine App. ## Branding ### Logo Your logo appears on device home screens and loading screens. Use a simple, high-contrast design in square format (512x512px SVG). Avoid text in the logo - it becomes illegible at small sizes. :::tip Test your logo at 48x48 pixels. If it's still recognizable, it will work well as an app icon. ::: ### Colors The app uses three brand colors: - **Primary** - headers, footers, and major UI elements. Should have sufficient contrast with white text. - **Secondary** - buttons and calls-to-action. Should stand out against Primary. - **Tertiary** - links and secondary actions. A lighter or accent shade works well. :::warning Avoid very light colors for Primary or Secondary - buttons and text may become illegible. Always test in the staging app before going to production. ::: ### Typography Prioritize readability on mobile. Choose fonts that match your organization's branding and test on slower connections, as web fonts add load time. ## Onboarding ### Welcome Screens The three welcome screens are your first impression: 1. **The Hook** - State the primary benefit clearly, with compelling imagery and minimal text 2. **How It Works** - Briefly explain features and set expectations 3. **Call to Action** - Motivate participants to get started ### Registration Use **Invitation Only** for controlled programs (clinical trials, corporate wellness). Use **Self Registration** for open programs (public health, consumer apps). ### Sign-In Methods - **SMS OTP** - simplest for participants, no passwords to remember. Good for older adults or less tech-savvy users. - **Email/Password** - traditional authentication. Better for international users (avoids SMS costs). Both methods can be enabled simultaneously. ## Feed - **Sort order** - Use ascending (oldest first) for sequential programs. Use descending (newest first) when recent content is most relevant. - **Card dismissal** - Enable when content is optional or you want to reduce perceived burden. Disable for research studies or when complete data collection is critical. - **External links** - Enable the confirmation prompt so participants know they're leaving the app. ## Journey Management Controls whether participants can pause, resume, stop, or restart their own journeys. **Enable** for self-directed wellness programs where participant autonomy matters. **Disable** for clinical or structured programs where coaches need oversight. :::tip For most programs, enable journey management but encourage participants to "pause" rather than "stop". The flexibility increases satisfaction without significantly increasing dropouts. ::: ## Health Data (Sahha) Only request the sensors you'll actually use - each permission prompt can cause drop-off. Data syncs on-demand when participants view their progress screens, not continuously. **Available scores:** Activity, Sleep **Available sensors:** Heart Rate, HRV, Blood Pressure, Glucose, Steps, Floors Climbed, Activity Summary, Sleep :::info Apple requires an explanation of why health data is collected. Be clear about the benefits to the participant and transparent about how data is used. ::: ## Example Configurations **Corporate Wellness** - Invitation Only, both sign-in methods, journey management enabled, Sahha with steps/sleep/activity. Employees are invited but have flexibility in how they engage. **Clinical Research** - Invitation Only, SMS sign-in, journey management disabled, card dismissal disabled, all relevant Sahha sensors. Maximizes researcher control and data completeness. **Public Health** - Self Registration, both sign-in methods, journey management enabled, card dismissal enabled, minimal Sahha (steps only). Low barrier to entry with maximum participant autonomy. ## Before Launch - Test the full onboarding flow as a new participant - Verify branding renders correctly on iOS and Android - Walk through each app section and test edge cases - Run a pilot with a small group (10–20 participants) and gather feedback - Adjust configuration based on findings before full rollout --- ## App Deletion # App Deletion ## iOS You can remove apps from your iPhone. If you change your mind, you can download the apps again later. 1. Touch and hold the app on the Home Screen 2. Tap **Remove App** 3. Tap **Remove from Home Screen** to keep it in App Library, or tap **Delete App** to delete it from iPhone You can also touch and hold the app in App Library, tap **Delete App**, then tap **Delete**. ## Android Some of these steps work only on Android 13 and up. 1. Open the Google Play Store app 2. Tap the Profile icon at top right 3. Tap **Manage apps & devices**, then **Manage** 4. Select the app name to delete 5. Tap **Uninstall** Deleted or disabled apps can be reinstalled. Purchased apps can be reinstalled without repurchasing. --- ## Staging & Production Environments # Staging & Production Environments Each client deployment has two separate environments: **Production** and **Staging**. These environments are entirely independent — they do not share data, Journeys, Cards, participants, or any other configuration. ## Production Production is the live environment that your participants use. All real participant data, Journeys, and Cards live here. This is the environment your mobile app connects to. ## Staging Staging is a separate environment used for two purposes: - **Testing new Intervengine releases** — when we release a new version of the platform, it is deployed to Staging first so you can verify the update before it goes live. - **Prototyping changes** — you can experiment with Journey designs, Card configurations, and other settings without affecting your live participants. Staging is **not** a journey builder for Production. It is a testing and prototyping space. Changes made in Staging do not automatically flow to Production. ## How Migration Works Migration only goes in one direction: **Production to Staging**. We never migrate from Staging to Production. When a migration is performed: - It is a **one-off reset** of the Staging environment using a copy of Production data. - Journey version numbers are reset to 0 in Staging. - Production is completely unaffected — version numbers, participant data, and all configuration remain as they were. - After the migration, the two environments are independent again. Ongoing changes in one environment are not reflected in the other. :::warning Because migration resets Staging, any in-progress work in Staging will be overwritten. Make sure you have finished testing before requesting a migration. ::: ## Applying Changes to Production If you prototype a Journey or Card change in Staging and want to apply it to Production, you need to **manually recreate the change in Production**. There is no automated sync or push from Staging to Production. This is intentional — it ensures that changes to your live environment are deliberate and reviewed, rather than accidentally pushed from a testing space. ## Why Version Numbers Differ Between Environments Because the environments are independent, version numbers will almost always differ. For example, a Journey might be at v56 in Production and v0 in Staging. This is expected — the version numbers are not related to each other. After a migration from Production to Staging, Staging Journey versions reset to 0 even though Production remains at its current version. Publishing changes in Staging increments from 0 independently of Production. ## Summary - Production and Staging are **completely separate** environments. - Migration goes **Production to Staging only**, as a one-off reset. - Changes in Staging must be **manually applied** to Production. - Different version numbers between environments are **normal and expected**. - Staging is for **testing releases and prototyping**, not for building content that automatically transfers to Production. --- ## Cal.com # Intervengine x [Cal.com](https://cal.com/) :::info[Coming Soon] This integration is currently in development. Details on this page represent the planned functionality and may change before release. ::: # What is Cal.com? Cal.com is open scheduling infrastructure for booking and calendar management. It provides a flexible platform for managing availability, appointment types, and calendar integrations - giving both Participants and coaches full control over scheduling. ## How It Integrates with Intervengine Cal.com connects to Intervengine on both sides of the platform: - **App (Participant-facing):** Participants can browse available time slots and book sessions with their assigned coaches or clinicians directly from the Intervengine App. - **Portal (Coach-facing):** Coaches and clinicians manage their availability, view upcoming appointments, and handle scheduling from within the Intervengine Portal. ## Key Capabilities - **Coaching Sessions:** Participants book one-on-one sessions with their coach or clinician at times that work for both parties - **Clinical Appointments:** Schedule structured clinical consultations as part of a care pathway or Journey - **Follow-up Check-ins:** Automate the scheduling of follow-up appointments at key Journey milestones - **Group Sessions:** Coordinate group-based activities and workshops with multiple Participants :::warning[Paid Integration] Please note that Cal.com is a separate paid integration. You will need an active Cal.com license and API credentials to enable these features within your Intervengine environment. ::: --- ## Integrations Overview # Integrations Intervengine connects with third-party services to extend what you can deliver to participants. Rather than building everything in-house, integrations bring specialized capabilities - passive health monitoring, guided exercise, scheduling \- directly into your cards and journeys. ## How Integrations Work Integrations connect to the platform in two ways: - **Passive data** - partner SDKs run in the background, collecting health data from smartphones and wearables. This data flows into participant profiles and progress screens automatically. - **Active experiences** - partner content is embedded directly in cards using external references. Participants interact with the partner experience without leaving the app. ### [Sahha](./sahha) Passive health data collection from smartphones and wearables. Captures sleep, steps, heart rate, and other biomarkers, then turns them into wellness scores using machine learning. ### [KinesteX](./kinestex) AI-powered movement tracking through the smartphone camera. Delivers guided exercise sessions with real-time form correction and rep counting. ### [Typeform](./typeform) Interactive forms, surveys, and quizzes embedded in activity cards. :::warning[Coming Soon] This integration is currently in development. ::: ### [Cal.com](./cal-com) Appointment booking and scheduling for participants and coaches. :::warning[Coming Soon] This integration is currently in development. ::: ### [Topol.io](./topol) Drag-and-drop email template builder for journey-triggered communications. :::warning[Coming Soon] This integration is currently in development. ::: :::info Paid Services Most integrations require a separate license or API credentials from the partner. Contact your Intervengine representative for setup. ::: --- ## KinesTex # Intervengine x [KinesTex](https://www.kinestex.com/) # What is KinesTex? KinesTex is an Integration partner that Intervengine uses to provide real-time, AI-powered movement tracking and exercise feedback directly through a smartphone camera. We do this in two ways: - **Computer Vision SDK:** KinesTex uses the front-facing camera to track a Participant's skeletal frame in real-time, ensuring they are performing exercises with the correct form. - **Interactive Workouts:** The integration allows Intervengine to deliver guided physical activity where the app counts repetitions, identifies mistakes, and provides instant coaching. :::warning[Paid Integration] Please note that KinesTex is a separate paid integration. You will need an active KinesTex license and API credentials to enable these features within your Intervengine environment. ::: ## Creating a KinesTex Workout Card To deliver a KinesTex experience, you must configure a specific **Activity Card** within the Intervengine platform. This setup ensures the app knows to launch the camera interface rather than a standard text Activity Element. ### Configuration Steps When creating your Activity Card, follow these steps: 1. **Add an Activity Element:** Within your card, create a new Activity Element. 2. **Set Activity Element Type:** Set the Activity Element type to **"Activity Element & external reference"**. 3. **Enter External Reference:** In the `externalReference` field, you must provide the workout identifier using the following URI scheme: > `kinestex://[WORKOUT_NAME]` _Example: `kinestex://squat_challenge_` ### Technical Implementation The Intervengine app identifies these links using a regex pattern. When the `externalReference` matches the KinesTex pattern, it triggers the specialized iFrame. ## The Participant Experience When a user opens the card in the **Intervengine App**: - **iFramed Experience:** The app launches a secure iFramed KinesTex environment. - **AI Guidance:** The Participant's camera is activated (with consent) to track their movement and provide real-time feedback. - **Automatic Results:** Once the workout ends, the session data is not lost-the workout result is automatically saved as a **JSON object** directly into the **answer field** of that Activity Element. ## Data & Progress Because the workout results are stored as JSON, Intervengine can collate this data to display performance trends on the Participant Dashboard and within the screens. --- ## Sahha # Intervengine x [Sahha](https://docs.sahha.ai/) # What is Sahha? Sahha is an Integration partner that Intervengine uses that lets you collects and analyse passive human data from smartphones and wearables. We do this in two ways: - Sahha securely and passively captures smartphone and wearable device data with the consent of end-users through their mobile SDK which is installed within the Intervengine app. - Their machine learning models turn that data into insights and measures of behavioural, mental and physical state, bespoke to each Participant - With this super-power, you can build personalised digital health, fitness and wellbeing Journeys, measure the efficacy of the intervention or recommendations you provide and gain deep insight into how health data shapes your Participants :::warning[Paid Integration] Please note that Sahha is a separate paid integration. You will need an active Sahha license and API credentials to enable these features within your Intervengine environment. ::: ## Health Scores [Full documentation →](https://docs.sahha.ai/docs/products/scores) Scores transform complex health data into simple 0-1 values that participants can understand. Each score includes explainable factors, so participants know exactly what is contributing to their result and what to improve. Scores work with smartphone data alone - wearables add more factors (like heart rate) but are not required. All scores return one of four states: `minimal`, `low`, `medium`, `high`. - **Smartphone compatible** - works with phones alone, reaching 100% of participants without hardware requirements - **Explainable** - every score shows contributing factors so participants understand the "why" behind their number - **Real-time** - updates within 1 minute of new data arriving - **Instant value** - 14 days of retroactive scores on integration, so participants see insights from day one - **Actionable** - each factor includes goals so participants know what to improve ### Available Scores | Score | Description | Docs | | -------------------- | ----------------------------------------------------- | -------------------------------------------------------------- | | **Wellbeing** | Holistic assessment combining activity and sleep data | [View →](https://docs.sahha.ai/docs/products/scores/wellbeing) | | **Activity** | Daily physical activity levels | [View →](https://docs.sahha.ai/docs/products/scores/activity) | | **Sleep** | Sleep quality and quantity | [View →](https://docs.sahha.ai/docs/products/scores/sleep) | | **Mental Wellbeing** | Mental wellness derived from behavioural patterns | [View →](https://docs.sahha.ai/docs/products/scores/mental) | | **Readiness** | Daily recovery and preparedness for physical exertion | [View →](https://docs.sahha.ai/docs/products/scores/readiness) | :::info The Mental Wellbeing score is an informational tool based on behavioural patterns. It is not a diagnostic tool for clinical use. ::: ## Biomarkers [Full documentation →](https://docs.sahha.ai/docs/products/biomarkers) Biomarkers are 60+ standardised health metrics - steps, sleep, heart rate, and more - deduplicated and normalised from any device or source. Multiple data sources are intelligently merged to prevent double-counting across different devices. | Category | Examples | | -------------- | --------------------------------------------------------------------------------------- | | **Activity** | Steps, floors climbed, active hours, energy expenditure, exercise distances | | **Body** | Height, weight, BMI, body fat percentage, lean mass | | **Sleep** | Duration, stages (light, REM, deep), sleep debt, regularity, efficiency | | **Vitals** | Resting heart rate, HRV, respiratory rate, SpO2, VO2 max, blood glucose, blood pressure | | **Engagement** | App session counts and duration | Biomarkers update in real-time (within 1 minute) and are delivered as standardised values with consistent units, formats, and aggregation methods regardless of source device. ## Archetypes [Full documentation →](https://docs.sahha.ai/docs/products/archetypes) Archetypes classify participants into behavioural labels derived from weeks of health data analysis. Unlike numerical scores, archetypes provide intuitive labels like "Night Owl" or "Highly Active" that characterise patterns for segmentation and personalisation. There are two classification types: - **Ordinal** - ranked progressions where values move from lower to higher states (e.g. sleep duration: very short sleeper → long sleeper) - **Categorical** - distinct groups without hierarchy (e.g. chronotypes: early bird, night owl, intermediate) | Category | Archetypes | | ------------ | ----------------------------------------------------------------------------------------------- | | **Sleep** | Duration, efficiency, quality, regularity, pattern, bed schedule, wake schedule | | **Activity** | Activity level, exercise frequency, primary exercise, primary exercise type, secondary exercise | | **Wellness** | Mental wellness, overall wellness | Archetypes update at the end of each week, month, or quarter depending on periodicity. On integration, 2 weeks of historical archetypes are provided retroactively. ## Insights [Full documentation →](https://docs.sahha.ai/docs/products/insights) Insights provide trend and comparison intelligence derived from the data Sahha already collects - including health scores, biomarkers, and behavioural signals. Rather than looking at a single point in time, Insights evaluate patterns across time to generate meaningful summaries. ### Trends Trends detect directional change in a score, factor, or biomarker over time - is it going up, down, or staying the same, and by how much? Use trends to create compelling narratives, trigger actions on meaningful changes, and build smarter campaigns. ### Comparisons Comparisons benchmark individual values against peers, population norms, or personal baselines. For example, comparing a participant's sleep duration against females aged 35-40. --- ## Topol.io # Intervengine x [Topol.io](https://topol.io/) :::info[Coming Soon] This integration is currently in development. Details on this page represent the planned functionality and may change before release. ::: # What is Topol.io? Topol.io is a no-code drag-and-drop email template builder. It provides a visual editor for designing responsive, professional email templates without requiring HTML or design expertise. ## How It Integrates with Intervengine Topol.io connects to Intervengine in two ways: - **Template Builder (Portal):** The Topol plugin is embedded directly in the Intervengine Portal, allowing coaches and administrators to design email templates using a visual drag-and-drop editor. - **Email Automation (Journeys):** Templates built with Topol are used in Journey-triggered email communications, automatically sending designed emails to Participants when they reach specific states or milestones. ## Key Capabilities - **Journey Milestone Notifications:** Send professionally designed emails when Participants reach key points in their Journey - **Appointment Reminders:** Deliver branded reminder emails for upcoming sessions and check-ins - **Coach Communications:** Give coaches the tools to send polished, on-brand emails to their Participants - **Journey Updates:** Communicate Journey changes, new content, and announcements with consistent visual design :::warning[Paid Integration] Please note that Topol.io is a separate paid integration. You will need an active Topol.io license and API credentials to enable these features within your Intervengine environment. ::: --- ## Typeform # Intervengine x [Typeform](https://www.typeform.com/) :::info[Coming Soon] This integration is currently in development. Details on this page represent the planned functionality and may change before release. ::: # What is Typeform? Typeform is a platform for creating interactive forms, surveys, and quizzes with a conversational UI. Instead of presenting a static list of fields, Typeform delivers one question at a time in a guided, engaging experience - leading to higher completion rates and richer response data. ## How It Integrates with Intervengine Typeform integrates as an external reference within **Activity Cards**, following the same pattern as other embedded experiences (like KinesTex). When creating your Activity Card: 1. **Add an Activity Element** and set the type to **"Activity Element & external reference"**. 2. **Enter the External Reference** using the URI scheme: > `typeform://[FORM_ID]` When a Participant opens the card in the Intervengine App, an embedded Typeform experience launches. Once the Participant completes the form, responses flow back into Intervengine as answer data attached to that question. ## Key Capabilities - **Assessments & Screening Tools:** Deploy validated questionnaires and screening instruments as part of a Journey - **Onboarding Questionnaires:** Gather baseline information from Participants through guided, conversational flows - **Research Surveys:** Collect structured research data at specific Journey milestones - **Participant Feedback:** Capture experience feedback and satisfaction ratings throughout a Journey :::warning[Paid Integration] Please note that Typeform is a separate paid integration. You will need an active Typeform license and API credentials to enable these features within your Intervengine environment. ::: --- ## LLM Documentation Access # LLM Documentation Access Intervengine publishes a machine-readable version of its documentation at [/llms.txt](/llms.txt). This is a single markdown file containing the full content of every documentation page, cleaned of formatting artifacts and optimised for use with large language models like Claude, ChatGPT, and others. The file is regenerated automatically on every documentation build, so it always reflects the latest published content. ## Using with Claude The recommended way to use this with [Claude](https://claude.ai) is via a **Project** with custom instructions. ### One-time setup 1. Go to [claude.ai](https://claude.ai) and create a new **Project** 2. In the **Project Instructions**, add: > When you need to reference Intervengine documentation, fetch the contents > of https://intervengine-docs.web.app/llms.txt using your web fetch > capability and read it directly. 3. Start a conversation inside that Project Claude will fetch the latest documentation when needed. Because it reads from the live URL, you never need to re-upload or update anything — the file stays current as the docs are updated. ### Quick use (no project) Paste the URL directly into any Claude conversation: ``` https://intervengine-docs.web.app/llms.txt ``` Claude will fetch and read the content. This works for one-off questions but doesn't persist across conversations. --- ## Platform # Platform Platform-level documentation covering infrastructure, processes, third-party integrations, and legal policies. - **Processes** — environments and release management - **Integrations** — third-party services for health data, exercise, scheduling, and more - **Legal** — privacy policy, terms and conditions, app deletion - **llms.txt** — machine-readable site index for LLM consumption --- ## Privacy Policy # Privacy Policy This policy outlines how Artilect Limited (operating as Intervengine) complies with New Zealand's Privacy Act 2020. Artilect provides platform services supporting healthcare practitioners, corporates, employers, and public sector clients. Services include apps, customer data management, application development, data integrations, and APIs. The company commits to proper, open, and transparent management of personal information while maintaining compliance with privacy laws. Any data we collect about our clients' customers or patients, on behalf of our clients, is managed in accordance with the respective privacy policies of each client. This policy applies only to personal information from clients, suppliers, and external third parties that Artilect directly engages with. ## What personal information does Artilect collect? Artilect collects only necessary personal information through fair and lawful means via websites, employment processes, correspondence, and service purchases. Collection varies by services provided and jurisdiction. ### Information about contractors and suppliers Artilect collects name, contact details, and tax information. With consent, sensitive information (medical details about injuries) may be collected for workplace health and safety. Third-party feedback about contractor performance is also gathered to monitor service quality and ensure product excellence. ### Information about job applicants Applicants must provide name, contact details, CV information, driver's license, or passport details. References are collected from identified referees. We also perform a police criminal background check before employing a new person. This information determines suitability for vacant roles. ### Information about clients and their employees and stakeholders Personal information collected includes name, contact details, bank account, and invoicing details. This information is used for: - Billing and order fulfillment - Contacting customers about service provision - Maintaining account details - Providing technical support on managed systems - Providing product and service information on request - Streamlining and personalising customer experience - Conducting satisfaction surveys and tailoring services Artilect may also collect personal information from its customers relating to its employees and stakeholders, for example contact information and job roles. Aggregated, anonymous demographic and usage information improves websites and services without identifying individuals. ## Quality of personal information Artilect will ensure, to the extent reasonably possible, that personal information collected, used or disclosed is accurate, up-to-date, complete and relevant. Upon discovering inaccurate information, Artilect takes prompt steps to update records. ## Information security Artilect applies active measures and controls per ISO/IEC 27001 Information Security Standard. All devices, storage, and channels undergo continuous monitoring, logging analysis, and audit. Artilect may contract third parties for these functions. All personal information is stored at secure premises using good quality security protocols including two-factor authentication where possible. Security systems are regularly reviewed and updated. When you use our service, we automatically collect information about your interactions and technical data to ensure our service is secure and reliable. This includes your IP address, device identifiers, and a unique internal user ID which we may record in our logs for troubleshooting and security analysis purposes. ## Access and correction of personal information Subject to identity verification, individuals may access, update, or correct personal information through the Artilect Privacy Officer. Artilect will endeavour to respond to access and correction of personal information within 15 business days after a written request is received. ## Direct marketing Artilect engages in direct marketing per New Zealand law. Individuals or organisations may request cessation of marketing materials at any time. Email communications include simple opt-out (unsubscribe) mechanisms available anytime. ## Disclosure and retention of personal information As part of providing services to a customer, Artilect may disclose limited personal information to third party suppliers or contractors as authorised by law. Artilect retains personal information only as required by law or for business functions. Unneeded information is destroyed or securely disposed of. ## International data transfers As an IT services provider, Artilect retains personal information on servers in multiple overseas countries. The company respects varying national laws and cross-border data transfer obligations. Artilect will take all reasonable steps to ensure that no person or entity breaches any relevant privacy and data protection laws using a variety of lawful data transfer mechanisms and contractual agreements. ## Website browsing Website access logs information including time of access, IP address, and viewed pages. External website links appear on Artilect or Intervengine websites, but the company is not responsible for the content or privacy policies that govern such external websites. ## Privacy issues Artilect holds legal obligations to secure information and use it appropriately per this policy. To raise privacy concerns or questions, contact the Artilect Privacy Officer. **Email:** privacy@artilect.co.nz **Mailing Address:** The Privacy Officer, Artilect Ltd, PO Box 301348, Albany, Auckland 0752 Unsatisfied individuals may escalate privacy complaints to the relevant government authority responsible for privacy and data protection. --- ## Release Process # Intervengine Software Release Process :::info This document outlines the structured process we follow to ensure that every new version of the Intervengine platform is stable, secure, and meets the highest quality standards before being deployed to your production environment. ::: ## Phase 1: Internal Quality Assurance (QA) & Preparation Before any new version is considered for release, it must first pass a rigorous internal validation process as a **Release Candidate**. This process is designed to catch issues early and ensure the stability and security of the platform. The Release Candidate must successfully pass all of the following checks in our development environment: - **Comprehensive Testing:** Our internal QA team conducts extensive testing. - **Code Linting:** Automated checks ensure code is clean, readable, and follows best practices. - **Secret Scanning:** We scan our codebase to ensure no sensitive credentials or keys have been accidentally included. - **Dependency Scanning:** We check all third-party libraries for known vulnerabilities. - **Security IaC Scanning:** Our Infrastructure as Code is scanned for any potential security misconfigurations. - **Peer Review:** The code is manually reviewed and approved by senior developers. Only when a Release Candidate has passed every one of these checks is it approved for the next phase. ## Phase 2: Staging Deployment Once a Release Candidate is internally approved, we reserve the right to deploy it immediately to our **staging environments**. This allows our team and any clients with staging access, such as yourself, to see the new version in a production-like setting before the official client review period begins. ## Phase 3: Client User Acceptance Testing (UAT) & Production Go-Live This phase is a collaborative effort to ensure you are fully informed, prepared, and satisfied with the upcoming release before it goes live on your production environment. --- ### The User Acceptance Testing (UAT) Process & Timeline The entire UAT process has a duration of **three (3) weeks** from the date of notification. 1. **Notification & Documentation (Start of Week 1)** - We will formally notify you that a new production release is planned and publish the official **Release Notes**. - You will also be sent two key documents: - **Testing Spreadsheet:** Details the new features and changes for your review. - **Certificate of Acceptance:** The formal sign-off document. 2. **Your Review & Feedback (Weeks 1-2)** - You have a period of **two (2) weeks** from the notification date to review the upcoming release and return the signed **Certificate of Acceptance**. - During this time, you have two options: - **Option A: Accept Our Testing:** You can accept our internal QA testing as sufficient, sign the Certificate of Acceptance, and return it. - **Option B: Perform Your Own Testing:** You can use our Testing Spreadsheet to guide your own internal testing. All feedback and bug reports must be submitted within this two-week window. 3. **Feedback Deadline & Final Release (End of Week 2)** - The deadline for returning the signed Certificate of Acceptance and submitting any feedback or bug reports is the end of the second week. ### Scope of Testing & Your Responsibility Our internal QA process and the provided Testing Spreadsheet cover all generic, platform-wide features. For any non-generic, client-specific features that have been developed for your organization, it is **your responsibility** to create and maintain your own testing procedures. Our team does not perform testing on custom features as part of the standard release cycle. :::tip If you report feedback or bugs within the two-week deadline: We will address the issues, which may involve delaying the release to ensure a stable final product. ::: :::warning **If the two-week deadline passes without your feedback or a returned certificate:** We will proceed with the production release as scheduled at the end of the three-week window. In this event, the liability for any bugs discovered post-release rests with **you**. ::: --- ## Terms & Conditions # Terms & Conditions **Owner:** Artilect Limited — info@artilect.co.nz ## What the user should know at a glance - Certain provisions apply only to specific user categories (Consumers vs. Business Users) - Clauses apply to all Users unless explicitly stated otherwise ## Terms of use ### General usage requirements Users confirm they meet these conditions: - No restrictions based on Consumer or Business User status - Not located in U.S.-embargoed countries or "terrorist-supporting" countries - Not listed on U.S. Government prohibition or restriction lists ### Account registration - Users may register or use the Service without an account (with limited features) - Users must provide complete and truthful information when registering - Users are responsible for keeping login credentials confidential - Passwords must meet highest strength standards - Users are fully responsible for all account activities - Users must immediately notify the Owner if personal information is compromised ### Conditions for account registration - Bot-automated accounts are prohibited - Users should register only one account (unless explicitly permitted) - Accounts generally cannot be shared with other persons ### Account termination Users may terminate accounts by contacting the Owner at the provided contact details. ### Account suspension and deletion - The Owner reserves the right to suspend or delete accounts deemed inappropriate or in violation of Terms - Suspension or deletion does not entitle users to compensation or reimbursement - Users remain liable for fees even if accounts are deleted due to user misconduct ### Content on this application - All content is owned or provided by the Owner or licensors - The Owner endeavours to ensure content does not infringe legal provisions or third-party rights - Users should report complaints using provided contact information ### Rights regarding content The Owner holds and reserves all intellectual property rights for any such content. Users may not: - Copy, download, share, modify, translate, transform, publish, transmit, sell, sublicense, or create derivative works - Allow third parties to do the above through their device - Violate these restrictions even without conscious knowledge Where explicitly stated, users may download and share content for sole personal, non-commercial use with proper attribution. Statutory copyright limitations remain unaffected. ### Access to external resources - The Owner has no control over third-party resources - The Owner is not responsible for third-party content or availability - Third-party terms govern use of their resources ### Acceptable use This Application and the Service may only be used within the scope of what they are provided for. Users are solely responsible for ensuring use does not violate applicable law or third-party rights. The Owner reserves the right to take appropriate measures, including: - Denying access to the Application or Service - Terminating contracts - Reporting misconduct to competent authorities Prohibited activities include: - Violating laws, regulations, or these Terms - Infringing third-party rights - Impairing the Owner's legitimate interests - Offending the Owner or third parties ## Liability and indemnification ### Australian users — limitation of liability Nothing excludes rights under the Competition and Consumer Act 2010 (Cth) or similar legislation that cannot be excluded. To the fullest extent permitted by law, our liability to the User is limited, at the Owner's sole discretion, to the re-performance of the services or the payment of the cost of having the services supplied again. ### US users — disclaimer of warranties This Application is provided strictly on an "as is" and "as available" basis. The Owner expressly disclaims all conditions, representations, and warranties — whether express, implied, statutory, or otherwise, including merchantability, fitness for particular purpose, and non-infringement. No advice creates additional warranties. The Owner does not warrant: - Content accuracy, reliability, or correctness - The Service will meet User requirements - Service availability, uninterrupted access, or security - Defects or errors will be corrected - The Service is virus-free or harmless Any content downloaded or otherwise obtained through the use of the Service is downloaded at the user's own risk. The Owner does not endorse or assume responsibility for third-party products or services. The Service may become inaccessible or malfunction with certain browsers, devices, or operating systems. ### US users — limitations of liability To the maximum extent permitted by law, the Owner is not liable for: - Indirect, punitive, incidental, special, consequential, or exemplary damages - Damages for lost profits, goodwill, use, data, or intangible losses - Damage from hacking, tampering, or unauthorised access - Errors, mistakes, or content inaccuracies - Personal injury or property damage from Service use - Unauthorised access to secure servers or personal information - Transmission interruption or cessation - Bugs, viruses, or trojan horses - Losses from content use - Defamatory, offensive, or illegal User or third-party conduct In no event shall the Owner be liable for any claims, proceedings, liabilities, obligations, damages, losses or costs in an amount exceeding the amount paid by User to the Owner in the preceding 12 months, or the period of duration of this agreement. This applies regardless of legal basis, even if the Owner was advised of damage possibility. Some jurisdictions do not allow consequential damage exclusions, so limitations may not apply. ### Indemnification The User agrees to defend, indemnify and hold the Owner and its subsidiaries, affiliates, officers, directors, agents, co-branders, partners, suppliers and employees harmless from and against any and all claims or demands. Users indemnify the Owner for: - User's use and access to the Service, including transmitted and received data - Violations of these Terms - Third-party rights violations (privacy, intellectual property) - Statutory law violations - Misleading, false, or inaccurate content from User's account - User's willful misconduct ## Common provisions ### No waiver The Owner's failure to assert rights does not constitute a waiver. No waiver is a continuing or further waiver. ### Service interruption The Owner reserves the right to interrupt the Service for maintenance, updates, or changes, with appropriate User notification. The Owner may suspend or terminate the Service entirely. Upon termination, the Owner will cooperate to enable User data withdrawal per applicable law. The Service may become unavailable due to force majeure (labour actions, infrastructure failures, blackouts, etc.) outside the Owner's reasonable control. ### Service reselling Users may not reproduce, duplicate, copy, sell, resell or exploit any portion of this Application and of its Service without the Owner's express prior written permission. ### Privacy policy Users should refer to the [privacy policy](/privacy) for personal data use information. ### Intellectual property rights Any intellectual property rights, such as copyrights, trademark rights, patent rights and design rights related to this Application are the exclusive property of the Owner or its licensors. All trademarks, marks, trade names, service marks, illustrations, images, and logos are the Owner's exclusive property, subject to applicable intellectual property protection. ### Changes to these terms The Owner reserves the right to amend or modify Terms. Users will be appropriately informed. The continued use of the Service will signify the User's acceptance of the revised Terms. Users may stop using the Service if unwilling to accept changes. ### Assignment of contract The Owner reserves the right to transfer, assign, dispose of through novation, or subcontract rights and obligations, considering User's legitimate interests. Users cannot assign or transfer rights or obligations without the Owner's written permission. ### Contacts All Service-related communications must use the contact information stated in this document. ### Severability Invalid or unenforceable provisions will not affect remaining provisions' validity, which remain fully enforceable. ### Governing law These Terms are governed by the law of the place where the Owner is based. ### Venue of jurisdiction Courts at the Owner's location have exclusive competence over disputes. --- ## Activities & Activity Elements # Activities & Activity Elements An **Activity** is a form, survey, or check-in that you build to gather data from your participants. They are the core of how you track progress and engage with users, and each Activity is made up of one or more **Activity Elements**. ### General Activities A general **Activity** (like a `Questionnaire` or `Reflection`) is designed to be scheduled. You can assign it to a participant, or as part of a **recurring action plan** within a Journey. This allows you to prompt the user to complete it on a regular basis, for example, every Monday morning. :::tip[Example] Imagine a coach wants to track a participant's mood at the start of every week. 1. They create a standard **Activity** named 'Weekly Mood Check-In'. 2. Inside, they add a single multiple-choice **Activity Element**: "How is your mood today?" with scored options like 'Great', 'Okay', and 'Not Good'. 3. They then add this Activity to a recurring action plan in the participant's Journey, setting it to appear every Monday. ::: ### Health Measures **Health Measures** are a special type of Activity designed specifically for ongoing, self-paced tracking by a participant. A **Health Measure** is unique because it is **unscheduled**. Once assigned to a participant, it remains persistently available in their app. This allows them to enter data at any time and as often as they like, which is perfect for logging metrics like weight, sleep hours, or pain levels on an ad-hoc basis. :::tip[Example] Imagine a coach needs a participant to log their weight regularly, but on a flexible schedule. 1. They create a **Health Measure** named 'Log Your Weight'. 2. Inside, they add an **Activity Element** with the 'Number' format and set the unit to 'kg'. 3. Once assigned, this measure is always available in the participant's app, allowing them to enter their weight whenever is convenient. ::: --- ### Building an Activity: The Activity Elements An **Activity Element** is the individual field you add inside an Activity to collect a piece of data. Activity Elements are created _within_ an activity and are specific to that activity. ### Activity Element Preamble Every Activity Element, regardless of its format, can include optional preamble **Content** such as text or images to provide instructions or context to the participant before they answer. ### Activity Element Format When you add an Activity Element, you must choose a format that determines how the participant will answer. - **Text/Multiple Choice:** This versatile format can be used for both open-ended text responses and for selecting from a list of predefined options. - _Example with Options:_ "Which of these best describes your energy levels?" with predefined, selectable options like 'High', 'Moderate', and 'Low'. - _Example without Options:_ "What is one thing you are grateful for today?" where the participant types their answer into a text box. - **Number:** This format is for numerical input and can be displayed in two ways. - _Example as a Slider:_ "On a scale of 1-10, how would you rate your sleep quality?" where the participant drags a slider to select their rating. - _Example as a Single Input:_ "How many minutes of exercise did you complete today?" where the participant types a number into a field. - **Yes/No:** A simple choice between two options. - _Example:_ "Did you complete your morning exercise today?". - **Content Page:** Use to display information (text, images, or video) without requiring a response. - _Example:_ A page that displays a "Welcome to Week 2" message and a short instructional video. --- ### Scoring and Data You can configure your activities to automatically calculate a total score based on participant responses. ### How Activity Scoring Works First, you select a **Scoring Strategy** for the overall Activity that determines how the individual scores are combined. Then, you set the score for each option within your individual **Activity Elements.** An optional **Score Multiplier** can be used to scale the final result. The available scoring strategies are: - **Sum:** Adds the scores from all answered Activity Elements to produce a total (e.g., 2 + 3 + 1 = 6). - **Average:** Calculates the mean score of all answered Activity Elements. This strategy also considers the **Weight** you can assign to each Activity Element, giving some Activity Elements more importance than others. - **Min:** Finds the single lowest score from all the answered Activity Elements. - **Max:** Finds the single highest score from all the answered Activity Elements. - **Median:** Finds the middle score after all answered Activity Elements' scores are sorted. - **Concat:** Joins the answers from all Activity Elements into a single text string. This is useful for non-numeric, text-based activities. - **None:** No scoring is calculated for this activity. --- ### Referencing Previous Responses in Activity Element Content When building an Activity with multiple elements, you can make later elements feel personalised by referencing a participant's answer to an earlier one. This is done by inserting a placeholder into the preamble content of any Activity Element using the syntax `{values.ELEMENT_CODE}`. The `ELEMENT_CODE` is the **Code** field of the Activity Element you want to reference. This is the same code used in Journey signal conditions. You can copy this syntax directly from the Activity Element form using the copy button next to the element name. :::note The copy button is only available once the Activity Element has been saved, as saving generates the element's code. ::: :::tip[Example] Imagine you are building a weekly check-in Activity with three elements: 1. **"Rate your mood today"** — a Number slider from 1–10 (Code: `MOOD_SCORE`) 2. **"What activities did you do this week?"** — a multi-select Text/Multiple Choice element (Code: `WEEKLY_ACTIVITIES`) 3. **"Reflection"** — a follow-up Content Page In the Reflection element's preamble content, you write: > You rated your mood as **\{values.MOOD_SCORE\}** out of 10 and completed > **\{values.WEEKLY_ACTIVITIES\}** this week. Let's reflect on how these > activities affected your wellbeing. If the participant rated their mood as 7 and selected "Running" and "Yoga", they will see: > You rated your mood as **7** out of 10 and completed **Running, Yoga** this > week. Let's reflect on how these activities affected your wellbeing. ::: This works across all Activity Element formats: - **Text/Multiple Choice** — inserts the selected option or typed text. For multi-select elements, multiple answers are joined with commas (e.g. "Running, Swimming, Reading"). - **Number** — inserts the number as text (e.g. "7" or "8.5"). - **Yes/No** — inserts the option label (e.g. "Yes" or "No"). - **Date/Time** — inserts a formatted date (e.g. "3 March 2026"). - **Content Page** — not applicable (no response to reference). :::note This only works for elements answered before the one containing the placeholder. If the referenced element hasn't been answered yet, the placeholder is left as-is. ::: --- ## Cards # Cards Cards are the primary method of delivering Content and Activities to your participants. This is usually presented to your Participants through a card feed. Each Card in the Card feed is distinct, and can have many different appearances and attachments. Cards can be either prescribed manually by coaches from the Participant Dashboard, or automatically via Journeys ## Card Type The Card Type defines if the card should present Content or Activities :::tip[Activities] Behaviours a person wants to do where you want an input from the participant, so that they can achieve a goal, scheduled, at times of the day, days of the week, are measured, for instance: - Did I do it? (i.e. Yes / No) - How long did it take (mins) - How far did I go (steps / kms / miles) - How difficult was it (likert scale 0-5) - Did I take it? (taken / missed) - How many reps and sets (numeric, one for reps, one for sets) ::: :::tip[Content] Rich text and image based experiences that educate and engage with your Participants. ::: Example Standard Layout Content Card set to open in a Modal ## Asset The Asset of the Card an optional field that can help draw your Participants into the Card, and add more context to the card for the Participant When creating a card, you often want to create a card that fits the App space perfectly (so as to have the image bleed to the sides perfectly). There are two ways to achieve that: 1. Configure the image to an aspect ratio of 1.88:1 (width:height) 2. Use the square config parameter, and create your image as a square (i.e. like instagram) The optimal resolution is at least 500px wide, though up to 1200px wide still works quickly enough, and resolves well on modern phones. ## Name The Name of the Card is what is shown to the users as the primary text The Name is also what you will be using to search on in order to find cards when you want to attach them in Journeys or prescribe them manually It is a good idea to keep the name of the cards short and to the point as shorter Names present well on cards on a wide range of different devices ## Description The Description of a card is used as secondary text under the Name. This can help give your Participants more context as to why they should interact with the card Try use this field to prompt the Participant to open it --- ## Contents and Content Types # Contents and Content Types A **Content** item is a piece of information, such as an article, guide, or link, that you can create and share with participants. Content is the foundation for building educational and engaging experiences within Journeys, Coaching and Action Plans. A **Content Type** is a required category for every piece of content. It provides a way to classify and organise your content library. Think of them as folders for your articles and links, such as 'Sleep Hygiene', 'Nutrition Basics', or 'Mental Wellbeing'. Every piece of content you create must be one of two formats: ### Rich Text This format allows you to build articles directly within the platform. Your article is composed of **Sections**, and each section is built from **Content Elements** like text and assets. - **Text Formatting with Markdown:** Text elements support **Markdown**, following the CommonMark and GitHub Flavoured Markdown (GFM) specifications. This allows you to easily format your text with headings, lists, bold, italics, and more. [CommonMark](https://commonmark.org/) [GitHub Flavored Markdown Spec](https://github.github.com/gfm/) - **Assets:** You can insert media directly from your Assets library. This is perfect for images, audio clips, and short video files. - **Embedding Videos:** For longer videos, it is suggested to use embeds. This method is more performant for participants and does not have the file size limits of uploaded Assets. You can embed videos directly using special tags: - **YouTube:** Use the `` tag. - **Vimeo:** Use the `` tag. :::info Don't include the { } brackets, they just mean insert the `videoId` `` ::: - **Direct Video File:** Use the `` tag for other video URLs. :::tip[Example] Imagine a coach wants to create an article explaining the benefits of a good sleep routine. 1. **Content Type:** The coach first ensures a 'Sleep' Content Type exists. 2. **Content Creation:** They create a new piece of content named 'The Importance of Sleep'. 3. **Format:** They select the `Rich Text` format to build the article internally. 4. **Content:** Using the editor, they build the article with sections, format text with **Markdown**, and embed a relevant YouTube video using the `` tag. 5. **Save & Publish:** Once the article is complete, they save and publish it to make it available for use. ::: ### External Link This format redirects the participant to an external webpage, which is useful when you want to present content that is already on the web, such as news articles or other websites. You can personalise the link by adding `{userId}` to the URL, which will be automatically replaced with the participant's unique ID. :::tip[Example] Imagine a coach wants to share a detailed article from a reputable health website. 1. **Content Type:** The coach creates and selects the 'Nutrition' Content Type. 2. **Content Creation:** They create a new piece of content named 'Guide to a Healthy Diet'. 3. **Format:** They select the `External Link` format. 4. **URL:** They paste the URL to the external article in the provided field. 5. **Save & Publish:** Once the link is complete, they save and publish it to make it available for use. ::: --- ### The Publishing System Content created in the **Rich Text** format uses a publishing system. When you are ready for your changes to go live, you must explicitly **Publish** the content. This action creates a new, locked **version** of the article, logs who published it and when, and makes it the live version for participants. This lets you make changes to the content without interrupting the participants experience. --- ## Health Areas # Health Areas A **Health Area** is a high-level category used to group and organize Activity Plans for your participants. They are the primary way to provide a clear, contextual structure to the participant's experience in the app. Think of them as the shelves in a library where you place related books. Instead of one long list of books, participants can go directly to the 'Physical Health' or 'Mindfulness' shelf to find what they're looking for. :::tip[Grouping by Topic] The most common use is to create Health Areas for clinical or wellness topics. For example, you could create areas for `Nutrition`, `Sleep Hygiene`, and `Mental Wellbeing`. All activities related to diet would then be assigned to the `Nutrition` Health Area. ::: :::tip[Grouping by Journey] You can create a Health Area for anything you want to group together. For instance, if you have a **Journey** called the `6-Week Stress Reduction`, you can create a **Health Area** with the exact same name. By ensuring all Cards sent by that Journey are assigned to the `6-Week Stress Reduction` Health Area, they will all appear together in their own dedicated list in the app. This creates a seamless and organized experience for participants who might be enrolled in multiple Journeys at once. ::: ### How Health Areas Influence the App In the app, all **One-Off** Activity Plan Cards assigned to a participant are no longer shown in a single long list. Instead, they are grouped by their common **Health Area**. Each Health Area appears as its own section with a title, containing a horizontally scrolling list of all the Cards associated with that Health Area. This new layout provides a much clearer context, helping participants understand the purpose of each Card and how it relates to their overall program. --- ## Coaches # Coaches **Coaches** are the users responsible for performing coaching and management tasks within the Intervengine platform. They are the primary users who interact with **Participants**, manage **Journeys**, assign Activity Plans, and view progress. Think of Coaches as the guides or administrators of the platform, while Participants are the end-users who engage with the content and journeys. A Coach's access to features and participant data is controlled by the **Roles** and **Groups** they are assigned. ### Profile Information Each coach has a profile with their **First Name**, **Last Name**, and **Email**. We highly recommend that all coaches upload a **Profile Photo** to create a more personal and recognizable experience for participants. :::warning[Uniqueness Rules] To ensure every account is unique, **Email addresses and Mobile Numbers** must be unique across the _entire system_. A Coach cannot use the same email or mobile number as another Coach or a Participant. ::: ### Security (Two-Factor Authentication) The **Mobile Number** field is optional and is used exclusively for Two-Factor Authentication (2FA). If your organization has 2FA enabled, coaches must provide a valid mobile number to securely log in. This is an organizational-level setting, not configured per coach. ### Access Control A coach's permissions are defined by two key fields: - **Roles**: This determines _what they can do_. For example, the `Admin` role allows access to everything, while the default `Coach` role has more restricted permissions. - **Groups**: This determines _who they can see_. For example, a coach in the `Upreach` group can only see participants who are also in that same group. ### Data & Reporting The **External ID** is a automatically generated unique identifier (`UID`). It is used to map the coach's account to their `user_id` in the reporting database. This field is read-only and used for internal data linking. --- ## How to Add and Manage Participants # How to Add and Manage Participants Participants are the people your program is designed to support. This guide walks you through creating participants, organizing them, assigning content, and tracking their engagement. ## What is a Participant? A **Participant** is an end-user of the Intervengine platform — the person who receives coaching, completes activities, reads content, and engages with Journeys through the mobile app. Think of them as the members, clients, or patients in your program. ## Step 1: Create a Participant Navigate to **Participants** in the left menu and click **Create**. Fill in the participant's profile: - **First Name** and **Last Name** — required for identification - **Email** — used for login and notifications - **Mobile Number** — used for SMS notifications and (optionally) 2FA - **Gender** — optional demographic field - **Preferred Timezone** — ensures scheduled content arrives at the right local time - **Reminder Hours** — sets when daily reminders are sent :::warning Uniqueness Rules **Email addresses and mobile numbers must be unique across the entire system.** A participant cannot share an email or mobile number with any other participant or coach. The system will reject duplicates. ::: Once created, the participant receives an email with a link to set their password and download the app. ## Step 2: Organize with Groups and Tags Keeping participants organized makes it easier to manage access, target content, and run reports. ### Groups (Access Control) **Groups** control which coaches can see which participants. Assign a participant to one or more groups to ensure only the right coaches have visibility. - A coach in the `Uptown Clinic` group can only see participants also in that group - Items in the `Shared` group are visible to everyone - Admin users bypass all group restrictions ### Tags (Segmentation) **Tags** are labels you apply to participants for classification and targeting. Use them to: - Segment participants (e.g., `high-risk`, `new-starter`, `week-4`) - Target campaigns to specific audiences - Trigger Journey logic based on tag presence :::tip Establish a consistent tagging convention early. For example, use prefixes like `risk-high`, `risk-low`, `phase-onboarding`, `phase-active` to keep tags organized as your program grows. ::: ## Step 3: Assign Content via Activity Plans To deliver a Card to a specific participant, assign it from their profile. This creates an **Activity Plan** — a schedule that generates the individual app cards the participant sees. 1. Open the participant's profile 2. Navigate to their **Feed** tab 3. Click **Add Activity Plan** 4. Select the Card you want to assign 5. Configure the schedule (daily, weekly, one-time) and date range The Activity Plan generates **Activity Plan Details** — one for each scheduled occurrence. These are what the participant sees and completes in the app. :::info For a deeper explanation of how Cards, Activity Plans, and Activity Plan Details relate to each other, see [Cards vs Activity Plans](../participants/tutorials/cards-vs-activity-plans). ::: ## Step 4: Assign a Journey Journeys automate the delivery of content over time. To enroll a participant in a Journey: 1. Open the participant's profile 2. Click **Assign Journey** 3. Select the Journey from the list 4. The participant enters the Journey's start state and begins receiving automated content based on the Journey's transitions and signals :::tip Participants can be enrolled in multiple Journeys simultaneously. This allows you to layer different programs — for example, a general onboarding Journey alongside a condition-specific intervention Journey. ::: ## Step 5: Communicate via Chats Chats provide a direct messaging channel between you and your participants within the app. 1. Open the participant's profile 2. Navigate to the **Chats** tab 3. Select an existing chat session or create a new one 4. Send messages, share encouragement, or follow up on completed activities Participants receive push notifications for new messages and can reply directly from the app. ## Step 6: Monitor Progress The **Progress** tab on each participant's profile gives you a view of their engagement: - **Completion rates** — how many assigned activities have been completed - **Score trends** — how scores on assessments change over time - **Journey position** — which state they are currently in for each active Journey Use this information to identify participants who need extra support, adjust their content, or celebrate milestones. ## Tips for Success - **Set up groups before adding participants** — it's easier to assign groups during creation than to go back and update them later. - **Use the External ID field** — if your participants exist in an external system (CRM, EHR), store that system's ID in the External ID field for easy cross-referencing. - **Assign Journeys early** — Journeys handle most of the content delivery automatically, reducing your manual workload. - **Check in on Chats regularly** — timely responses keep participants engaged and build trust in the coaching relationship. - **Review Tasks daily** — Tasks flag participants and items that need your attention, so you never miss something important. --- ## How to Set Up a Journey # How to Set Up a Journey Journeys are the automation engine of Intervengine. They deliver cards, messages, and actions to participants automatically based on time, responses, and other triggers. This guide walks you through building your first Journey from scratch. ## What is a Journey? A **Journey** is a visual state-machine workflow. It defines the stages (states) a participant moves through and the rules (transitions) that advance them from one stage to the next. Each transition can deliver content, send messages, apply tags, and more. For a full overview, see [Journeys](../journeys). ## Prerequisites Before building a Journey, make sure you have: - **Cards created** — Journeys deliver Cards to participants, so you need at least one Activity or Content Card ready. See [Cards](../cards) for details. - **A test participant** — you'll want someone to enroll in the Journey to verify it works as expected. ## Step 1: Create a New Journey 1. Navigate to **Journeys** in the left menu 2. Click **Create** 3. Enter a **name** for your Journey (e.g., "Welcome Program" or "Week 1 Check-Ins") 4. Optionally add a **description** to help other coaches understand the Journey's purpose 5. Click **Save** You'll be taken to the Journey editor — a visual canvas where you build the workflow. ## Step 2: Add States **States** represent the stages a participant moves through. Every Journey needs at least: - A **start state** — where participants enter the Journey - One or more **intermediate states** — the phases of your program - An **end state** — where the Journey is considered complete To add a state, drag out from the output handle of an existing state and drop it on the canvas. You can also add a state between two existing states by clicking the **Add new State** button on a transition line. :::tip Name your states descriptively — for example, "Onboarding", "Week 1", "Week 2", "Assessment Review", "Complete". This makes the Journey easier to understand at a glance. ::: ## Step 3: Connect States with Transitions **Transitions** define how participants move from one state to the next. To create a transition: 1. Drag from the output handle of one state to the input handle of another 2. A transition line appears connecting the two states Each transition needs a **trigger** to determine when it fires. You'll configure that in the next step. ## Step 4: Configure Triggers Every transition needs a trigger — the condition that causes it to fire and move the participant to the next state. There are four trigger types: - **Time** — fires after a set duration (seconds, minutes, hours, or days) from when the participant entered the current state. Use this for time-based programs (e.g., "move to Week 2 after 7 days"). - **Time from Start** — fires after a set duration from when the participant first entered the Journey. Use this for absolute scheduling. - **Response** — fires when the participant responds to a message sent by the Journey. Use this for interactive, conversational flows. - **Signal** — fires when a specific event occurs, such as a participant completing an activity, being assigned a tag, or receiving an external event. Use this for behavior-driven logic. :::info For the full reference on signal expressions and syntax, see [Signals](../journeys/signals). ::: ## Step 5: Add Attachments to Transitions When a transition fires, it can execute one or more **attachments** — actions that happen as the participant moves between states. Available attachment types: - **Add Card** — assign an Activity, Content, or Health Measure Card to the participant - **Send Message** — deliver an app notification, email, or SMS - **Start Journey** — enroll the participant in another Journey (for branching or chaining workflows) - **Assign Tags** or **Remove Tags** — update the participant's tags - **Add Groups** — add the participant to a group - **Add Extras** — set custom data on the participant's profile - **Add Task** — create a task for a coach to follow up on :::tip A single transition can have multiple attachments. For example, you might simultaneously assign a Card, send a notification, and apply a tag — all when the participant transitions from one state to the next. ::: ## Step 6: Test with a Test Participant Before enrolling real participants, always test your Journey: 1. Create or identify a **test participant** (or use your own test account) 2. Open the test participant's profile 3. Click **Assign Journey** and select your new Journey 4. The test participant enters the start state 5. Verify that transitions fire at the right times and attachments are delivered correctly 6. Walk through the entire Journey to confirm participants reach the end state as expected :::warning If your Journey uses time-based triggers with long delays (e.g., 7 days), you may need to adjust the durations temporarily for testing (e.g., change to minutes) and then restore them before going live. ::: ## Tips for Success - **Plan on paper first** — sketch your states and transitions before opening the Journey editor. Knowing the flow upfront saves time. - **Start simple** — begin with a linear Journey (state A → state B → state C) before adding branching logic or signals. - **Use descriptive names** — name your states and transitions clearly so other coaches can understand the workflow. - **Test every path** — if your Journey has branching transitions, test each branch to make sure participants are routed correctly. - **Combine time and signal triggers** — a common pattern is to use a time trigger as a default advance (e.g., "move after 7 days") with a signal trigger for early advancement (e.g., "move immediately if assessment is completed"). - **Chain Journeys** — use the "Start Journey" attachment to break complex programs into smaller, reusable Journeys. --- ## How to Use the Coach Dashboard # How to Use the Coach Dashboard The Portal is your command center for coaching. This guide walks you through the interface, explains the key areas, and helps you build an efficient daily workflow. ## What is the Portal? The **Portal** is the coach-facing web application where you manage everything your participants experience. From here you can create content, design automated journeys, monitor participant progress, and communicate directly with your participants. ## Navigating the Portal The Portal is organized into four main sections, accessible from the left-hand navigation menu. ### Participants Your primary workspace. Here you can: - View and search all participants assigned to your groups - Open individual participant profiles to see their feed, progress, chats, and tasks - Create new participants and assign them content or journeys ### Cards The content library where you build what participants receive. Cards come in three types: - **Activity Cards** — collect responses from participants (surveys, assessments, check-ins) - **Content Cards** — deliver educational material (articles, videos, instructions) - **Health Measure Cards** — allow participants to log health data on demand ### Journeys The automation engine. Journeys are visual state-machine workflows that deliver cards and messages to participants based on time, responses, and other triggers. Build a Journey once and it runs continuously for every enrolled participant. ### More Additional configuration tools including: - **Groups** — control which coaches see which participants - **Tags** — label and segment participants for targeted delivery - **Tasks** — track action items that require coach attention - **Campaigns** — send bulk messages to groups of participants - **Configurations** — manage organization-level settings like schedulers and notifications - **Webhooks** — integrate with external systems - **RBAC** — manage roles and permissions ## Your Daily Workflow as a Coach A typical coaching day follows a predictable pattern. Here's a recommended routine to stay on top of your participants. ### 1. Check Tasks for Action Items Start your day by reviewing your **Tasks**. Tasks are generated when something needs your attention — for example, a participant has completed an assessment that requires review, or a Journey has flagged an issue. ### 2. Review Participant Progress Open the **Participants** section and check in on participants who are actively engaged in Journeys or have upcoming activities. The **Progress** tab on each participant's profile shows their completion rates and score trends over time. ### 3. Respond to Chats Check the **Chats** tab for any participant messages that need a reply. Chats are a direct line of communication between you and your participants within the app. ### 4. Monitor Journey Enrollments Review the **Journeys** section to check that participants are progressing through their assigned Journeys as expected. Look for participants who may be stuck in a state or who have completed a Journey and need a follow-up. ## Managing Your Coach Profile Your profile is visible to participants in the app, so keeping it up to date helps build trust. Make sure you have: - A **profile photo** — participants see this in chats and on their coaching team list - Your **name** and **email** filled in correctly - A valid **mobile number** if your organization uses Two-Factor Authentication (2FA) ## Understanding Access Control Your visibility in the Portal is controlled by two mechanisms: - **Roles** determine _what you can do_. The built-in `Admin` role grants full access, while the `Coach` role restricts access to day-to-day coaching features. Your organization may have custom roles as well. - **Groups** determine _who you can see_. You can only view participants and content that belong to the same groups you are assigned to. Items in the special `Shared` group are visible to everyone. :::tip If you can't find a participant or a Journey, check with your admin that you are assigned to the correct groups. Admin users bypass all group restrictions. ::: ## Tips for Success - **Check Tasks first thing each day** — they surface the most important items that need your attention. - **Use tags to segment participants** — tagging participants (e.g., `high-risk`, `week-1`) makes it easy to filter and target groups for campaigns or manual follow-ups. - **Keep your profile photo updated** — it creates a more personal experience for participants. - **Learn the keyboard shortcuts** — the Portal supports keyboard navigation for faster workflows. - **Start small** — focus on one Journey and a handful of participants before scaling up to more complex programs. --- ## Gout # Gout Helps people with Gout better understand their illness, self-manage their condition, and improve medication adherence. Designed for New Zealanders, Maori, and Pasifika prescribed Allopurinol. No contra-indications. ## How it Works The Journey focuses on: - Educating people that Gout is primarily genetic, not the result of poor lifestyle - Creating positive beliefs about medication (Allopurinol) use - Addressing unhelpful behaviours such as stopping treatment to test if the condition persists, or discontinuing medication to feel normal ## Outcomes Significant change in illness-related beliefs and increased satisfaction with Allopurinol treatment. ## Rationale Combines the work of Drs Emad, Dalbeth, Petrie, Weinman, and Chalder with Susan Reid from Health Literacy NZ, who leads the Gout Aotearoa Action Group and created the [Change of Life Gout resource guide](https://www.notion.so/78d2ff6b06d84a4cbdb183f208afd417?pvs=21). ## References Dr Yasaman Emad, Dr Nicola Dalbeth, Dr K Petrie, Dr J Weinman, Dr T Chalder - University of Auckland. [Journal of Rheumatology, 2022](https://www.jrheum.org/content/49/6/622.abstract) --- ## MoodFit / Positive Emotions # MoodFit / Positive Emotions Helps people experience more positive emotions, even during difficult or stressful experiences. Suitable for anyone seeking to improve their wellbeing, including those experiencing stress, illness, burnout, or non-acute depression and anxiety. No contra-indications. ## How it Works MoodFit is a Positive Psychology intervention developed by the Medical Social Sciences School (Intervention Science) at Northwestern University. Over 6 weeks, participants learn and practise core skills: - Noticing and savouring positive events - Gratitude - Mindfulness (includes 10+ guided meditations, replayable anytime) - Positive reappraisal - Self-compassion - Personal strengths - Attainable goals Each topic combines psychoeducation with daily practice and reflection. Evaluated in 10+ clinical trials across populations experiencing stress or distress, including dementia carers, nurses with burnout, people recently diagnosed with diabetes, depression, HIV, early breast cancer, and gun violence interrupters. ## Outcomes - 88% find the intervention acceptable - 61% retention at 12 weeks - Improved mental health, positive affect, life satisfaction, meaning/purpose, and general self-efficacy (ps < .05, ds = .45 to .63) - Decreased anger (p < .05, d = -0.41) ## References [Prof Judith Moskowitz](https://www.feinberg.northwestern.edu/faculty-profiles/az/profile.html?xid=30504), Northwestern University. - [International Journal of Behavioural Medicine, 2023](https://link.springer.com/article/10.1007/s12529-023-10162-5) - Cancer patients - [The Journal of Positive Psychology, 2014](https://www.tandfonline.com/doi/abs/10.1080/17439760.2014.920410) - Diabetes - [PLOS One, 2024](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0305172) - Nurses experiencing burnout - [Journal of Health Psychology, 2012](https://pubmed.ncbi.nlm.nih.gov/22021272/) - Health-related stress - [Health Psychology, 2019](https://pubmed.ncbi.nlm.nih.gov/31045422/) - Dementia caregivers ### Learn More - [YouTube - Can You Have Positive Emotions in the Midst of Stress?](https://youtu.be/eelIx7735so) - [How positive emotions help us cope - Judith Moskowitz (IWR)](https://nziwr.co.nz/how-positive-emotions-help-us-cope-in-lifes-most-stressful-times-with-judy-moskowitz/) --- ## MoveFit # MoveFit Helps people move more to improve fitness and cardiovascular health. Suitable for anyone wanting to exercise more, from sedentary individuals to those already active. No contra-indications - safe even for those who have experienced a cardiac event. ## How it Works Originally developed as HEART for CVD, the intervention supports graded exercise. Participants start with 3 walks per week, progressing over 20 weeks to 6 walks per week at 35-50 minutes per walk. Three levels (low, medium, high) are available depending on baseline fitness, and the intervention can be tailored for those with or without CVD. The intervention includes: - Self-monitoring - Behavioural strategies (problem solving, implementation intentions, goal setting, action planning) - Reshaping beliefs - Psychoeducation Originally designed for SMS delivery, adapted for in-app delivery. ## Outcomes - Increases walking by 150 mins/week (55%), from 360 to 512 mins/week - Increases leisure time physical activity by 110 mins/week, from 273 to 383 mins/week - Evaluated as cost-effective for CVD management and cardiac rehab ## References Ralph Maddison, Robyn Whittaker et al. Developed at NIHI with exercise physiologists, cardiologists, behavioural scientists, and primary care physicians. [European Journal of Preventive Cardiology, 2015](https://academic.oup.com/eurjpc/article/22/6/701/5926402) --- ## Nourish # Nourish Helps people examine their eating behaviours and develop a healthier relationship with food. Suitable for anyone seeking to better understand their eating behaviours, including those wanting to lose weight (though this is not a weight loss Journey). :::warning Not suitable for people being clinically managed for an eating disorder. ::: ## How it Works Nourish helps people establish a healthy relationship to food, maintain a healthy diet, and engage in wellness-enhancing behaviours. Topics include: - Building a balanced meal - Menu planning and shopping - Recognising hunger and fullness signals - Non-hungry eating and dealing with urges - Mindful eating - Self-kindness and body gratitude - Long-term troubleshooting The Journey does not present any diets or focus on health literacy. Instead, it equips people with skills and self-reflection to understand and modify their eating behaviours. ## References Co-developed by Emily McRae, Clinical Psychologist and Health Psychologist specialising in Bariatric Care, and Olivia Dixon, to support patients in clinical practice. --- ## QuitHelp # QuitHelp Helps people quit smoking. Designed for European, Maori, and Pasifika populations. No contra-indications. ## Rationale Smoking is highly costly to the health economy and one of the leading causes of harm. QuitHelp supports people through their quit journey by connecting them to their motivation and preparing them for the difficulties of quitting. Originally developed as STOMP, then TXT2QUIT, this was the first intervention of its type when published in The Lancet in 2010. Subsequent publications demonstrated cost effectiveness, cultural effectiveness, and repeatability. ## Outcomes Quit rates more than doubled compared to control groups (11% vs 5%). ## References Dr Caroline Free, Rosemary Knight, Steven Robertson, Robyn Whittaker, Phil Edwards, Weiwei Zhou et al. - [The Lancet, 2009]() - [The European Journal of Health Economics, 2012](https://link.springer.com/article/10.1007/s10198-012-0424-5) --- ## SleepFit # SleepFit Helps people build better sleep hygiene. Suitable for anyone seeking to improve their sleep outcomes. No contra-indications. ## How it Works SleepFit takes a behavioural and educational approach to sleep hygiene, covering: - Types of sleep - Causes of poor sleep - Creating the optimal sleep environment (with scheduled activities) - Substances and sleep (alcohol, nicotine, caffeine) - Building a bedtime routine (with scheduled activities) - Sleep and stress (with activities to manage unhelpful thoughts) - Sleep and exercise The intervention combines psychoeducation, reflections on current behaviours, and setting up cues for new and improved behaviours. ## References Developed by Emily McRae, Clinical Psychologist and Health Psychologist, to support patients in clinical practice. --- ## TahaWairua / Taioranga / Hei Mahi / PreDiabetes # TahaWairua / Taioranga / Hei Mahi / PreDiabetes Provides culturally appropriate health literacy support for Maori and Pasifika populations based on Te Whare Tapa Wha principles. Suitable for New Zealanders working to improve their health. No contra-indications. ## How it Works Embracing the Te Whare Tapa Wha model, these Journeys use language and cultural references suitable for Maori and Pasifika New Zealanders, covering: - Hei Mahi (Exercise) - Taioranga (Nutrition) - TahaWairua (Spirituality) - PreDiabetes The interventions are primarily health literacy-focused, using engaging quizzes to test understanding. Imagery reflects New Zealand people and landscapes to resonate with the lived experience of New Zealanders. ## Rationale Developed by NIHI, Population Health Group, University of Auckland School of Medicine. Made available to the Precision Driven Health initiative with funding from Orion Health, and provided under licence by Orion Health. ## References Dr Rosie Dobson, University of Auckland. Licensed from Orion Health and PDH (Precision Driven Health). --- ## Type 2 Diabetes # Type 2 Diabetes Helps people with Type 2 Diabetes to better self-manage. Content has been tailored for both European and Maori participants. No contra-indications. ## How it Works The Journey runs over 9 months, primarily message-based, delivering notifications most days. It incorporates personalisation based on motivation, goals, and what matters to the participant. Themes include: - Foot care - Blood glucose measurement - Insulin management - Exercise - Healthy eating - Stress management - Smoking - Young adult considerations Culturally adapted with personalisation for Maori and European participants. ## Rationale Recognised the cost of Type 2 Diabetes to the NZ health economy and sought to demonstrate that a simple SMS-based intervention could improve outcomes. Intervengine adapted the intervention for in-app delivery. ## References Rosie Dobson, Dr Robyn Whittaker, Yannan Jiang, Ralph Maddison, Matthew Shepherd, Catherine McNamara, Richard Cutfield, Manish Khanolkar, Rinki Murphy. [BMJ, 2018](https://www.bmj.com/content/361/bmj.k1959) --- ## Journeys # Journeys **Journeys** allow you to set up automated workflows for coaching your Participants. A Journey is a visual state machine that automates the delivery of content, activities, and interventions based on participant behavior and progress. ## Core Concepts A Journey is built from three key components: - **States**: The building blocks of a Journey. Each state represents a phase or stage that a participant moves through. - **Transitions**: The connections between states that define how participants move through the Journey. Transitions contain **Attachments** (cards, activities, content) that are delivered when the transition fires. Transitions are triggered by **Signals** based on time, participant actions, or external events. - **Signals**: The triggers that cause transitions to fire. Signals can be based on schedules, activity completion, scores, or custom conditions. ## How Journeys Work 1. A participant is assigned to a Journey and enters the **start state** 2. When a transition's signal conditions are met, its attachments (cards, activities) are delivered and the participant moves to the next state 3. This process repeats as the participant progresses through states 4. This continues until the participant reaches an **end state** or is removed from the Journey ## Key Features ### Automated Delivery Journeys automatically schedule and deliver content at the right time. Set up a Journey once and it runs continuously for each participant. ### Conditional Logic Use signals to create branching paths based on participant responses, scores, or behaviors. For example, route participants to different content based on their assessment results. ### Recurring Actions States can include recurring action plans that deliver activities on a schedule (e.g., daily check-ins, weekly assessments). ### Multiple Journeys Participants can be enrolled in multiple Journeys simultaneously, allowing you to layer different programs or interventions. ## Getting Started 1. **Plan your workflow**: Map out the states participants will move through and what triggers transitions 2. **Create your content**: Build the activities, content cards, and other attachments you'll deliver 3. **Build the Journey**: Create states, connect them with transitions, and add attachments to transitions 4. **Define signals**: Set up the conditions that trigger each transition 5. **Test**: Assign a test participant and verify the Journey behaves as expected 6. **Deploy**: Assign the Journey to your participants --- ## Common Journey Patterns # Common Journey Patterns This page describes reusable patterns for building Journeys. Each pattern explains the structure, when to use it, and the key signals and attachments involved. You can combine multiple patterns within a single Journey or across chained Journeys. --- ## Linear Time-Based Deliver content on a fixed schedule. Each transition uses a **Time** trigger to advance the participant after a set delay. **Structure:** ```mermaid flowchart LR A([Start]) -->|1 day| B([State A]) B -->|3 days| C([State B]) C -->|7 days| D([End]) ``` **When to use:** Journeys with a fixed curriculum delivered over days or weeks (e.g. a 4-week education series). **Key configuration:** - Trigger type: **Time** (days/hours from reaching the state) - Attachments: **Add Card** on each transition to deliver the next piece of content or activity **Tips:** - Use **Time from Journey Start** on the first transition if the first piece of content should be delivered immediately (0 seconds) - Keep each Journey module to 1–2 weeks and chain them together for longer Journeys (see [Versioning & Modular Design](./versioning)) --- ## Content Completion-Based Advance participants only when they read a Content Card. The Journey waits at each state until the participant engages with the content before moving on. **Structure:** ```mermaid flowchart LR A([Start]) -->|deliver Card A| B([Wait for Read]) B -->|CONTENT_READ| C([Deliver Card B]) C --> D([Wait for Read]) D -->|CONTENT_READ| E([End]) ``` **When to use:** Self-paced education where participants control the speed. **Key configuration:** - Trigger type: **Signal** - Signal: `code == "CONTENT_READ" && identifier == "{cardId}"` - The Content Card is delivered via an **Add Card** attachment on the inbound transition **Tips:** - Combine with a time-based fallback transition (e.g. advance after 7 days even if not read) to prevent participants from stalling indefinitely --- ## Activity Completion-Based Advance participants when they complete an Activity Card, regardless of their responses. **Structure:** ```mermaid flowchart LR A([Start]) -->|deliver Activity Card| B([Wait for Completion]) B -->|ACTIVITY_REPORTED| C([Deliver Next Card]) C --> D([End]) ``` **When to use:** Check-in workflows, assessments, or any flow where the act of completing the activity is enough to move forward. **Key configuration:** - Trigger type: **Signal** - Signal: `code == "ACTIVITY_REPORTED" && identifier == "{cardId}"` - Deliver the Activity Card via **Add Card** on the inbound transition --- ## Branching via Activity Responses Route participants down different paths based on their Activity responses or scores. Create multiple transitions out of a single state, each with a different signal condition. **Structure:** ```mermaid flowchart LR A([Start]) --> B([Activity]) B -->|scores < 5| C([Low Path]) B -->|scores 5–14| D([Medium Path]) B -->|scores >= 15| E([High Path]) ``` **When to use:** Triage, assessments, personalised content paths based on participant answers. **Key configuration:** - Trigger type: **Signal** - Signal examples: - By score: `code == "ACTIVITY_REPORTED" && identifier == "1" && scores < 5` - By element value: `code == "ACTIVITY_REPORTED" && identifier == "1" && values.READINESS_LEVEL == "Not ready"` - By multi-select: `code == "ACTIVITY_REPORTED" && identifier == "1" && anyof(values.INTERESTS, ["Running", "Swimming"])` **Tips:** - Make sure your branch conditions are mutually exclusive to avoid unexpected behaviour - Use scored activities (Sum, Average, etc.) for numeric triage — see [Scoring & Triage](#scoring--triage) below --- ## Branching via Messages Route participants based on their response to a chat message with response buttons. Send a message with options, then create separate transitions for each possible reply. **Structure:** ```mermaid flowchart LR A([Start]) --> B([Send Message]) B -->|"Yes"| C([Proceed Path]) B -->|"No"| D([Alternative Path]) ``` **When to use:** Quick decision points, consent checks, or conversational Journeys where the participant chooses a direction. **Key configuration:** - The message attachment must have **response buttons** configured (e.g. "Yes" / "No") - Trigger type: **Chat Message** — select the message sent in the previous transition, then choose which response option this transition should match - Create one transition per response option, each using the **Chat Message** trigger pointed at the same message but matching a different response **Tips:** - Add a time-based fallback transition for participants who don't respond --- ## Message-Based A Journey driven entirely by chat messages rather than Cards. Useful for conversational coaching, onboarding questions, or quick check-ins. **Structure:** ```mermaid flowchart LR A([Start]) -->|send message| B([Wait for Reply]) B -->|reply received| C([Send Next Message]) C --> D([Wait for Reply]) D -->|reply received| E([End]) ``` **When to use:** Lightweight interactions that don't need a full Activity Card, conversational onboarding, or quick pulse checks. **Key configuration:** - Attachments: **Send Message** (Inbox channel) with response buttons - Trigger type: **Chat Message** — select the message from the previous transition, then choose the expected response to advance **Tips:** - Combine message-based steps with branching to create conversational decision trees - Keep message chains short — long sequences can feel tedious; switch to Activity Cards for anything requiring more than 2–3 questions --- ## Loops Cycle a participant back to a previous state to create recurring check-ins or repeated content delivery. A transition points back to an earlier state instead of forward. **Structure:** ```mermaid flowchart LR A([Start]) --> B([Deliver Check-in]) B --> C([Wait for Response]) C --> D([Give Feedback]) D -->|wait 7 days| B ``` **When to use:** Weekly check-ins, recurring reflections, habit tracking, or any pattern that repeats on a schedule. **Key configuration:** - Create a transition from a later state back to an earlier state - Use a **Time** trigger on the looping transition (e.g. 7 days) - Add **Add Card** attachments to re-deliver the check-in activity **Tips:** - Add an exit condition to break out of the loop (e.g. a tag-based transition, a score threshold, or a time-from-start limit) - Without an exit condition, the participant will loop indefinitely — this may be intentional for ongoing Journeys --- ## Listener Sub-Journeys A main Journey starts a sub-Journey that adds a recurring Activity Card, listens for each completion, gives feedback, and loops back to listen again. Every time the participant completes the activity, the sub-Journey provides feedback and resets to wait for the next response. **Structure:** ```mermaid flowchart LR subgraph Main Journey M1([Start]) --> M2([Start Sub-Journey]) M2 --> M3([Continue with other content...]) end subgraph Sub-Journey A([Start]) --> B([Add Recurring Activity Card]) B --> C([Wait for Response]) C --> D([Give Feedback]) D -->|loop back| C end M2 -.-> A ``` The recurring Activity Card is added once and keeps appearing on the participant's schedule. The sub-Journey then loops between listening and giving feedback — it does not re-add the Card each time. **When to use:** Ongoing monitoring with automated feedback — mood tracking with encouragement, symptom diaries with tailored responses, exercise logs with progress commentary. **Key configuration:** - Main Journey: **Start Journey** attachment to launch the sub-Journey - Sub-Journey first transition: **Add Card** with a **recurring** schedule to deliver the activity on an ongoing basis (e.g. daily, weekly) - Sub-Journey listen transition: **Signal** with `code == "ACTIVITY_REPORTED" && identifier == "{cardId}"` - Sub-Journey feedback transition: **Send Message** with contextual feedback (can branch based on values/scores) - Sub-Journey loop transition: points back to the **waiting** state (not the Card delivery state) so the recurring Card continues on its schedule without being re-added **Tips:** - Use branching within the feedback step to give different messages based on scores or values (e.g. "Great job!" vs "Let's work on this together") - The sub-Journey runs independently, so the main Journey can continue delivering other content in parallel - Add a **Remove Tags** or **Stop Journey** mechanism so coaches can end the listening loop when appropriate --- ## Exception Handling Handle edge cases like non-responses, unexpected paths, or timeout scenarios using fallback transitions. **Structure:** ```mermaid flowchart LR A([Current State]) -->|Activity completed| B([Next State]) A -->|3 days, no response| C([Reminder State]) C --> D([...]) ``` **When to use:** Any Journey where a participant might not respond, or where you need a safety net to prevent participants from getting stuck. **Key configuration:** - Add a **Time** trigger transition alongside the signal-based transition from the same state - The time-based transition fires only if the signal hasn't fired first - Chain reminders: first nudge → second nudge → escalation (coach task or different path) **Common patterns:** - **No response reminder:** Time trigger → Send Message with a gentle nudge - **Escalation:** After multiple missed responses, add a **Add Task** attachment to alert a coach - **Graceful exit:** After extended inactivity, move to an end state with a "We're here when you're ready" message - **Catch-all transitions:** Add a broad signal transition as a fallback if none of the specific branch conditions match --- ## SMS & Email-Based Journeys that communicate via SMS, email, or push notifications instead of (or in addition to) in-app messages. Useful for reaching participants who may not open the app regularly. **Structure:** ```mermaid flowchart LR A([Start]) -->|send SMS| B([Wait]) B -->|time| C([Send Email]) C --> D([Wait]) D -->|time| E([End]) ``` **When to use:** Appointment reminders, medication adherence nudges, re-engagement campaigns, or populations that prefer SMS/email. **Key configuration:** - Attachments: **Send Message** with channel set to **SMS**, **Email**, or **Push Notification** - Time-based triggers between messages **Tips:** - SMS and email messages cannot have response buttons — use them for one-way communication or pair with an in-app activity for responses - Consider using a **Home Feed Card** message type to deliver a message as a Card in the participant's feed - Be mindful of SMS costs and frequency — too many messages can feel intrusive --- ## Onboarding Welcome flows triggered automatically when a participant is created, signs up, or consents. The Onboarding Journey uses special built-in signals. **Structure:** ```mermaid flowchart LR A([Start]) -->|PARTICIPANT_CREATED / SIGNED_UP| B([Wait for Consent]) B -->|PARTICIPANT_CONSENTED| C([Welcome Content]) C -->|Start Journey| D([Assign to Journey]) ``` **When to use:** Every deployment should have an onboarding Journey to welcome new participants and get them started. **Key configuration:** - Signal: `code == "PARTICIPANT_CREATED"` (coach-added) or `code == "PARTICIPANT_SIGNED_UP"` (self-registered) - Signal: `code == "PARTICIPANT_CONSENTED"` to gate content until consent is given - Attachments: **Send Message** (welcome), **Add Card** (intro content), **Start Journey** (enrol in next Journey), **Add Tags** / **Add Groups** **Tips:** - Branch based on how the participant was created (coach-added vs self-registered) to tailor the welcome experience - Use the onboarding Journey to assign tags, groups, and extras that other Journeys and Campaigns depend on - Keep onboarding short and impactful — deliver the first Card quickly so participants see value immediately --- ## Group, Tag & Extra Conditional Content Deliver different Cards, messages, or Journey paths based on a participant's groups, tags, or extras. Use conditions on transitions to personalise the experience. **Structure:** ```mermaid flowchart LR A([Start]) --> B([Assessment]) B -->|DIABETES tag| C([Diabetes Content]) B -->|PREDIABETES tag| D([Prediabetes Content]) ``` **When to use:** Multi-cohort Journeys, personalised content delivery, or any scenario where different participants should receive different experiences within the same Journey. **Key configuration:** - Add conditions to transitions using `tags.{TAG_CODE} == "true"`, `groups.{GROUP_CODE} == "true"`, or `extras.{EXTRA_CODE} == "value"` - Combine with any trigger type (time, signal, or message response) **Examples:** - `tags.HIGH_RISK == "true"` — route high-risk participants to intensive content - `groups.CLINIC_A == "true"` — deliver clinic-specific instructions - `extras.PREFERRED_LANGUAGE == "te reo"` — send content in the participant's preferred language - `extras.MEDICATION == "Metformin"` — deliver medication-specific education **Tips:** - Set tags, groups, and extras during onboarding or via earlier Journey steps so they're available for later conditions - Use `== "false"` in the **condition field** (not the signal field) to check that a tag or group is absent - Combine multiple conditions with `&&` for precise targeting --- ## Scoring & Triage Use scored Activity Cards to automatically route participants to the right intensity level. Combine scored activities with branching transitions. **Structure:** ```mermaid flowchart LR A([Start]) --> B([PHQ-9 Card]) B -->|"scores <= 4 (Minimal)"| C([Self-Guided Path]) B -->|"scores 5–9 (Mild)"| D([Light Support Path]) B -->|"scores 10–14 (Moderate)"| E([Coaching Path]) B -->|"scores >= 15 (Severe)"| F([Escalation Path + Coach Task]) ``` **When to use:** Clinical assessments (PHQ-9, GAD-7, K10), wellness screenings, readiness assessments, or any scenario where a numeric score determines the next step. **Key configuration:** - Activity scoring strategy: **Sum**, **Average**, **Min**, **Max**, or **Median** - Signal: `code == "ACTIVITY_REPORTED" && identifier == "{cardId}" && scores <= 4` - Add a **Add Task** attachment on high-severity branches to alert coaches **Tips:** - Re-assess periodically by looping back to the assessment state — combine with the [Loops](#loops) pattern - Use session variables (`vars`) to store previous scores and compare over time --- ## Drip-Feed Education Deliver a series of content pieces with time gates between each one. Unlike purely time-based delivery, drip-feed combines time delays with completion signals so participants must engage before the next piece unlocks. **Structure:** ```mermaid flowchart LR A([Start]) --> B([Content 1]) B -->|read + 2 day wait| C([Content 2]) C -->|read + 2 day wait| D([Content 3]) D --> E([End]) ``` **When to use:** Educational courses, onboarding series, or any Journey where you want participants to both engage with content and have time to absorb it before moving on. **Key configuration:** - First transition: **Signal** `code == "CONTENT_READ" && identifier == "{cardId}"` - Second transition from same state: **Time** (2 days) as a minimum gap - Combine both by using the signal transition to move to an intermediate "wait" state, then a time transition to deliver the next piece **Tips:** - Consider adding a reminder message if content isn't read within a few days - This pattern works well as a modular sub-Journey that can be reused across Journeys --- ## Nudge & Reminder Send reminders when a participant hasn't completed a Card within a set time. Escalate through channels (in-app → push → SMS → coach task) if they continue to be unresponsive. **Structure:** ```mermaid flowchart LR A([Deliver Activity]) -->|Activity completed| B([Next State]) A -->|2 days, no response| C([Nudge State]) C -->|Activity completed| B C -->|3 days, no response| D([SMS Reminder]) D -->|Activity completed| B D -->|5 days, no response| E([Coach Task + End]) ``` **When to use:** Critical activities where completion matters — medication adherence, safety check-ins, important milestones. **Key configuration:** - Each state has two outbound transitions: a **Signal** for completion and a **Time** fallback - Nudge attachments: **Send Message** (Inbox), then **Send Message** (Push Notification), then **Send Message** (SMS) - Final escalation: **Add Task** to alert a coach **Tips:** - Keep nudge messages warm and encouraging, not nagging - Space reminders further apart with each escalation step - Consider a graceful exit rather than endless reminders — "We noticed you've been busy. We're here when you're ready." --- ## Parallel Journeys Run multiple Journeys concurrently for the same participant, each handling a different concern or health area. **Structure:** ```mermaid flowchart LR subgraph Onboarding A([Onboarding Journey]) end subgraph Parallel B([Nutrition Journey]) C([Exercise Journey]) D([Mental Health Journey]) end A --> B A --> C A --> D ``` Each Journey runs independently with its own states, transitions, and timing. **When to use:** Multi-domain Journeys (e.g. a diabetes Journey covering nutrition, exercise, medication, and mental health simultaneously). **Key configuration:** - Use **Start Journey** attachments on a single transition to launch multiple Journeys at once - Each sub-Journey is self-contained with its own start and end states **Tips:** - Be mindful of content volume — three Journeys delivering Cards simultaneously can overwhelm a participant - Stagger delivery times across Journeys (e.g. nutrition Cards in the morning, exercise Cards in the afternoon) - Use tags to coordinate across parallel Journeys if needed (see [Tag-Based Coordination](#tag-based-coordination) below) --- ## Tag-Based Coordination Use tag add/remove signals to coordinate behaviour across multiple Journeys. One Journey adds a tag, and another Journey reacts to it. **Structure:** ```mermaid flowchart LR subgraph Journey A A1([...]) -->|Add Tag READY_FOR_PHASE_2| A2([...]) end subgraph Journey B B1([Start]) --> B2([Wait]) B2 -->|TAG_ADDED| B3([Deliver Phase 2 Content]) end A1 -.->| tag triggers| B2 ``` **When to use:** Cross-Journey communication, milestone tracking, or triggering secondary workflows based on progress in a primary Journey. **Key configuration:** - Journey A attachment: **Add Tags** with the coordination tag - Journey B signal: `code == "PARTICIPANT_TAG_ADDED" && tags.READY_FOR_PHASE_2 == "true"` **Tips:** - Use descriptive tag names that indicate their purpose (e.g. `COMPLETED_MODULE_1`, `HIGH_RISK_FLAGGED`, `READY_FOR_DISCHARGE`) - Clean up coordination tags with **Remove Tags** when they're no longer needed - This pattern is especially powerful with Campaigns — add a tag in one Journey and let a Campaign auto-enrol matching participants in the next --- ## Self-Enrolment from Explore Allow participants to browse and start Journeys themselves from the Explore screen in the app. Useful for optional Journeys, elective education, or self-service wellbeing tools. **Key configuration:** - Enable **Self Enrolment** on the Journey settings - Add a clear name, description, and asset image so participants understand what they're signing up for **When to use:** Optional add-on Journeys, wellbeing libraries, or situations where participants should have autonomy over their experience. **Tips:** - Combine with the Explore screen configuration to feature promoted Journeys - Self-enrolment Journeys work well as standalone modules that complement a coach-assigned core Journey - Consider using tags to track which optional Journeys a participant has self-enrolled in --- ## Combining Patterns Most real-world Journeys combine several patterns. Here are some common combinations: - **Onboarding + Scoring + Branching:** Welcome the participant, run an assessment, and route them to the appropriate intensity level - **Linear + Loops + Nudges:** Deliver weekly education with a recurring check-in and reminders for non-responders - **Listener Sub-Journey + Tag Coordination:** A mood-tracking listener runs in parallel, flags concerning scores with a tag, and the main Journey reacts - **Drip-Feed + Nudges:** Deliver an education series with reminders for participants who haven't engaged with the latest content --- ## Signals # Signals Signals allow Journeys to react to specific events, such as a participant completing an activity, reading content, or being assigned a tag. They are the building blocks for creating complex, reactive Journeys. ## Signal Structure Each signal expression can use any combination of the following fields: | Field | Description | | ------------ | -------------------------------------------------- | | `code` | The event type being evaluated | | `identifier` | The ID of the resource being evaluated (Card ID for `CONTENT_READ` and `ACTIVITY_REPORTED`, Activity ID for `HEALTH_MEASURE_REPORTED`) | | `value` | A single string value (used by some internal signals) | | `values` | Response values from an Activity or Health Measure | | `scores` | Aggregate score from a Scored Activity | | `tags` | The participant's current Tags | | `groups` | The participant's current Groups | | `extras` | The participant's current Extras | | `events` | Historical event memory for advanced journey logic | | `vars` | Session variables from journey memory | :::info The entire signal expression string — including both the values in the evaluation context (`code`, `identifier`, `value`, `values.*`, `tags.*`, `groups.*`, `extras.*`) and the function names (`anyof`, `allof`, `noneof`, `splitat`, `strlen`) — is lowercased before evaluation. All string comparisons and function names are therefore case-insensitive. ::: --- ## Signal Codes ### CONTENT_READ Fires when a participant reads a Content Card. ``` code == "CONTENT_READ" && identifier == "1" ``` ### ACTIVITY_REPORTED Fires when a participant completes an Activity Card. ``` code == "ACTIVITY_REPORTED" && identifier == "1" ``` #### Scored Activity Cards ``` code == "ACTIVITY_REPORTED" && identifier == "1" && scores < 50 ``` ``` code == "ACTIVITY_REPORTED" && identifier == "1" && scores > 50 ``` #### Activity Reported with a Categorical Activity Element In the case below, `Activity_Element_Name_Code` is the code relating to the Activity Element. To find the code, click an Activity Element in the Activity's Activity Elements column and copy its CODE. ``` code == "ACTIVITY_REPORTED" && identifier == "136" && values.{Activity_Element_Name_Code} == "I want to make changes" ``` For example: ``` code == "ACTIVITY_REPORTED" && identifier == "136" && values.ARE_YOU_READY_TO_MAKE_SOME_CHANGES == "I want to make changes" ``` To find the code for an Activity Element, highlight columns to show the code. Copy the code from the column directly. #### Activity Reported with Specific Values :::info Remember to swap out `values.NUMERIC_ELEMENT_ONE_CODE` with the code of the Activity Element you are targeting. ::: **Numeric:** ``` values.{ELEMENT_CODE} == 5 values.NUMERIC_ELEMENT_ONE_CODE == 5 ``` ``` values.NUMERIC_ELEMENT_ONE_CODE <= 5 ``` ``` values.NUMERIC_ELEMENT_ONE_CODE > 5 && values.NUMERIC_ELEMENT_ONE_CODE < 10 ``` ``` values.NUMERIC_ELEMENT_ONE_CODE <= 5 && values.NUMERIC_ELEMENT_TWO_CODE >= 5 ``` **String:** ``` values.STRING_ELEMENT_ONE_CODE == "Yes" ``` ``` values.STRING_ELEMENT_ONE_CODE == "No" ``` **Boolean:** Boolean Activity Elements use the Activity Element's configured option labels: ``` values.BOOLEAN_ELEMENT_CODE == "Yes 👍" ``` ``` values.BOOLEAN_ELEMENT_CODE == "No 👎" ``` ### HEALTH_MEASURE_REPORTED Fires when a participant submits a Health Measure. ``` code == "HEALTH_MEASURE_REPORTED" && identifier == "1" ``` You can also check specific Activity Element responses: ``` code == "HEALTH_MEASURE_REPORTED" && identifier == "1" && anyof(values.ELEMENT_CODE, ["Bothered", "Miserable"]) ``` For example: ``` code == "HEALTH_MEASURE_REPORTED" && identifier == "1" && anyof(values.HOW_ARE_YOU_FEELING_TODAY_1043, ["Bothered", "Miserable"]) ``` With a boolean Activity Element: ``` code == "HEALTH_MEASURE_REPORTED" && identifier == "1" && values.ELEMENT_CODE == "Yes 👍" ``` Or with a numeric comparison: ``` code == "HEALTH_MEASURE_REPORTED" && identifier == "1" && values.ELEMENT_CODE >= 50 ``` :::tip Finding IDs and Codes For `CONTENT_READ` and `ACTIVITY_REPORTED`, the `identifier` is the **Card ID**, found in the URL when opening a Card from the Cards list (e.g. `https://example.web.app/#/activity_plan_templates/340`). For `HEALTH_MEASURE_REPORTED`, the `identifier` is the **Activity ID**, found in the URL when opening an Activity from the Activities list (e.g. `https://example.web.app/#/activity_types/340`). The `values.ELEMENT_CODE` is the Activity Element code, found by clicking an Activity Element in the Activity's Activity Elements column and copying its CODE. ::: ### PARTICIPANT_TAG_ADDED Fires when a tag is assigned to a participant. ``` code == "PARTICIPANT_TAG_ADDED" && tags.START_CAMPAIGN_JOURNEY == "true" ``` ``` code == "PARTICIPANT_TAG_ADDED" && tags.{TAG_CODE} == "true" ``` Where `{TAG_CODE}` is the code of the tag, not the name of the tag. ### PARTICIPANT_TAG_REMOVED Fires when a tag is removed from a participant. ``` code == "PARTICIPANT_TAG_REMOVED" && values.TAG_CODE == "true" ``` :::info `PARTICIPANT_TAG_ADDED` uses `tags.{TAG_CODE}` because the tag is now present on the participant and available via the `tags` context. `PARTICIPANT_TAG_REMOVED` uses `values.{TAG_CODE}` because the tag has already been removed from `tags` at evaluation time — the handler explicitly sets it in `values` instead. ::: ### PARTICIPANT_GROUP_ADDED Fires when a participant is added to a group. The syntax below can also be used as a condition once another signal code has been interpreted (e.g. after `code == "ACTIVITY_REPORTED" && identifier == "1"`). ``` code == "PARTICIPANT_GROUP_ADDED" && groups.GROUP_ONE_CODE == "true" ``` Multiple groups can be checked together: ``` code == "PARTICIPANT_GROUP_ADDED" && groups.GROUP_ONE_CODE == "true" && groups.GROUP_TWO_CODE == "true" ``` ### PARTICIPANT_GROUP_REMOVED :::warning This signal is defined but the handler is not currently registered. It does not currently fire. ::: Fires when a participant is removed from a group. ``` code == "PARTICIPANT_GROUP_REMOVED" && values.GROUP_CODE == "true" ``` ### PARTICIPANT_EXTRA_ADDED :::warning This signal code is defined but does not currently fire. Use PARTICIPANT_EXTRA_UPDATED instead, which fires for both new and changed extras. ::: Fires when a participant extra is set. **String:** ``` code == "PARTICIPANT_EXTRA_ADDED" && values.EXTRA_CODE == "test freetext string value" ``` **JSON:** ``` code == "PARTICIPANT_EXTRA_ADDED" && values.JSON_EXTRA_CODE == "value1 string value" ``` **Numeric:** ``` code == "PARTICIPANT_EXTRA_ADDED" && values.NUMERIC_EXTRA_CODE == 4 ``` **Boolean:** ``` code == "PARTICIPANT_EXTRA_ADDED" && values.BOOLEAN_EXTRA_CODE == "true" ``` **Time:** ``` code == "PARTICIPANT_EXTRA_ADDED" && values.TIME_EXTRA_CODE == "2024-01-15T09:00:00Z" ``` ### PARTICIPANT_EXTRA_UPDATED Fires when a participant extra is created or updated. ``` code == "PARTICIPANT_EXTRA_UPDATED" && values.group == "YOUR_EXTRA_GROUP" && values.EXTRA_CODE == "new value" ``` ### PARTICIPANT_EXTRA_REMOVED :::warning This signal code is defined but does not currently fire. ::: Fires when a participant extra is removed. ``` code == "PARTICIPANT_EXTRA_REMOVED" && values.EXTRA_CODE == "true" ``` ### PARTICIPANT_JOURNEY_STARTED Fires when a participant starts a Journey. ``` code == "PARTICIPANT_JOURNEY_STARTED" ``` ### PARTICIPANT_JOURNEY_COMPLETED Fires when a participant completes a Journey. ``` code == "PARTICIPANT_JOURNEY_COMPLETED" ``` ### EXTERNAL_EVENT_RECEIVED Fires when an external event is received for a participant. ``` code == "EXTERNAL_EVENT_RECEIVED" && value == "my_event_label" ``` ### MESSAGE_RESPONDED Fires when a participant responds to a message. ``` code == "MESSAGE_RESPONDED" && identifier == "{threadId}" ``` To also check what the participant replied, use the `values.RESPONSE_*` key. The key is built from the message's configured response option labels joined by `_`, prefixed with `RESPONSE_`. For example, if the message had options `Yes` and `No`, the key is `RESPONSE_Yes_No`: ``` code == "MESSAGE_RESPONDED" && identifier == "{threadId}" && values.RESPONSE_Yes_No == "Yes" ``` ``` code == "MESSAGE_RESPONDED" && identifier == "{threadId}" && values.RESPONSE_Yes_No == "No" ``` The key always reflects the response options configured on the original message, so if options were `Agree` and `Disagree` the key would be `RESPONSE_Agree_Disagree`. ### MESSAGE_STATUS Fires when a message delivery status changes. Supported statuses: `__SENT__`, `__DELV__`, `__RCVD__`, `__BOUC__`, `__FAIL__`. ``` code == "MESSAGE_STATUS" && value == "__SENT__" ``` ``` code == "MESSAGE_STATUS" && value == "__DELV__" ``` --- ## Conditions Conditions allow you to evaluate without being triggered a specifc signal/event. You can evaluate tags, groups, or extras as conditions without listening for their assignment event. Use them in the condition field or combine them with another signal code using `&&`. **Tags:** ``` tags.{tag_code} == "true" tags.START_CAMPAIGN_CODE == "true" ``` To check that a tag is **not** present: ``` tags.{tag_code} == "false" ``` **Groups:** ``` groups.GROUP_ONE_CODE == "true" ``` To check that a participant is **not** in a group: ``` groups.GROUP_ONE_CODE == "false" ``` **Extras** (supports strings, integers, and booleans): ``` extras.PREFERRED_NEXT_ACTION == "Moving more" extras.PARTICIPANT_AGE == 37 extras.PARTICIPANT_GRADUATED == "true" ``` :::info A signal must begin with `code ==`, so when you only want to evaluate a tag/group/extra value, place it in the condition field or append it with `&&` to an existing signal code expression. The `== "false"` pattern for tags and groups only works reliably in the **condition field**. When used in a signal rule expression, an absent tag or group evaluates to empty string, not `"false"`. ::: --- ## Operators | Operator | Description | | -------- | --------------------- | | `&&` | Logical AND | | `\|\|` | Logical OR | | `==` | Equals | | `<` | Less than | | `>` | Greater than | | `<=` | Less than or equal | | `>=` | Greater than or equal | | `!=` | Not equal | | `!` | Negation | To match multiple possible values, use `anyof`: ``` anyof(tags.TAG_NAME, ["A", "B"]) ``` --- ## Functions ### splitat Splits a delimited value (using `|`) and returns the item at the given index as a string. Useful for multi-part values like blood pressure readings. :::warning `splitat` returns a string, so comparisons like `< "120"` are lexicographic (string order), not numeric. ::: :::warning If the index is out of bounds the expression produces an evaluation error and the rule will not match. It does not return `false` silently. ::: Given `values.BLOOD_PRESSURE_SYS = "118|65"`: ``` splitat(values.BLOOD_PRESSURE_SYS, 0) // returns "118" splitat(values.BLOOD_PRESSURE_SYS, 1) // returns "65" splitat(values.BLOOD_PRESSURE_SYS, 2) // index out of bounds → evaluation error, rule does not match ``` Full examples: ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && splitat(values.BLOOD_PRESSURE_SYS, 0) < "120" && splitat(values.BLOOD_PRESSURE_SYS, 1) > "80" output: false ``` ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && splitat(values.BLOOD_PRESSURE_SYS, 0) < "120" && splitat(values.BLOOD_PRESSURE_SYS, 1) > "80" output: true ``` ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && splitat(values.BLOOD_PRESSURE_SYS, 0) < "120" && splitat(values.BLOOD_PRESSURE_SYS, 1) > "80" && splitat(values.BLOOD_PRESSURE_SYS, 2) > "100" output: evaluation error // index out of bounds, rule does not match ``` ### anyof Returns `true` if **any** of the specified values match. Works with pipe-delimited multi-values. The `in` keyword can also be used: ``` code == "ACTIVITY_REPORTED" && identifier == "113" && values.ELEMENT_A in ["A", "B", "C"] output: false ``` Given `values.ELEMENT_A = "D"`: ``` code == "ACTIVITY_REPORTED" && identifier == "113" && anyof(values.ELEMENT_A, ["A", "B", "C"]) output: false ``` Given `values.ELEMENT_A = "C"`: ``` code == "ACTIVITY_REPORTED" && identifier == "113" && anyof(values.ELEMENT_A, ["A", "B", "C"]) output: true ``` Given `values.ELEMENT_A = "A|D"`: ``` code == "ACTIVITY_REPORTED" && identifier == "113" && anyof(values.ELEMENT_A, ["A", "B", "C"]) output: true ``` Also works with tags - given `tags.TAG_A = "D"`: ``` code == "CONTENT_READ" && identifier == "115" && anyof(tags.TAG_A, ["A", "B", "C"]) output: false ``` Given `tags.TAG_A = "B"`: ``` code == "CONTENT_READ" && identifier == "115" && anyof(tags.TAG_A, ["A", "B", "C"]) output: true ``` ### noneof Returns `true` if **none** of the specified values match. Works with pipe-delimited multi-values. Given `values.ELEMENT_A = "A"`: ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && noneof(values.ELEMENT_A, ["A", "B", "C"]) output: false ``` Given `values.ELEMENT_A = "D"`: ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && noneof(values.ELEMENT_A, ["A", "B", "C"]) output: true ``` Given `values.ELEMENT_A = "A|E"`: ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && noneof(values.ELEMENT_A, ["A", "B", "C"]) output: false ``` Also works with tags - given `tags.TAG_A = "B"`: ``` code == "CONTENT_READ" && identifier == "{activityId}" && noneof(tags.TAG_A, ["A", "B", "C"]) output: false ``` Given `tags.TAG_A = "E"`: ``` code == "CONTENT_READ" && identifier == "{activityId}" && noneof(tags.TAG_A, ["A", "B", "C"]) output: true ``` ### allof Returns `true` if **all** of the specified values are present. Works with pipe-delimited multi-values. Given `values.ELEMENT_A = "A|B"`: ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && allof(values.ELEMENT_A, ["A", "B", "C"]) output: false ``` Given `values.ELEMENT_A = "C|A|B"`: ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && allof(values.ELEMENT_A, ["A", "B", "C"]) output: true ``` Given `values.ELEMENT_A = "B"`: ``` code == "ACTIVITY_REPORTED" && identifier == "{activityId}" && allof(values.ELEMENT_A, ["A", "B", "C"]) output: false ``` ### strlen Returns the length of a string value. Works with Activity Element values and extras. ``` code == "ACTIVITY_REPORTED" && identifier == "1" && strlen(values.ELEMENT_CODE) > 10 ``` ``` code == "PARTICIPANT_EXTRA_UPDATED" && strlen(values.EXTRA_CODE) > 0 ``` --- ## Onboarding Signals The Onboarding Journey is a special Journey that starts automatically when a participant is onboarded. It uses these built-in signals: | Signal | Fires when | | ----------------------- | ------------------------------------- | | `PARTICIPANT_CREATED` | A coach creates a new participant | | `PARTICIPANT_SIGNED_UP` | A participant registers via the app | | `PARTICIPANT_CONSENTED` | A participant consents to use the app | ### Coach-Added Participant 1. Coach adds participant details 2. Email sent with a link to create their password (if email address provided) 3. Wait for consent 4. On consent, trigger a sub-journey (e.g. Welcome Journey) ### Self-Registered Participant 1. Participant creates profile with phone number 2. Acknowledges consent 3. Verifies account via SMS code 4. On verification, a sub-journey (e.g. Welcome Journey) is auto-triggered --- ## States # States **States** represent a Participant's possible position within the Journey. You can add a new State by dragging out from the output of an existing State and dropping it on the canvas. You can also add a state in between two existing states by clicking on the Add new State button --- ## Transitions # Transitions **Transitions** define how to move from one State to the next. You can add Transitions between States in two ways: Drag a new Transition from the output of one State and connect it to the input of another State: :::info All Transitions have to move from one State to another State. This is controlled via the Trigger - `Time` Seconds, Minutes, Hours, Days from reaching the State - `Time from Start` Seconds, Minutes, Hours, Days from when the Journey has started - `Response` When the user responds to a previous Message that the Journey has sent - `Signal` When a specifc event happens within Intervengine ::: :::info When a Transition is executed, you can add Attachments, these will be executed as the participant moves through the Journey - `Send Message` App Message, Notification, Email, SMS - `Add Card` - `Start Journey` Allows you to chain Journeys together and preform branching - `Assign Tags` or `Remove Tags` - `Add Groups` - `Add Extras` - `Add Task` ::: --- ## Versioning & Modular Design # Versioning & Modular Design Every time you publish a Journey, a new version is created. Understanding how versioning works helps you plan your Journeys so that updates reach participants quickly and safely. ## How Journey Versioning Works When you publish changes to a Journey, the platform creates a new version with an incremented version number. This has a few important implications: - **Participants already on the Journey stay on their assigned version.** They will not see any changes you make after they were assigned. - **New participants (or restarted participants) receive the latest version.** Only people who start the Journey after you publish will get the updated version. - **Changes do NOT retroactively update in-progress participants.** Once a participant is on a version, that version is locked in for them. Think of it like a printed workbook. Once you hand a workbook to a participant, you can't change the pages they already have. But the next print run will include all your edits. ## Why It Works This Way Versioning protects the integrity of in-progress experiences: - **Stability for participants** — someone mid-way through a Journey won't have states, transitions, or content change unexpectedly beneath them. - **Cohort consistency** — all participants assigned at the same time share the same experience, which matters for group programmes and research. - **Workflow safety** — removing or renaming a state in a new version won't break the flow for participants who are currently in that state. ## Recommended Approach: Modular Journeys The most effective way to work with versioning is to keep Journeys short and modular. Instead of building one large Journey that spans an entire programme, break it into smaller, self-contained modules. ### Design principles - **Keep each Journey to 1–2 weeks.** Shorter Journeys mean version changes reach participants faster. - **Make each Journey self-contained** with a clear entry point and a clear exit point. - **Chain Journeys together** using "Start Journey" attachments on transitions. When a participant finishes one module, the transition automatically starts the next one. ### Benefits - **Version drift is limited** to the duration of each module. A 2-week module means a participant is at most 2 weeks behind the latest version, rather than months. - **Coaches can update the next module** while participants complete the current one, without affecting anyone in progress. - **Easy to swap, reorder, or A/B test modules** without rebuilding the entire programme. ## Example: Modular vs Monolithic Consider a 12-week programme designed two different ways: **Monolithic approach** — one single 12-week Journey: - You publish a fix in week 3. - Participants who started in week 1 won't see the fix until they are restarted or finish and begin the Journey again. - It could take up to 12 weeks for all participants to be on the latest version. **Modular approach** — four 3-week Journeys chained together: - You publish a fix to Module 2 in week 3. - Participants currently in Module 1 will receive the updated Module 2 as soon as they transition into it. - Within 3 weeks, every active participant can be on the latest version of each module. ## Tips :::tip If you need an urgent fix to reach an in-progress participant, you can **restart** them on the Journey. This moves them to the latest published version. Use this sparingly, as it resets their progress within that Journey. ::: :::tip Always **test version changes with a test participant** before publishing. Create a test participant, assign them the Journey, and verify the experience is correct before rolling it out. ::: - Use descriptive Journey names that include the module or phase (e.g. "MoveFit — Week 1–2: Getting Started", "MoveFit — Week 3–4: Building Habits"). This makes it easy to see which module a participant is on at a glance. --- ## Assets # Assets **Assets** are reusable media files, such as images, videos, and audio clips, stored in a central library within the platform. By uploading a file once as an Asset, you can easily find and reuse it in multiple places like **Cards**, **Journeys**, **Profile Pictures**, or **Group Logos**. This ensures consistency and saves time. :::tip[Example] Imagine you need tio reuse a 'Welcome' oboarding video. You would upload the video file once to your **Assets** library and give it a name like 'Company Welcome Video'. Now, when building your **Journeys** or **Cards**, you can simply select this asset from your library to add it to your content. This is incredibly useful for managing brand consistency and saving time, as you never have to upload the same file twice. ::: ### Upload a New Asset You can upload a variety of media files, including **Images** (e.g., .jpg, .webp), **Videos** (e.g., .mp4), and **Audio** files (e.g., .mp3). Please note that there is a **10MB file size limit** for each upload. 1. Navigate to the side menu and select **More → Assets**. 2. Click the button to upload a new file, give it a clear name (e.g., 'Sleep Podcast EP 1'), and add any relevant tags. ### Use Existing Assets Once uploaded, assets become available in your media library throughout the platform. When editing an item like a **Card** or updating a **Group Logo**, you can choose to select an existing asset from your media library instead of uploading a new file. --- # Image Guidelines :::tip[DO] - Use JPG for photos - Use PNG for logos, graphics, or anything needing transparency - Keep file sizes under 500 KB each - Provide sharp images - Use consistent lighting and quality across all images ::: :::danger[DONT] - Upload huge files (over 2 MB) - they'll slow down the app - Use blurry or pixelated images - Mix portrait and landscape orientations where squares are expected ::: :::warning[Checklist] - [ ] Correct dimensions for the use type - [ ] File size under 500 KB - [ ] JPG for photos, PNG for graphics/logos - [ ] Image is clear and not pixelated - [ ] Looks good on mobile screen - [ ] Consistent style with other images in the app ::: | Cheat Sheet | Recommended size (pixels) | Recommended aspect ratio | | ---------------------------- | ------------------------- | ------------------------ | | Standard cards | 800 × 150 | 5:1 | | Square cards | 600 × 600 | 1:1 | | Slim cards | 200 x 200 | 1:1 | | Journey images (list view) | 400 x 300 | 4:3 | | Journey images (detail view) | 1200 x 900 | 4:3 | | Profile pictures | 300 x 300 | 1:1 | | Content images | 1000 x 750 | 4:3 | --- ## Cards **Standard cards** - Best size: 800 × 150 pixels (wide rectangle) - Aspect ratio: About 5:1 (much wider than tall) **Square cards** - Best size: 600 × 600 pixels (perfect square) - Aspect ratio: 1:1 (equal width and height) **Slim cards** - Best size: 200 × 200 pixels (square) - Aspect ratio: 1:1 **Horizontal scrolling cards** - 2:1 in scale (2 width: 1 height). The images vary in size and scale depending upon: - The length of text in the card heading and description - Device text size setting We recommend images should be considered at least at 4.5:1, knowing that it may scale to 2.4:1. Its important to note the scaling occurs from the center of the image. Varying image scales combined with text sizes 2.5:1 and 4:1 on a 16:9 image --- ## Journeys **Small thumbnail (in list)** - Best size: 400 × 300 pixels - Aspect ratio: 4:3 (slightly wider than tall) **Large image (detail view)** - Best size: 1200 × 900 pixels - Aspect ratio: 4:3 (same proportions, higher resolution) --- ### Participants and Coaches - Best size: 300 × 300 pixels (square) - Aspect ratio: 1:1 - Note: The app will crop these into circles automatically --- ### Contents and Content Types Images inside articles or educational content. - Best size: 1000 × 750 pixels (flexible) - Aspect ratio: Flexible, but 4:3 works well --- ## Campaigns # Campaigns A **Campaign** is a tool used to find and target a specific segment of participants and automatically assign them to a **Journey**. This allows you to proactively enroll groups of users into relevant content based on their specific needs, tags, or other characteristics, automating targeted interventions. :::tip `Example` Imagine you want to help all participants who are struggling with their sleep. You could create a campaign that searches for every participant with the tag `Sleep-Deprived`. The campaign would then automatically assign all of those participants to a specialized Journey you've built called 'Better Sleep Habits'. This ensures the right users get the right support at the right time without manual effort. ::: ### Creating a New Campaign Creating a campaign involves defining the target audience, the action to take, and when it should happen. 1. **Define the Target Audience:** First, you will build a **Query** to define your participant segment. This could be based on a simple rule, like finding all participants with a specific tag, or a more complex set of criteria. 2. **Select the Journey:** Next, you will select the **Journey** that this group of participants will be assigned to. 3. **Schedule the Campaign:** Finally, you can choose to run the campaign immediately or set a **Scheduled At** date and time for it to run in the future. ### Building Your Query Query Syntax is the powerful filtering language used to select the exact segment of participants you want to target. Think of it as building a set of precise instructions to find people based on their characteristics. A query is made up of one or more conditions. **Filtering by Tags** - **Inclusion:** To find participants who have one or more specific tags, use the `in` operator. `tags in ["TAG_A", "TAG_B"]` - **Exclusion:** To exclude participants who have specific tags, use the `not in` operator. `tags not in ["TAG_C"]` **Filtering by Groups** - **Inclusion:**`groups in ["GROUP_A", "GROUP_B"]` - **Exclusion:**`groups not in ["GROUP_C"]` **Filtering by Extras** You can also filter participants based on custom data stored in **Extras**. The syntax always starts with `extras.` followed by the code for your Extra Type. - **String Extras:** For text-based extras, use standard comparison operators. `extras.department = "Sales"` - **Numeric Extras:** For number-based extras, use mathematical operators like `>`, `<`, or `=`. `extras.age > 45` - **JSON Extras:** For extras that store complex JSON data, use the `>` notation to access nested keys. For example, if an extra `progress_data` contained `{"test": {"key": 1}}`, you could query it like this: `extras.progress_data -> test.key > 0` **Combining Filters** You can create highly specific segments by combining multiple conditions using the `&&` (AND) operator. This ensures that a participant must meet **all** the specified conditions to be included. **Complete Query Example**`tags in ["TAG_A"] && tags not in ["TAG_B"] && extras.status == "Active"` This query targets participants who have "TAG_A", do not have "TAG_B", and have their "status" extra set to "Active". ### Reviewing a Campaign After a campaign has run, you can review its performance. The system will show you when it was **Executed At** and a list of all the **Affected Participants** who were successfully found by your query and assigned to the Journey. --- ## Configurations # Configurations The **Configurations domain** is an advanced, internal-only area used to store and manage core settings that control the behavior of the Intervengine platform. Think of it as the central control panel or "settings file" for the entire application. It allows administrators to fine-tune system operations, customize templates, and toggle features without requiring code changes. :::warning[Caution] This is a powerful domain intended for use by authorized staff only. Incorrectly modifying these settings can have a significant and immediate impact on the platform's functionality for all users. ::: The Configurations domain is used to manage a wide variety of system settings. Common examples include: - **Customizing Templates:** Storing the content for automated messages, such as the `Onboarding SMS Template` or the `Unread Message Email Template`. This includes using dynamic variables like `{first_name}` to personalize the content. - **Controlling Timings:** Defining time-based settings, such as the delay for sending an unread message notification (`snoozerTimer`). - **Enabling/Disabling Features:** Using a simple true/false value to act as a feature flag, like the `Enable Unread Message Notification` setting. --- Each setting in the domain has a consistent structure that defines what it is and how it behaves. ### Name and Description The **Name** is a human-readable label for the setting, while the **Description** explains its purpose and how it's used within the system. ### Path (The Unique Key) The **Path** is the most critical field. It is a unique, machine-readable identifier (e.g., `platformConfigs.onboarding`) that the application code uses to look up the setting's value. This path must be precise and should not be changed without consulting the development team. ### Value (The Setting) The **Value** is the actual data for the setting. This could be text, a number, a `true`/`false` value, or even a block of HTML code for email templates. ### Readable/Writeable Toggles These flags control the permissions of the configuration item itself, determining if its value can be accessed (`Readable`) or modified (`Writeable`) by different parts of the system. --- Authorized staff can browse, search, and filter all existing configuration items from the main Configurations screen. To edit a setting, you click on it to open the detail view, modify its **Value** or other properties, and save the changes. Creating a new configuration item is an advanced task that requires a deep understanding of the system, as a corresponding **Path** must be implemented in the application code for the new setting to have any effect. --- ## Custom Card UI Configs # Custom Card UI Configs The Configurations domain can be used to define **custom UI config fields** that appear on the Card (Activity Plan Template) edit form. This allows you to extend the card settings beyond the built-in options (like Persistent, Dismissible, Card Layout, etc.) without any code changes. Custom fields appear below a divider in the **Ui Configs** section of the Card form, beneath the standard built-in fields. --- ## How It Works 1. You create a **Configuration** with a specific **Path** 2. The **Value** contains a JSON definition of your custom fields 3. The portal reads this Configuration and dynamically renders the fields in the Card edit form 4. When a coach saves the Card, the custom values are stored in the card's `uiConfigs` object alongside the built-in fields 5. The mobile app can then read these values to alter how it renders the card --- ## Step 1: Create the Configuration Navigate to **Configurations** and create a new item with the following settings: | Field | Value | | ------------- | -------------------------------------------- | | **Name** | A descriptive name, e.g. `Custom Card Theme` | | **Path** | `uiConfigs.activityPlanTemplate.custom` | | **Readable** | On | | **Writeable** | On | :::info The **Path** must be exactly `uiConfigs.activityPlanTemplate.custom`. This is the path the portal uses to look up custom card UI config definitions. All custom card fields must be defined under this path. ::: ## Step 2: Define Fields in the Value The **Value** field must contain a JSON object with a `name` and a `fields` array. Each entry in `fields` defines a single form input. Here is the general structure: ```json { "name": "My Custom Config", "fields": [ { "type": "TEXT", "path": "uiConfigs.", "key": "MY_CUSTOM_FIELD" } ] } ``` Each field object supports the following properties: | Property | Required | Description | | ----------------- | -------- | --------------------------------------------------------------------------------------------------------- | | `type` | Yes | The input type. One of: `BOOLEAN`, `TEXT`, `NUMBER`, `SELECT`, `PLACEHOLDER` | | `path` | Yes | The storage path prefix. Use `uiConfigs.` so the value is stored in the card's `uiConfigs` object | | `key` | Yes | The field key in `MACRO_CASE` (e.g. `CARD_THEME`). This becomes the key in `uiConfigs` | | `label` | No | A custom display label for the field. If omitted, the key is converted to title case (e.g. `CARD_THEME` → **Card Theme**) | | `defaultValue` | No | The default value when the field is empty. If omitted, the field starts blank | | `required` | No | Set to `true` to make the field mandatory | | `disabled` | No | Set to `true` to make the field read-only | | `choices` | No | Required for `SELECT` type. Array of `{ "value": "...", "label": "..." }` objects | | `condition` | No | Show this field only when another field matches specific values (see Conditional Fields below) | | `placeholderSize` | No | For `PLACEHOLDER` type only. Grid column width (1-12) for layout spacing | :::tip By default, the `key` is automatically converted to a human-readable label in the form. For example, `CARD_THEME` becomes **Card Theme**. You can override this by setting the `label` property to any custom text (e.g. `"label": "Reading Time"`). ::: --- ## Step 3: Choose the Right Field Type ### BOOLEAN A toggle switch for true/false values. ```json { "type": "BOOLEAN", "path": "uiConfigs.", "key": "SHOW_PROGRESS_BAR", "defaultValue": "true" } ``` ### TEXT A free-text input field. ```json { "type": "TEXT", "path": "uiConfigs.", "key": "CUSTOM_HEADER_TEXT", "defaultValue": "Welcome", "required": true } ``` ### NUMBER A numeric input field. ```json { "type": "NUMBER", "path": "uiConfigs.", "key": "ANIMATION_DURATION_MS", "defaultValue": "300" } ``` ### SELECT A dropdown with predefined choices. ```json { "type": "SELECT", "path": "uiConfigs.", "key": "CARD_THEME", "defaultValue": "light", "choices": [ { "value": "light", "label": "Light" }, { "value": "dark", "label": "Dark" }, { "value": "system", "label": "System Default" } ] } ``` ### PLACEHOLDER Not a real input - used for layout spacing in the form grid. ```json { "type": "PLACEHOLDER", "path": "uiConfigs.", "key": "SPACER", "placeholderSize": 6 } ``` --- ## Conditional Fields You can make a field visible only when another field has a specific value. This is useful for showing options that only apply in certain contexts. Add a `condition` object with: - `key` - the key of the field to check - `values` - an array of values that make this field visible ```json { "name": "Theme Settings", "fields": [ { "type": "SELECT", "path": "uiConfigs.", "key": "CARD_THEME", "defaultValue": "light", "choices": [ { "value": "light", "label": "Light" }, { "value": "dark", "label": "Dark" }, { "value": "custom", "label": "Custom" } ] }, { "type": "TEXT", "path": "uiConfigs.", "key": "CUSTOM_PRIMARY_COLOR", "defaultValue": "#000000", "condition": { "key": "CARD_THEME", "values": ["custom"] } }, { "type": "TEXT", "path": "uiConfigs.", "key": "CUSTOM_BACKGROUND_COLOR", "defaultValue": "#FFFFFF", "condition": { "key": "CARD_THEME", "values": ["custom"] } } ] } ``` In this example, the two color fields only appear when **Card Theme** is set to "Custom". --- ## Full Example Here is a complete Configuration Value that adds theme, layout, and behavioral customizations to cards: ```json { "name": "Custom Card Behaviors", "fields": [ { "type": "SELECT", "path": "uiConfigs.", "key": "CARD_THEME", "defaultValue": "light", "choices": [ { "value": "light", "label": "Light" }, { "value": "dark", "label": "Dark" } ] }, { "type": "BOOLEAN", "path": "uiConfigs.", "key": "SHOW_PROGRESS_BAR", "defaultValue": "true" }, { "type": "NUMBER", "path": "uiConfigs.", "key": "AUTO_ADVANCE_DELAY_MS", "defaultValue": "0" }, { "type": "TEXT", "path": "uiConfigs.", "key": "COMPLETION_MESSAGE", "defaultValue": "Well done!" } ] } ``` This would render four additional fields in the **Ui Configs** section of every Card form: a theme dropdown, a progress bar toggle, an auto-advance delay input, and a completion message text field. --- ## How Custom Fields Are Stored When a coach saves a card, the custom field values are merged into the card's `uiConfigs` object. For the example above, the stored data would look like: ```json { "IS_PERSISTENT": false, "IS_DISMISSIBLE": true, "CARD_LAYOUT": "STANDARD", "CARD_THEME": "dark", "SHOW_PROGRESS_BAR": true, "AUTO_ADVANCE_DELAY_MS": 500, "COMPLETION_MESSAGE": "Well done!" } ``` The built-in fields and custom fields live side-by-side in the same object. The mobile app reads from this object to determine how to render the card. :::warning Custom field keys must not conflict with built-in keys (`IS_PERSISTENT`, `IS_DISMISSIBLE`, `CARD_LAYOUT`, `IMAGE_ASPECT_RATIO`, `CARD_LAYOUT_TYPE`, `CARD_CONTENT_TYPE`, `START_BUTTON_LABEL`, `NEXT_BUTTON_LABEL`, `END_BUTTON_LABEL`, `RESPONSE_UI_CONFIGS`). Using a conflicting key will cause unpredictable behavior. ::: --- ## Notifications # Notifications ## Enable Unread Message Notification - **Config group:** `platformConfigs.notification` - **Config name:** `Enable Unread Message Notification` - **Value format:** Boolean string (`"true"` or `"false"`) - **Default:** Feature is disabled if the config is missing or set to `"false"` When a coach has unread messages and the snoozer timer fires (see Snoozer Timers below), the system checks this config. If `true`, it sends an email to the coach with a summary of their unread messages. If `false` or missing, the email is skipped. The unread message event is still published regardless, so other listeners (e.g. SSE, push) are unaffected. ## Unread Message Notification HTML Template - **Config group:** `platformConfigs.notification` - **Config name:** `Unread Message Notification HTML Template` - **Value format:** Go `html/template` string - **Default:** Falls back to a simple inline HTML string: _"You have N new messages. Please click the link to view messages."_ Used by the unread message notification handler to render the coach notification email body. The template is parsed with Go's `html/template` engine and executed with the following variables: - `{{.Total}}` - total unread message count - `{{.MessageIcon}}` - URL to the new message icon hosted on the server - `{{.ViewAllMessageURL}}` - link to the portal tasks page (`{PORTAL_URL}/#/tasks`) - `{{.AppName}}` - formatted as `"{year} {APP_NAME}"` (e.g. "2026 Intervengine") - `{{.Messages}}` - array of message objects, each containing: - `{{.CreatorName}}` - full name of the message sender - `{{.CreatorInitials}}` - initials derived from the name - `{{.CreatorPhotoURL}}` - profile photo URL (can be nil) - `{{.Content}}` - message content - `{{.SentAt}}` - human-readable time ago string (e.g. "2 minutes ago") ## Snoozer Timers ### Unread Message - **Config group:** `platformConfigs.snoozerTimer` - **Config name:** `Unread Message` - **Value format:** Duration string (e.g. `"1m"`, `"5m"`, `"1h"`, `"30s"`). Set to `"off"` to disable. - **Default:** `1m` (1 minute) When a message is sent and the recipient coach is not currently connected via SSE (i.e. not online), a snoozer task is enqueued with this delay. The task is deduplicated per coach - if multiple messages arrive while the coach is offline, only one snoozer task exists at a time. When the snoozer fires after the configured delay, the system queries for all unread messages from approximately the last minute and (if the Enable Unread Message Notification config is enabled) sends a notification email to the coach. Setting the value to `"off"` disables the snoozer entirely - no unread message check will be scheduled. ### Not Consented - **Config group:** `platformConfigs.snoozerTimer` - **Config name:** `Not Consented` - **Value format:** Duration string (e.g. `"1m"`, `"24h"`, `"7d"`) - **Default:** `7d` (7 days) When a new participant is created and they have not yet consented, a snoozer task is enqueued with this delay. When the timer fires, it publishes a "participant not consented" event to the Task domain, which can trigger follow-up actions such as creating a coach task to check in with the participant. If the config is not set, defaults to 7 days. --- ## Schedulers # Schedulers ## Activity Reminder Scheduler - **Config group:** `platformConfigs.scheduler.activityReminders` - **Value format:** Simplified cron expression - `"minute hour"` in UTC (e.g. `"0 *"`) - **Default:** `"0 *"` (every hour at minute 0) A Cloud Tasks scheduled job fires a time event at a regular interval. When the coaching event handler receives this event, it reads the Activity Reminder Scheduler configuration. The value is parsed as a two-part cron expression (`minute hour`). A wildcard `*` means "match every" - so `"0 *"` means "at minute 0 of every hour". The handler compares the parsed time against the current UTC time. If the current hour and minute match, it runs the activity reminders job. The reminders job queries all scheduled activities falling within the global timezone range (UTC-12 to UTC+14). For each activity, it checks whether the participant's preferred timezone and preferred reminder hours match the current time. If so, a reminder event is published containing the participant's name, contact details, and activity details, which downstream handlers use to send push/SMS/email reminders. ## Missing Activity Scheduler - **Config group:** `platformConfigs.scheduler.missingActivities` - **Value format:** Simplified cron expression - `"minute hour"` in UTC (e.g. `"5 20"` = 20:05 UTC) - **Default:** None - if not set, the check is skipped entirely Loaded alongside the Activity Reminder Scheduler in the same time event handler. If the config exists and the current UTC time matches the cron expression, it runs the missing activities job. The job uses the Number of Consecutive Missed Days config (see below) and a hardcoded 7-day window to query for participants who have missed activities on consecutive days. It publishes a missing activity pattern event containing each participant's ID, total missing activities, and the list of missed activity names. This is typically used to create coach tasks for follow-up. ### Number of Consecutive Missed Days - **Config group:** `platformConfigs.tasks.consecutiveMissedDays` - **Value format:** Integer string (e.g. `"2"`) - **Default:** `2` Used by the Missing Activity Scheduler during each run. The value controls the threshold - how many consecutive days of unreported activities a participant must have within a 7-day window before the system flags it. If the value is not set, not a valid integer, or less than 1, it falls back to `2`. --- ## Extras & Extra Types # Extras & Extra Types **Extras** are custom fields you can create to store specific, freeform information on a participant's profile that doesn't fit into our standard domains. Their primary purpose is to make the platform flexible for your unique data needs. Think of it like adding a custom field to a contact in your address book, such as 'Employee ID' or 'Dietary Preference'. Extras allow you to define and store the exact data points you require for each participant. :::tip[Example] Imagine you need to track Department & Start Date for each employee. 1. First create two **Extra Types**: one named "Department" (with a Text format) and another named "Start Date" (with a Date/Time format). 2. Now, when a coach views any employee's profile, they can add these new "Extras". 3. The coach selects the "Department" Extra and enters "Marketing", then selects the "Start Date" Extra and enters the employee's start date. This custom information is now stored directly on that participant's record. ::: ### The Two-Part System: Extra Types and Extras The Extras system is built on a simple two-part structure: the template for the data (**Extra Type**) and the actual data itself (**Extra**). ### Extra Types (The Template) Before you can add any custom data, you must first create an **Extra Type**. An Extra Type is the **blueprint** for your custom field. It defines crucial properties like: - **Name**: What the field is called (e.g., 'Emergency Contact'). - **Format**: The type of data it will hold (e.g., Text, Number, Yes/No, JSON, Date/Time). - **Rules**: Its behavior, such as whether it's hidden from the participant (`isHidden`), cannot be edited after creation (`isReadOnly`), or keeps a visible history of its changes (`Log History`). ### Extras (The Data) Once an Extra Type has been created, a coach can then add an **Extra** to a specific participant's profile. This is the **actual data** being stored. When a coach adds an Extra, they select from the list of available Extra Types (like 'Emergency Contact') and are then presented with a form to enter the value that matches the defined format. --- ## Groups # Groups **Groups** are labels used to manage access and visibility across the platform, creating private spaces for specific users and content. While they help organize items like tags do, their primary purpose is **access control**. The fundamental rule is: **coaches can only see participants and items that are in the same group(s) as they are.** This ensures that information is secure and only visible to the intended audience. :::tip `Example` Imagine a physiotherapist, Dr. Anya, who runs two clinics: one in **Uptown** and one in **Riverside**. - She creates a group for each location: `Uptown Clinic` and `Riverside Clinic`. - She assigns her Uptown coaches and patients to the `Uptown Clinic` group. Now, those coaches can **only** view and manage patients from the Uptown clinic, ensuring patient privacy is maintained between locations. - She then creates a "Post-Op Knee Rehab" **Journey** and assigns it to the `Uptown Clinic` group. This means only patients from that specific clinic can find and self-enroll in it. ::: ### The `Shared` Group A special default group called `Shared` is available. Any item, like a Journey or Card, assigned to the `Shared` group is visible to **everyone**, regardless of their other groups. It functions as a global or public space for content accessible to all users. ### Admin Access Coaches with an **admin** role bypass all group rules. They have full visibility across all groups and can see every participant and item in the system. --- ### Group Details When you create a group, you can specify its details: - **Type**: A label for organization, either `Organisation` (for a whole company or clinic) or `Coaching Group` (for a small, specific team). - **Image/Logo**: It's highly recommended to add a logo so your groups are easily recognizable at a glance. --- ## Role-Based Access Control (RBAC) # Role-Based Access Control (RBAC) **Role-Based Access Control (RBAC)** is the system used to manage what users can see and do within the platform. Its primary purpose is to ensure users only have access to the information and tools necessary for their roles, enhancing security and simplifying user management. Think of it like a modern office keycard system 🔑. Your job title (your **Role**) determines which doors (the **Resources**) your keycard (your **Permissions**) can open. Here is how our pre-existing roles work as an example: :::info[The Admin Role (Full Access)] - The default **Admin** role is designed for full access. To achieve this, it must be granted a separate **Permission** for _every available resource_ in the system (e.g., `participants.*`, `journeys.*`, `webhooks.*`, etc.). - **Result**: Users assigned the Admin role have unrestricted access to every feature, all data, and every configuration setting across the entire platform. ::: :::info[The Coach Role (Restricted Access)] - The default **Coach** role is pre-configured for typical coaching duties. It has **Permissions** that grant it access to essential resources like `participants.*`, `journeys.*`, and `groups.*`. - It is deliberately **not** given permissions for advanced configuration resources like `webhooks.*` or `extras.*`. - **Result**: Users assigned the Coach role can fully manage their participants and programs but are restricted from accessing sensitive system settings that are not relevant to their day-to-day work. ::: The RBAC system is built on three simple but powerful concepts that work together to grant access. ### Resources (The What) **Resources** are the features, data, or areas of the platform that you want to control access to. A resource is a clearly defined part of the system, such as `webhooks.*`, `journeys.*`, or `participants.read`. ### Roles (The Who) **Roles** are like job titles that represent a group of users with similar access needs. Instead of assigning permissions to each person one by one, you assign them a Role, like the built-in 'Admin' or 'Coach'. A user can have multiple roles. ### Permissions (The Link) **Permissions** are the crucial link that connects a **Role** to a **Resource**. Creating a permission is the action of granting a specific role access to a specific resource. Permissions can also have an expiry date (`Valid Until`) for granting temporary access. ### How RBAC Works in Practice The typical workflow for managing access is a straightforward process: 1. **Define your Resources:** First, ensure all the features and data areas you want to control are defined as resources. 2. **Create Custom Roles:** If needed, create new roles that match the distinct job functions of your users. 3. **Grant Permissions:** Connect your roles (both custom and built-in) to the resources they need by creating permissions. Once set up, you can manage a user's access simply by assigning or removing roles from their profile, and the system will handle the rest. --- ## Tags & Tag Types # Tags & Tag Types **Tags** are descriptive keywords or labels used to classify and organize items across the platform. By applying the same tag to different types of items - like **Participants**, **Journeys**, **Tasks**, or **Cards -** you can create a powerful shared context between them. A **Tag Type** is an optional category for every **Tag**. It provides a way to classify, filter, and report on different types of tags. :::tip[Using a single tag called `Leadership-Skills`] - **Tag a Participant** to identify them as part of a leadership development program. - **Tag Cards** that contain content related to management theory. - **Tag a Journey or Task** designed to practice decision-making. This unified tagging is incredibly useful. When coaching a participant, you gain immediate context by seeing all the associated content and tasks that share the same tag. Similarly, when building reports, it allows you to analyze how users engage with all resources related to a specific topic like `Leadership-Skills`. ::: --- ## Tasks & Task Areas # Tasks & Task Areas A **Task** is an actionable to-do item for a coach or team. It serves as a reminder to perform an action, such as following up with a participant or reviewing a specific event. While tasks are often linked to a participant, this is optional; they can also be used for general administrative or team-based activities. A **Task Area** is a required category for every task. It provides a way to classify, filter, and report on different types of work. Think of them as folders or labels for your to-do list, such as 'High Risk Alerts', 'Onboarding', or 'Weekly Reviews'. :::tip[Example] Imagine a participant indicates they are at a high risk of disengagement. A coach can create a task to intervene: 1. **Task Name:** 'High Disengagement Risk - Follow Up Immediately'. 2. **Participant:** The specific at-risk participant is linked to the task. 3. **Task Area:** The task is assigned to the 'High Risk Alerts' Task Area. 4. **Priority:** The coach sets the priority to `CRITICAL`. 5. **Assignment:** The task is assigned directly to the participant's primary coach. This creates a formal, trackable item that ensures the high-risk situation is addressed promptly. ::: ### Built-in Tasks In addition to tasks created by users, the system automatically generates tasks to ensure critical events are not missed. :::info[Unread Messages] The system monitors messages from participants. If a message remains unread for a period defined in the system's **Configuration**, a new task is automatically generated in the 'Unread Messages' area to prompt the assigned coach to respond. ::: :::danger[Participant Not Consented] When a new participant is added but does not complete the consent process within a certain timeframe, the system automatically creates a task. This alerts the relevant team members to follow up and assist with onboarding. ::: ### Assignment and Visibility A task's visibility to coaches is controlled by its assignment settings, which are flexible and can be combined: - **Assigned Coach:** If a task is assigned directly to a specific coach, it will appear in their personal task list. - **Assigned Groups:** If a task is assigned to one or more groups, it will be visible to all coaches who are members of those same groups. - **Unassigned:** A task can have no specific coach or group, making it visible to a wider range of users based on other permissions. ### Priority and Due Date To help manage workloads, every task has a **Priority** level (Low, Medium, High, or CRITICAL) and can be given an optional **Due Date** to specify a deadline. ### Task Logs The system keeps a detailed, timestamped history of every action taken on a task, providing a full audit trail for all coaching interactions. ### Actioning a Task Once a task is created, coaches can perform several actions on it: - **Activate / Archive:** You can toggle a task between an `Active` and `Archived` state. Archiving removes a task from the main list but keeps its history. - **Complete:** When you have finished the work, click **Complete**. This opens a window allowing you to add notes about the outcome before the task is marked as completed and archived. - **Dismiss:** If a task is no longer needed, click **Dismiss**. This is a shortcut that immediately marks the task as 'Dismissed' and archives it without prompting for notes. --- ## Webhooks # Webhooks **Webhooks** are automated messages sent from Intervengine to your other applications when a specific event occurs. While they can be used for simple notifications, their primary purpose is **system integration**. The fundamental rule is: **when a selected event happens in Intervengine, the system will instantly send a data payload to a specific URL you provide.** This allows your external systems to react to actions in real-time, without needing to constantly ask our system if anything new has happened. :::tip[Example] Imagine you need to keep your main customer database or CRM system synchronized. - You create a webhook and in the **Target URL** field, you paste the unique web address provided by your CRM. - You then select the **Event Types** you want to listen for, such as `Participant Created` and `Participant Profile Updated`. - Now, when a new participant joins Intervengine, their data is instantly sent to your CRM, which automatically creates a new contact. If a participant later updates their profile, the webhook triggers again, and your CRM updates the existing contact record. ::: ### The Secret Key A special, confidential **Secret Key** is automatically generated for every webhook you create. This key is sent along with every notification, allowing your receiving application to verify that the data is genuinely from Intervengine and has not been tampered with. It's a critical tool for ensuring your integration is secure. ### The Data Payload The data sent by a webhook is formatted in a standard structure (JSON) that is easy for other systems to read. It contains all the relevant information about the event that occurred, such as the participant's details or the content of a message. ### Webhook Details When you create a webhook, you must specify its configuration: - **Name**: A simple label for you to easily identify the webhook's purpose (e.g., "CRM Sync"). - **Target URL**: The destination web address where the data payload will be sent. - **Event Types**: The specific triggers you want the webhook to listen for, such as `Message Sent` or `Participant Tags Added`. ### Using Webhooks When you create and save a webhook, you must securely copy the **Secret Key**. You then need to configure your external application (like your CRM) to listen for incoming data at the **Target URL** and use the **Secret Key** to validate each request it receives. --- ## Chats # Chats **Chats** enable direct, text-based communication between **Coaches** and **Participants**. They provide a secure messaging channel within the platform for both reactive support and proactive engagement. ## Types of Chats ### Coach-Initiated Coaches can start conversations with participants for personalized guidance, follow-ups, or support. ### Journey-Initiated **Journeys** can automatically send messages as part of States or Transitions-useful for timed check-ins, conditional support, or celebration messages. Messages sent from Journeys can include **response options** (buttons) that allow participants to reply with a quick tap, making it easy to branch Journey logic based on their response. :::tip[Response Options] A Journey asks: "Are you experiencing any side effects?" with buttons for "Yes" and "No"-branching to different States based on the participant's choice. ::: ## Message Content Chats support plain text, emojis, and response buttons (for Journey-initiated messages). For rich content like educational materials, coaches should prescribe **Content Cards** to the participant's **Feed**. :::info[No Rich Media] Chats currently don't support images, videos, files, or formatted text. ::: ## Notifications & Tasks When participants send messages, coaches are notified immediately. If a message remains unread past a configured threshold, the system automatically creates a **Task** to ensure timely response. :::warning[Response Times Matter] Rapid responses (within 24 hours) correlate strongly with participant retention and satisfaction. ::: ## Best Practices ### For Coaches: - Be personal, timely, and encouraging - Keep messages concise and actionable - Set clear expectations about response times ### For Journey Designers: - Don't over-message-use sparingly - Use response buttons for simple branching decisions - Time messages appropriately based on participant preferences --- ## Device Data # Device Data **Device Data** displays automatically collected health information from participants' devices via **Google Fit** or **Apple Health** integrations. This passive data collection supplements self-reported Activity Plans with objective device metrics. :::tip[Example] A coach reviews Andy's Device Data and sees Sleep Pattern shows "Inconsistent Late Sleeper," Activity Level shows "Moderately Active," and Mental Wellness shows "Good Mental Wellness"-all calculated automatically from device sensors. ::: ## What Device Data Includes ### Archetypes Behavioral patterns identified from device data. ### Trends Changes in biomarkers or behaviors over time, highlighting improving or declining patterns. ### Health Scores Composite scores calculated from multiple data points to indicate overall wellness in specific areas. ### Biomarkers Individual health metrics like heart rate, step count, sleep duration, or active minutes. ### Comparisons Benchmarks comparing participant data against population averages or personal baselines. ## Sahha Integration When **Sahha** is integrated, it processes raw device data from Google Fit or Apple Health and calculates Archetypes, Scores, and Biomarkers automatically. :::info[Sahha Integration] Sahha provides passive data collection from device sensors, supplementing self-reported data. ::: --- ## Extras # Extras **Extras** are custom fields for storing participant-specific information that doesn't fit standard profile fields. They provide flexibility to capture unique data points your organization requires. :::tip[Example] A corporate wellness program tracks Employee Department, Start Date, Manager Name, and Preferred Contact Time using Extras. ::: ## How Extras Work ### Extra Types (Templates) Administrators create **Extra Types** that define the field blueprint: name, format (Text/Number/Yes-No/Date-Time/JSON), and behavior rules (`isHidden`, `isReadOnly`, `Log History`). ### Extras (Data) Coaches add **Extras** to individual participant profiles by selecting an Extra Type and entering the value. ## Formats - **Text**: Emergency contacts, dietary restrictions, notes - **Number**: Employee IDs, member numbers - **Yes/No**: Onboarding status, research consent - **Date/Time**: Enrollment dates, appointments - **JSON**: Complex data structures (for integrations) ## Special Properties - **isHidden**: Data stored but not visible to participant in app - **isReadOnly**: Can be added once but not edited (prevents accidental changes) - **Log History**: Maintains audit trail of all value changes ## Use Cases ### Campaigns & Segmentation Filter participants by Extra values (e.g., "all participants where `extras.department = 'Sales'`") ### Integrations Store external system IDs (CRM contacts, EHR patient numbers, billing accounts) to link Intervengine with other platforms. ## Extras vs. External ID - **External ID**: Single primary identifier (e.g., main EHR patient ID) - **Extras**: Multiple identifiers or other custom data ## Best Practices - Plan Extra Types before creating them - Use descriptive names and consistent naming conventions - Only create Extras for data you'll actually use - Keep data current and respect privacy settings --- ## Feed # Feed **The Feed** is the coach's preview of what the participant sees in their app. It shows all assigned **Activity Plans** organized by **Health Area**, giving coaches visibility into the participant's daily experience. :::tip[Example] A coach reviews Sarah's Feed and sees today's Activity Cards, educational Content from her Journey, and persistent Health Measures-all organized by Health Area. ::: ## How Activity Plans Appear Activity Plans reach the participant's Feed through three pathways: ### Manual Prescription Coaches can prescribe Activity Plans directly to participants for personalized interventions. ### Journey Delivery When assigned to a **Journey**, participants receive Activity Plans automatically. This is the primary method for structured programs. ### Health Measures Health Measures are Activity Plans with no schedule, allowing participants to log data (weight, mood, etc.) whenever they choose. They remain persistently available in the Feed. :::info[Cards & Activity Plans] All Cards are Activity Plan templates. Every Card assignment creates an Activity Plan. Activity Plans can be completed on schedule or anytime-Health Measures have no schedule, so they're always available for anytime completion. ::: ## Organization Activity Plans are grouped by **Health Area** to help participants understand how different activities support their wellness. The calendar view lets participants review past activity and track streaks. ## Best Practices - **Don't Overwhelm**: Balance the number and types of Activity Plans to maintain engagement - **Strategic Timing**: Schedule Activity Plans when participants are most likely to complete them - **Use Health Areas**: Group related activities together for clarity --- ## Participants # Participants **Participants** are the end-users of the Intervengine platform. They are the individuals who receive coaching, engage with **Journeys** and **Content**, and complete **Activities** and **Health Measures**. Think of them as the members, clients, or patients your program is designed to support. The entire platform is built around delivering a tailored and engaging experience to them. ### Profile Information Each participant has a profile with their **First Name**, **Last Name**, **Gender**, **Email**, and **Mobile Number**. :::warning[Uniqueness Rules] To ensure every account is unique, **Email addresses and Mobile Numbers** must be unique across the _entire system_. A Coach cannot use the same email or mobile number as another Coach or a Participant. ::: ### Organization & Segmentation You can organize participants for targeted interventions and access control: - Apply **Tags** to segment participants into dynamic groups (e.g., `high-risk`, `new-starter`) for use in **Campaigns**. - Apply **Groups** to control which coaches can see them and what content they can access. ### Preferences & Notifications Participants can set their **Preferred Timezone** and **Reminder Hours** to ensure they receive notifications and scheduled activities at the most convenient times for them. ### External ID This is an optional, unique identifier you can use to link a participant's Intervengine profile to a record in an external system, such as a Customer Relationship Management (CRM) or an Electronic Health Record (EHR) system. --- ## Progress # Progress **Progress** is the coach's central view for tracking participant outcomes through two main sections: **Activity Plans** and **Journeys**. :::tip[Example] A coach views John's Progress and sees his active Activity Plans with completion rates, his enrolled Journeys with their current status, and visualizations of his weight trending down over 8 weeks. ::: ## Progress Data & Visualizations Progress shows self-reported data collected from participants through Activity Plans and Health Measures. ## Activity Plans The **Activity Plans** section shows all assigned Activity Plans with their status, completion rates, and schedule details. :::info[Cards & Activity Plans] All **Cards** are Activity Plan templates. When a coach assigns a Card, it creates an Activity Plan. Every card assignment is an Activity Plan. ::: ### Types of Activity Plans **Recurring Activity Plans** create scheduled prompts at specific times (daily, weekly) for building habits, ongoing monitoring, and routine check-ins. **One-Off Activity Plans** assign an Activity Plan once without recurrence-useful for single assessments, content, one-time tasks, or initial check-ins. :::tip[Example] A coach creates a recurring plan for Maria to log her mood daily at 8 AM for 8 weeks. The list view shows completion percentage and recent activity. ::: ### Activity Plan Completion Activity Plans can be completed in two ways: - **Scheduled Completion**: Participant completes the Activity Plan at its scheduled time (e.g., daily at 8 AM) - **Anytime Completion**: Participant completes the Activity Plan whenever they choose, regardless of schedule **Health Measures** are Activity Plans with no schedule-they're only available as anytime completions, which is why they appear in the Feed as permanently available. :::info[Health Measures] Health Measures have no schedule, so participants can log data (weight, mood, etc.) whenever convenient. They remain persistently visible in the Feed. ::: ### Creating Activity Plans Configure the Card template, recurrence pattern (daily/weekly), time, duration, and start date. Activity Plans can be prescribed manually or delivered automatically through **Journey** States. ### Managing Activity Plans - **Change Schedule**: Modify recurrence or timing for future instances - **Extend or End Early**: Adjust duration as needed :::warning[Note] Activity Plans cannot be paused. To temporarily stop, end the plan and create a new one later. Schedule changes only affect future instances. ::: ## Participant Journeys The **Journeys** section shows all active and past Journey enrollments with their progress status. **Participant Journeys** are active Journey enrollments that deliver Activity Plans, Content, and Chat messages automatically based on the Journey's States and Transitions. ### Managing Participant Journeys - **Pause**: Temporarily halt progress (e.g., vacation) - **Resume**: Reactivate from current State - **Stop**: Permanently end enrollment ### Enrollment Settings Configure start date, intervention hours, reminder preferences, and participant-specific parameters when prescribing. ## Data-Driven Coaching Use Progress data to: - Identify intervention opportunities (declining metrics, low completion rates) - Personalize Journeys based on outcomes - Provide evidence-based feedback in Chats - Generate reports --- ## Tasks # Tasks **Tasks** are actionable to-do items for coaches to track critical activities, follow-ups, and interventions. They ensure important actions don't fall through the cracks. :::tip[Example] A participant's PHQ-9 score indicates severe depression. The system automatically creates a CRITICAL priority Task assigned to their coach: "High Depression Score - Immediate Follow-Up Required." ::: ## How Tasks Are Created ### Manual Creation Coaches can create Tasks for scheduling follow-ups, assigning work to team members, or setting reminders. ### Automatic System Tasks The platform automatically generates Tasks for critical situations: - **Unread Messages**: When a participant's Chat message remains unread past a configured threshold (with email notification) - **Participant Not Consented**: When onboarding isn't completed within the timeframe - **Webhook Tasks**: External systems can trigger Task creation via API ## Task Organization Tasks are organized into **Task Areas** (categories like "High Risk Alerts," "Onboarding," "Unread Messages") for filtering and prioritization. Each Task has: - Name, linked Participant (optional), Task Area, Priority (Low/Medium/High/CRITICAL), Due Date (optional), Assigned Coach/Groups ## Task Actions - **Complete**: Mark done with notes documenting the outcome - **Dismiss**: Remove Tasks that are no longer relevant (no notes) - **Archive/Activate**: Toggle between active and archived states ## Notifications Coaches receive: - **In-app badges**: Count of active Tasks - **Email notifications**: For specific tasks like unread messages or CRITICAL priorities ## Best Practices ### For Coaches: - Check Tasks daily, addressing CRITICAL first - Add detailed completion notes for continuity of care - Set realistic due dates - Create meaningful Task Areas matching team workflow - Configure reasonable thresholds for automatic Tasks - Monitor completion rates to identify bottlenecks --- ## Cards vs Activity Plans # Cards vs Activity Plans ## The Three-Tier Model | Card | Activity Plan | Activity Plan Detail | | --------------------------- | -------------------------------------------------- | ------------------------------------------------- | | A **template** (the recipe) | A **schedule** for one participant (the meal plan) | The **app card** the participant sees (each meal) | | Created once, reusable | Created when a Card is assigned | Generated automatically from the schedule | | Lives in the Cards library | Lives on the participant's profile | Appears in the participant's app | :::tip Key Takeaway **Card → Activity Plan → Activity Plan Details** The Activity Plan is a scheduling container - it generates Activity Plan Details (app cards) based on its schedule. ::: ## How It Works ### 1. Card (Template) A Card defines what to deliver - an Activity, Content, or Health Measure. Created once by a coach, reusable across many participants. ### 2. Activity Plan (Schedule) When you assign a Card to a participant, an **Activity Plan** is created. This happens: - **Manually** - A coach assigns a Card from the participant's profile - **Via Journey** - The participant reaches a Journey state that triggers a Card assignment The Activity Plan defines: | Field | Description | | ------------------- | ----------------------------------------- | | **Participant** | Who receives the card | | **Source Card** | Which Card template it came from | | **Schedule** | When it appears (daily, weekly, one-time) | | **Start/End Dates** | The active period | | **Health Area** | Which section of the app it appears in | ### 3. Activity Plan Details (App Cards) The Activity Plan generates **Activity Plan Details** - these are what the participant actually sees and interacts with in their app. :::warning Important The Activity Plan itself doesn't appear in the app. It's the Activity Plan Details that show up as completable items. ::: | Activity Plan | Activity Plan Details | | -------------------------- | ---------------------------------------- | | One per participant | Many per Activity Plan | | Defines the schedule | Generated by the schedule | | Tracks overall progress | Tracks individual completions | | "Daily at 8am for 4 weeks" | "Mon Jan 1", "Tue Jan 2", "Wed Jan 3"... | For a "Daily for 4 weeks" schedule: - **1** Activity Plan is created - **28** Activity Plan Details are generated (one per day) - Each detail has its own due date, completion status, and responses ## Visual Overview ```mermaid flowchart TB subgraph template["Template (Created Once)"] card["**CARD** Morning Check-In Type: Activity Schedule: Daily"] end subgraph schedule["Schedule (Per Participant)"] plan["**ACTIVITY PLAN** For: John Smith Start: Jan 1 Duration: 4 weeks"] end subgraph app["App Cards (Generated)"] d1["**Jan 1** ✓ Score: 7"] d2["**Jan 2** ✓ Score: 8"] d3["**Jan 3** Pending"] d4["**...**"] end card --> plan plan --> d1 plan --> d2 plan --> d3 plan --> d4 ``` ## Example: Morning Mood Check-In ### Step 1: Coach Creates a Card A coach creates a Card called "Morning Mood Check-In": - Type: Activity - Contains 3 Activity Elements (mood slider, sleep quality, comments) - Default schedule: Daily ### Step 2: Card Gets Assigned John Smith is enrolled in the "Better Sleep" Journey. When he reaches Week 1, the Journey automatically assigns the Card to him. ### Step 3: Activity Plan is Created An Activity Plan is created for John: - Linked to his participant profile - Scheduled for 8am daily (his preferred time) - Runs for 4 weeks ### Step 4: Details are Generated The Activity Plan generates 28 Activity Plan Details - one for each day of the 4-week period. These appear in John's app feed. ### Step 5: Participant Completes Them Each morning, John sees that day's Activity Plan Detail in his app. When he completes it: - His responses are saved to that specific detail - A score is calculated - The parent Activity Plan tracks progress (e.g., "15 of 28 completed") ### Step 6: Coach Reviews Progress The coach views John's Activity Plan to see: - Completion rate - Score trends over time - Individual responses for any specific day ## Card Types | Card Type | How Details are Generated | | ----------------------- | ---------------------------------------------------- | | **Activity Card** | One detail per scheduled occurrence | | **Content Card** | One detail per scheduled occurrence | | **Health Measure Card** | On-demand - participant creates details when logging | --- ## Portal Overview # Intervengine Portal The Portal is the coach-facing web application where you build and manage everything participants experience in the app. Create cards, design automated journeys, manage participants, and monitor progress - all from a single interface. ## Key Concepts - **Cards** - the core unit of content. Cards can be activities that collect participant responses, or content that delivers educational material. Cards are delivered to participants either manually or through journeys. - **Journeys** - automated workflows that deliver cards and move participants through stages based on time, responses, or other signals. Build once, run continuously. - **Participants** - the end-users who receive coaching and engage with cards in the app. Organized with groups and tags for targeted delivery. - **Coaches** - the team members who manage participants, assign content, and monitor progress. Access is controlled via roles and groups. ## Getting Started 1. **Set up your team** - create coach accounts and assign roles 2. **Add participants** - invite the people who will use the app 3. **Build cards** - create the activities and content your program needs 4. **Design journeys** - automate delivery with state-machine workflows 5. **Monitor progress** - track participant engagement and health outcomes :::tip New to Intervengine? Start with these beginner-friendly tutorials: 1. [How to Use the Coach Dashboard](./getting-started/using-the-coach-dashboard) — get oriented in the Portal 2. [How to Add and Manage Participants](./getting-started/managing-participants) — create and organize your participants 3. [How to Set Up a Journey](./getting-started/setting-up-a-journey) — build your first automated workflow ::: ### [Participants](./participants) Manage participant profiles, assign cards and journeys, view their feed, track progress, and communicate through chats. ### [Coaches](./coaches) Set up your coaching team with role-based permissions and group-level access control. ### [Cards](./cards) Create activity cards that collect responses and content cards that educate. Organize cards with health areas and configure scheduling, layout, and response types. ### [Journeys](./journeys) Build visual state-machine workflows that automate card delivery based on time, participant actions, and conditional logic. :::info More Features The Portal also includes [Groups](./more/groups) for access control, [Tags](./more/tags-tag-types) for segmentation, [Campaigns](./more/campaigns) for bulk messaging, [Assets](./more/assets) for shared media, [Configurations](./more/configurations) for organization settings, and [Webhooks](./more/webhooks) for external integrations. ::: --- ## React Native # Intervengine React Native SDK React Native wrapper for the Intervengine Mobile SDK, built with Expo Modules and Kotlin Multiplatform (KMP). ## Overview This SDK provides a React Native interface to the Intervengine platform, enabling mobile apps to: - Authenticate users and manage sessions - Fetch and display embeddable cards - Listen to real-time updates via Server-Sent Events (SSE) - Manage user context and state ## Architecture The SDK consists of three main layers: ### How It Works 1. **TypeScript SDK (`IntervengineSdk.tsx`)**: High-level API that React Native apps use 2. **Native Modules**: Platform-specific bridge code (Swift for iOS, Kotlin for Android) 3. **KMP Shared Library**: Cross-platform business logic written in Kotlin The native modules use **Expo Modules API**, which provides: - Automatic type conversion between native and JavaScript - Promise-based async functions - Event emitters for native → JavaScript communication - No need to write JSI/JNI code manually ## Installation (NPM package not published yet) ```bash npm install intervengine-rn-sdk ``` ## Usage ### Basic Setup ```tsx // Initialize the SDK const sdk = await IntervengineSdk.initialize({ apiUrl: '', apiKey: 'your-api-key', appId: 'your-app-id', appSecret: 'your-app-secret', initialPageSize: 20, enableLogging: true, }); // Start listening for events await sdk.start('participant', 'user-123'); ``` ### Listening to Auth State Changes ```tsx function MyComponent() { const [authState, setAuthState] = useState('loading'); useEffect(() => { if (!sdk) return; // Get current auth state sdk.getCurrentAuthState().then((state) => { setAuthState(state.state); }); // Listen for auth state changes const subscription = sdk.addAuthStateListener((state) => { console.log('Auth state:', state.state); console.log('Access token:', state.accessToken); setAuthState(state.state); }); return () => subscription.remove(); }, [sdk]); return Auth State: {authState}; } ``` ### Fetching Cards ```tsx // Fetch embeddable cards const cards = await sdk.getEmbeddableCards(1, 20); // page, perPage cards.forEach((card) => { console.log('Card:', card.title, card.url); }); ``` ### Listening to Card Updates ```tsx useEffect(() => { if (!sdk) return; const subscription = sdk.addCardsUpdateListener((update) => { console.log('New cards received:', update.newCards); // Refresh your cards list }); return () => subscription.remove(); }, [sdk]); ``` ### Getting User Context ```tsx const context = await sdk.getUserContext(); console.log('User ID:', context.userId); console.log('Access Token:', context.accessToken); ``` ### Complete Example ```tsx function App() { const [sdk, setSdk] = useState(null); const [authState, setAuthState] = useState('loading'); const [cards, setCards] = useState([]); useEffect(() => { // Initialize SDK IntervengineSdk.initialize({ apiUrl: '', apiKey: 'your-key', appId: 'your-app-id', appSecret: 'your-secret', }).then(async (sdkInstance) => { setSdk(sdkInstance); // Start listening for events await sdkInstance.start('participant', 'user-123'); // Fetch initial cards const initialCards = await sdkInstance.getEmbeddableCards(1, 20); setCards(initialCards); }); }, []); useEffect(() => { if (!sdk) return; // Listen for auth state changes const authSub = sdk.addAuthStateListener((state) => { setAuthState(state.state); }); // Listen for new cards const cardsSub = sdk.addCardsUpdateListener(async () => { const updatedCards = await sdk.getEmbeddableCards(1, 20); setCards(updatedCards); }); return () => { authSub.remove(); cardsSub.remove(); }; }, [sdk]); return ( Status: {authState} ( {item.title} {item.descriptionText} )} keyExtractor={(item) => item.id} /> ); } ``` ## API Reference ### `IntervengineSdk.initialize(config)` Initialize the SDK with configuration. **Parameters:** - `config.apiUrl`: API endpoint URL - `config.apiKey`: API key - `config.appId`: Application ID - `config.appSecret`: Application secret - `config.initialPageSize`: Initial page size for cards (default: 10) - `config.enableLogging`: Enable debug logging (default: false) **Returns:** `Promise` ### `sdk.start(userType, userId)` Start listening for Server-Sent Events (SSE). **Parameters:** - `userType`: `'participant'` or `'external'` - `userId`: User identifier **Returns:** `Promise` ### `sdk.stop()` Stop listening for SSE events. **Returns:** `Promise` ### `sdk.signOut()` Sign out and clear SDK state. **Returns:** `Promise` ### `sdk.getEmbeddableCards(page, perPage)` Fetch embeddable cards. **Parameters:** - `page`: Page number (default: 1) - `perPage`: Items per page (default: 10) **Returns:** `Promise` ### `sdk.getUserContext()` Get current user context. **Returns:** `Promise<{ userId: string, accessToken: string }>` ### `sdk.getCurrentAuthState()` Get current authentication state. **Returns:** `Promise` ### `sdk.addAuthStateListener(callback)` Listen for authentication state changes. **Parameters:** - `callback`: `(state: AuthStatePayload) => void` **Returns:** `{ remove: () => void }` ### `sdk.addCardsUpdateListener(callback)` Listen for card updates. **Parameters:** - `callback`: `(update: CardsUpdatePayload) => void` **Returns:** `{ remove: () => void }` ## Types ### `AuthStatePayload` ```tsx type AuthStatePayload = { state: 'authenticated' | 'unauthenticated' | 'loading' | 'error'; accessToken?: string; // Present when state is 'authenticated' error?: string; // Present when state is 'error' }; ``` ### `EmbeddableCard` ```tsx type EmbeddableCard = { id: string; url: string; activityPlanType: string; title: string; descriptionText: string; imageUrl: string; isOneOff: boolean; scheduledAt: string; reportedAt: string; }; ``` ### `CardsUpdatePayload` ```tsx type CardsUpdatePayload = { newCards: EmbeddableCard[]; }; ``` --- ## SDK Overview # SDKs Intervengine provides mobile SDKs that let you embed cards, authentication, and real-time updates directly into your own app. Instead of using the standalone Intervengine App, build a fully custom experience on top of the same backend. ## What the SDK Provides - **Authentication** - sign in users and manage sessions - **Card delivery** - fetch and display cards with full rendering support - **Real-time updates** - listen for new cards and state changes via Server-Sent Events - **User context** - manage participant state and preferences ## Available SDKs ### [React Native](./react-native) Expo Modules wrapper around the Intervengine KMP (Kotlin Multiplatform) core. Supports both iOS and Android from a single codebase. The SDK consists of a TypeScript API layer, native bridge modules, and a shared KMP business logic library. ---