This guide shows you how to manage research studies in JupyterHealth Exchange using either the web-based Console (Method 1) or the REST API (Method 2).
Introduction¶
Core Study Operations¶
Advanced Topics¶
Reference¶
Introduction¶
Prerequisites¶
For Console Access:
Practitioner account with login credentials
Manager or member role in an organization
List of data types you want to collect
List of data sources (devices) participants will use
For REST API Access:
OAuth2 access token
Manager or member role in an organization
HTTP client (curl, Python, JavaScript, etc.)
Choose the method that best fits your workflow.
Study Attributes¶
A study in JupyterHealth Exchange represents a research project or clinical program that:
Belongs to a single organization
Requests specific types of health data (scopes)
Supports specific data sources (devices/apps)
Enrolls patients who consent to share their data
Reference: jupyterhealth-exchange/core/models.py
Create Study¶
Method 1: Using JupyterHealth Exchange Console¶
The Console allows you to create studies through the Organizations page.
Prerequisites¶
Practitioner account in JupyterHealth Exchange
Manager or member role in an organization
Study name and description prepared
Access to JupyterHealth Exchange web portal
Step 1: Navigate to Organizations Page¶
Log in to the Console:
https://your-jhe-instance.com/portal/Click the Organizations tab in the navigation
Step 2: Open Your Organization¶
Find your organization in the table
Click the “eye” icon (View button) to view organization details
A modal opens showing organization information
Step 3: Create New Study¶
In the organization details modal, scroll down to the “Studies” section
Click the “+” icon (Add Study button) next to “Studies”
The Studies modal closes and a “Create Study” modal opens
Fill in the study form:
Name (required): e.g., “Diabetes Management Study”
Description (required): Detailed study description
Icon URL (optional): URL to study icon/logo
As you type, the icon preview updates in real-time
Organization Name: Auto-filled (read-only)
Click “Create” button
The study is created and the modal closes
Step 4: Configure Study (Optional)¶
After creating the study, you can immediately configure it:
Navigate to the Studies tab
Select your organization from the dropdown
Find your new study in the table
Click the “eye” icon to view study details
Add data sources and scope requests (see Configure Data Collection)
Note: New studies are always created from the Organizations page. The Studies tab is for viewing, editing, and deleting existing studies.
Method 2: Using REST API¶
The REST API enables programmatic study creation, ideal for bulk imports and automated workflows.
Prerequisites¶
OAuth2 access token (practitioner authentication)
Manager or member role in an organization
HTTP client (curl, Postman, or programming language)
Step 1: Authenticate¶
Obtain an access token as a practitioner. See Using the REST API for the full authentication flow.
ACCESS_TOKEN="your-access-token-here"Step 2: Identify Your Organization¶
List organizations you belong to:
curl https://your-jhe-instance.com/api/v1/organizations \
-H "Authorization: Bearer $ACCESS_TOKEN"Response:
[
{
"id": 1,
"name": "Example Clinic",
"type": "prov",
"practitioners": [
{
"id": 1,
"email": "you@example.com",
"role": "manager"
}
]
}
]Note your organization ID (e.g., 1) and verify your role is manager or member.
Reference: jupyterhealth-exchange/core/permissions.py
Step 3: Create the Study¶
curl -X POST https://your-jhe-instance.com/api/v1/studies \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Diabetes Management Study",
"description": "Monitoring blood glucose levels in Type 2 diabetes patients to optimize treatment plans.",
"organization": 1,
"iconUrl": "https://example.com/study-icon.png"
}'Fields:
name(required): Study name (e.g., “Diabetes Management Study”)description(required): Detailed study descriptionorganization(required): Organization IDiconUrl(optional): URL to study icon/logo
Response:
{
"id": 10001,
"name": "Diabetes Management Study",
"description": "Monitoring blood glucose levels...",
"organization": 1,
"iconUrl": "https://example.com/study-icon.png",
"patients": [],
"scopeRequests": [],
"dataSources": []
}Note the study ID (e.g., 10001) for subsequent steps.
Reference: jupyterhealth-exchange/core/views/study.py
Configure Data Collection¶
After creating a study, you need to configure what types of data to collect and which devices patients can use.
Method 1: Using JupyterHealth Exchange Console¶
The Console provides an interactive interface for managing study data sources and scope requests.
Prerequisites¶
Study must already be created
Manager or member role in the study’s organization
Know which data types and devices you want to support
Step 1: Navigate to Study Details¶
Log in to the Console and click the Studies tab
Select your Organization from the dropdown
Find your study in the table
Click the “eye” icon (View button) to open study details modal
Step 2: Add Data Sources (Devices)¶
In the study details modal:
Scroll down to the “Data Sources” section
Click the “+” icon next to “Data Sources”
A dropdown appears with available data sources:
Select a data source (e.g., “iHealth”, “Dexcom”, “CareX”)
Click the “Add” button (green)
The data source appears in the list
Repeat for additional data sources
To remove a data source:
Click the trash icon next to the data source name
Confirmation is instant
Step 3: Add Scope Requests (Data Types)¶
In the same study details modal:
Scroll down to the “Scope Requests” section
Click the “+” icon next to “Scope Requests”
A dropdown appears with available data types:
Select a scope (e.g., “Blood Glucose”, “Blood Pressure”, “Heart Rate”)
Click the “Add” button (green)
The scope request appears in the list
Repeat for additional data types
To remove a scope request:
Click the trash icon next to the scope name
Warning: Removing scope requests prevents collection of that data type going forward
Console Tips:
You can add/remove data sources and scopes at any time
Changes take effect immediately
Adding new scope requests requires patients to provide additional consent
The modal updates in real-time as you make changes
Method 2: Using REST API¶
The REST API enables programmatic configuration of study data collection.
Prerequisites¶
OAuth2 access token
Study ID from study creation
Manager or member role in the organization
Step 1: Add Data Types (Scope Requests)¶
Specify which types of health data the study will collect.
List Available Data Types:
curl https://your-jhe-instance.com/api/v1/data_sources \
-H "Authorization: Bearer $ACCESS_TOKEN"Look for supportedScopes in the response to see available data types:
{
"supportedScopes": [
{
"id": 1,
"codingSystem": "https://w3id.org/openmhealth",
"codingCode": "omh:blood-glucose:4.0",
"text": "Blood Glucose"
},
{
"id": 2,
"codingCode": "omh:blood-pressure:4.0",
"text": "Blood Pressure"
}
]
}Add Scope Requests to Study:
# Add blood glucose
curl -X POST https://your-jhe-instance.com/api/v1/studies/10001/scope_requests \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scope_code_id": 1
}'
# Add blood pressure
curl -X POST https://your-jhe-instance.com/api/v1/studies/10001/scope_requests \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scope_code_id": 2
}'
# Add heart rate
curl -X POST https://your-jhe-instance.com/api/v1/studies/10001/scope_requests \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scope_code_id": 4
}'Note: Each scope request represents one data type. Add as many as needed for your study.
Reference: jupyterhealth-exchange/core/views/study.py
Verify Scope Requests:
curl "https://your-jhe-instance.com/api/v1/studies?organization_id=1" \
-H "Authorization: Bearer $ACCESS_TOKEN"Response includes scopeRequests:
{
"id": 10001,
"name": "Diabetes Management Study",
"scopeRequests": [
{
"id": 1,
"codingCode": "omh:blood-glucose:4.0",
"text": "Blood Glucose"
},
{
"id": 2,
"codingCode": "omh:blood-pressure:4.0",
"text": "Blood Pressure"
}
]
}Step 2: Add Data Sources (Devices)¶
Specify which devices/apps participants can use.
List Available Data Sources:
curl https://your-jhe-instance.com/api/v1/data_sources \
-H "Authorization: Bearer $ACCESS_TOKEN"Response:
[
{
"id": 70001,
"name": "iHealth",
"type": "personal_device"
},
{
"id": 70002,
"name": "Dexcom",
"type": "personal_device"
},
{
"id": 70003,
"name": "CareX",
"type": "personal_device"
}
]Add Data Sources to Study:
# Add iHealth
curl -X POST https://your-jhe-instance.com/api/v1/studies/10001/data_sources \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data_source_id": 70001
}'
# Add Dexcom
curl -X POST https://your-jhe-instance.com/api/v1/studies/10001/data_sources \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data_source_id": 70002
}'Reference: jupyterhealth-exchange/core/views/study.py
Verify Data Sources:
curl "https://your-jhe-instance.com/api/v1/studies?organization_id=1" \
-H "Authorization: Bearer $ACCESS_TOKEN"Response includes dataSources:
{
"id": 10001,
"name": "Diabetes Management Study",
"dataSources": [
{
"id": 70001,
"name": "iHealth",
"type": "personal_device"
},
{
"id": 70002,
"name": "Dexcom",
"type": "personal_device"
}
]
}View Study¶
You can view study details using either the Console or REST API.
Method 1: Using JupyterHealth Exchange Console¶
Navigate to the Studies tab in the Console
Select your Organization from the dropdown
Find the study in the table
Click the “eye” icon (View button)
A modal opens showing:
Study ID
Name and description
Icon URL (with live preview)
Organization name
Data Sources: List of supported devices
Scope Requests: List of data types being collected
Method 2: Using REST API¶
curl "https://your-jhe-instance.com/api/v1/studies?organization_id=1" \
-H "Authorization: Bearer $ACCESS_TOKEN"Response includes all studies for the organization with full details.
Reference: jupyterhealth-exchange/core/views/study.py
Update Study Details¶
You can update study name, description, and icon URL using either the Console or REST API.
Method 1: Using JupyterHealth Exchange Console¶
Navigate to the Studies tab
Select your Organization from the dropdown
Find the study in the table
Click the “pencil” icon (Edit/Update button)
In the modal, update the fields:
Name: Study name
Description: Study description
Icon URL: URL to study icon
The icon preview updates in real-time as you type
Click “Update” button
Study information is updated
Note: You cannot change the organization of an existing study. To manage data sources and scope requests, use the View mode (eye icon) instead of Update mode.
Method 2: Using REST API¶
curl -X PATCH https://your-jhe-instance.com/api/v1/studies/10001 \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "Updated study description with additional details."
}'Updatable Fields:
namedescriptioniconUrl
Reference: jupyterhealth-exchange/core/views/study.py
Enroll Patients in Study¶
Patient enrollment in studies is covered in detail in the Patient Management guide, which includes step-by-step instructions for both Console and REST API methods.
Monitor Study Progress¶
After enrolling patients in a study, you can monitor their consent status and data collection progress.
Method 1: Using JupyterHealth Exchange Console¶
View Patient Consent Status¶
Navigate to the Patients tab in the Console
Select your Organization from the dropdown
Select the Study from the dropdown
Find a patient in the table
Click the “eye” icon (View button) to open patient details
Scroll down to view:
Studies Pending Response: Studies awaiting patient’s consent decision
Studies Responded To: Studies with consent status
Checkmark icon (✓) = Patient consented to this data type
X icon = Patient declined this data type
View Study Data Collection¶
Navigate to the Observations tab in the Console
Select your Organization from the dropdown at the top
Select your Study from the dropdown
The observations table displays all data collected for the study with these columns:
ID: Observation ID number
Scope: Data type (e.g., “Blood pressure”, “Heart Rate”)
Patient: Patient name (Last, First format)
Transaction Time: When the data was uploaded (timestamp)
Data: Preview of the JSON data (Open mHealth format)
Use the pagination controls:
Navigate between pages using the page number input
Adjust items per page (20, 50, 100, etc.) from the dropdown
The Data column displays the full OMH (Open mHealth) JSON structure for each observation including:
body: The actual health measurements (e.g., systolic/diastolic blood pressure values, heart rate)header: Metadata including UUID, schema ID, modality, source creation time, and data source reference
Console Tips:
The JSON data is displayed directly in the table for easy viewing
Each observation shows both the header (metadata) and body (actual measurements)
Use the Organization and Study dropdowns to switch between different studies
For programmatic access, filtering, or exporting data, use the REST API (see below)
Method 2: Using REST API¶
Check Consent Status¶
curl https://your-jhe-instance.com/api/v1/patients/10001/consents \
-H "Authorization: Bearer $ACCESS_TOKEN"Response:
{
"patient": {
"id": 10001,
"nameFamily": "Smith",
"nameGiven": "John"
},
"consolidatedConsentedScopes": [
{
"codingCode": "omh:blood-glucose:4.0",
"text": "Blood Glucose"
}
],
"studiesPendingConsent": [],
"studies": [
{
"id": 10001,
"name": "Diabetes Management Study",
"scopeConsents": [
{
"code": {
"codingCode": "omh:blood-glucose:4.0"
},
"consented": true,
"consentedTime": "2024-05-01T10:30:00Z"
},
{
"code": {
"codingCode": "omh:blood-pressure:4.0"
},
"consented": true,
"consentedTime": "2024-05-01T10:30:00Z"
}
]
}
]
}Reference: jupyterhealth-exchange/core/views/patient.py
Check Data Collection¶
curl "https://your-jhe-instance.com/api/v1/observations?organization_id=1&study_id=10001&patient_id=10001" \
-H "Authorization: Bearer $ACCESS_TOKEN"Response:
{
"count": 150,
"results": [
{
"id": 1,
"patientNameDisplay": "Smith, John",
"codingCode": "omh:blood-glucose:4.0",
"created": "2024-05-02T08:30:00Z"
}
]
}Delete Study¶
You can delete studies using either the Console or REST API.
Method 1: Using JupyterHealth Exchange Console¶
Navigate to the Studies tab
Select your Organization from the dropdown
Find the study in the table
Click the “trash” icon (Delete button)
A confirmation modal appears: “Are you sure you want to delete this entire record?”
Click “Delete” button to confirm
The study is permanently deleted
Warning: This permanently deletes:
The study
All patient enrollments
All consent records
(Optional) Associated observation data
Consider archiving inactive studies instead of deleting them.
Method 2: Using REST API¶
curl -X DELETE https://your-jhe-instance.com/api/v1/studies/10001 \
-H "Authorization: Bearer $ACCESS_TOKEN"Warning: This permanently deletes:
The study
All patient enrollments
All consent records
(Optional) Associated observation data
Consider archiving inactive studies instead of deleting them.
Reference: jupyterhealth-exchange/core/views/study.py
Common Issues¶
Permission Denied Creating Study¶
Error: 403 Forbidden
Cause: User doesn’t have study.manage_for_organization permission.
Solution: Verify your role in the organization:
curl https://your-jhe-instance.com/api/v1/organizations \
-H "Authorization: Bearer $ACCESS_TOKEN"Your role must be manager or member, not viewer.
Reference: jupyterhealth-exchange/core/permissions.py
Cannot Add Patient to Study¶
Error: “Patient and study must share the same organization”
Cause: Patient belongs to different organization than study.
Solution: Patients can only be added to studies in their organization. Either:
Add patient to study’s organization first
Create study in patient’s organization
Reference: jupyterhealth-exchange/core/views/study.py
Scope Request Not Appearing in Consent¶
Cause: Data source doesn’t support the requested scope.
Solution: Verify data source supports the scope:
python manage.py shell
from core.models import DataSource, CodeableConcept
ds = DataSource.objects.get(id=70001)
scope = CodeableConcept.objects.get(id=1)
# Check if supported
if ds.supported_scopes.filter(id=scope.id).exists():
print("Supported")
else:
print("Not supported - create DataSourceSupportedScope link")Best Practices¶
Study Design¶
Clear naming: Use descriptive study names (e.g., “Type 2 Diabetes Glucose Monitoring 2024”)
Detailed descriptions: Include objectives, procedures, expected duration
Minimal data collection: Only request data types you actually need
Device flexibility: Support multiple data sources when possible
Data Collection Planning¶
Start small: Begin with one or two data types, expand if needed
Test with pilot: Enroll a few patients first to validate workflow
Monitor compliance: Regularly check that patients are uploading data
Communicate clearly: Ensure patients understand what data is collected and why
Consent Management¶
Informed consent: Provide detailed study information in invitation
Re-consent for changes: When adding new data types, notify patients
Respect withdrawal: Make it easy for patients to revoke consent
Document process: Keep records of when patients consented
Security¶
Role-based access: Only grant manager/member roles to authorized researchers
Audit access: Regularly review who has access to study data
Data retention: Define and enforce data retention policies
De-identification: Consider de-identifying data for analysis
Complete Study Setup Example¶
# 1. Authenticate
ACCESS_TOKEN="your-access-token"
BASE_URL="https://your-jhe-instance.com"
# 2. Create study
STUDY=$(curl -X POST "$BASE_URL/api/v1/studies" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Hypertension Management Study",
"description": "Remote blood pressure monitoring for hypertensive patients.",
"organization": 1
}')
STUDY_ID=$(echo $STUDY | jq -r '.id')
echo "Created study ID: $STUDY_ID"
# 3. Add scope requests (blood pressure, heart rate)
curl -X POST "$BASE_URL/api/v1/studies/$STUDY_ID/scope_requests" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"scope_code_id": 2}'
curl -X POST "$BASE_URL/api/v1/studies/$STUDY_ID/scope_requests" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"scope_code_id": 4}'
# 4. Add data sources (iHealth, Omron)
curl -X POST "$BASE_URL/api/v1/studies/$STUDY_ID/data_sources" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"data_source_id": 70001}'
curl -X POST "$BASE_URL/api/v1/studies/$STUDY_ID/data_sources" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"data_source_id": 70005}'
# 5. Enroll patients
curl -X POST "$BASE_URL/api/v1/studies/$STUDY_ID/patients" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"patient_ids": [10001, 10002, 10003]}'
# 6. Generate invitation links
for PATIENT_ID in 10001 10002 10003; do
curl "$BASE_URL/api/v1/patients/$PATIENT_ID/invitation_link?send_email=true" \
-H "Authorization: Bearer $ACCESS_TOKEN"
done
echo "Study setup complete!"Choosing Between Console and REST API¶
When to Use JupyterHealth Exchange Console¶
✅ Best for:
Creating individual studies interactively
Configuring data sources and scope requests visually
Viewing study details and monitoring progress
Updating study information (name, description, icon)
Practitioners who prefer web-based interfaces
Day-to-day study management tasks
Quick testing and prototyping
Training and demonstrations
❌ Not ideal for:
Bulk study creation
Automated study setup workflows
Integration with external systems
Scheduled or triggered operations
Key Features:
Create studies from Organizations page
Visual icon preview with real-time updates
Add/remove data sources and scopes with dropdowns
View patient enrollment and consent status
Delete studies with confirmation
No programming required
When to Use REST API¶
✅ Best for:
Bulk study creation from templates
Automated study configuration workflows
Integration with research management systems
Building custom UIs or applications
Scheduled or triggered study setup
Programmatic data collection monitoring
Continuous integration/deployment pipelines
Complex multi-step study configurations
❌ Not ideal for:
One-off study creation
Users unfamiliar with APIs or command line
Quick interactive study management
Exploratory study viewing
Key Features:
Batch operations (create multiple studies at once)
Scriptable workflows (Python, JavaScript, shell)
Advanced filtering and querying
Custom business logic
FHIR R5 API compliance
Hybrid Approach (Recommended)¶
Most organizations use both methods for different purposes:
Typical Workflow:
Initial Setup (Console):
Create organization via web portal
Create first study interactively
Configure data sources and scopes
Test with a few patients
Bulk Configuration (REST API):
Create multiple studies from templates
Configure data collection programmatically
Enroll patients in bulk
Daily Operations (Console):
Monitor patient consent status
View study progress and data collection
Add/remove data sources as needed
Generate reports and insights
Analysis and Reporting (REST API):
Export observation data for analysis
Generate automated reports
Integrate with data warehouses