Skip to article frontmatterSkip to article content

Patient Management

This guide shows you how to manage patients in JupyterHealth Exchange using either the web-based Console (Method 1) or the REST API (Method 2).

Introduction

Core Patient Operations

Advanced Topics

Reference


Introduction

Prerequisites

Note: The JupyterHealth Exchange Console is a web-based Single Page Application (SPA) that provides a user-friendly interface for managing patients, studies, and health data.

For Console Access:

For REST API Access:

Choose the method that best fits your workflow.

Understanding Patient Attributes

In JupyterHealth Exchange, patients:

Reference: jupyterhealth-exchange/core/models.py


Add New Patient

Method 1: Using JupyterHealth Exchange Console

The JupyterHealth Exchange Console provides a web-based interface for practitioners to manage patients interactively.

Prerequisites

Step 1: Access the Console

  1. Navigate to the JupyterHealth Exchange web portal:

    https://your-jhe-instance.com/portal/
  2. Log in with your practitioner credentials

    • Enter your email address

    • Enter your password

    • You’ll be authenticated via OAuth2/OIDC

    • After successful login, you’ll be redirected to the Organizations page

Step 2: Navigate to Patients

  1. In the console navigation, click the Patients tab

  2. At the top left, select your Organization from the dropdown

  3. Optionally, filter by Study using the second dropdown (or select “All Studies”)

You’ll see a table of existing patients in the selected organization/study.

Step 3: Create New Patient

  1. Click the “Add Patient...” button (green button, top left area)

  2. A modal dialog opens titled “Create Patient”

  3. Option 1: Check if patient already exists

    • Enter the patient’s email in the “Patient E-mail” field

    • Click “Lookup” button

    • If patient exists in another organization:

      • Patient details will appear

      • You can add them to your organization (skip to Step 5)

    • If patient doesn’t exist:

      • Continue with patient creation below

  4. Create new patient by filling in the form:

    • E-mail (required): john.smith@example.com

      • This will be the patient’s login email

      • Automatically filled if you used lookup

    • External Identifier: Medical record number or other ID (e.g., MRN-12345)

    • Family Name (required): Smith

    • Given Name (required): John

    • DOB (required): 1980-01-01 (YYYY-MM-DD format)

    • Cell: 555-1234 (optional phone number)

  5. Click “Create” button

  6. The patient is created and added to the selected organization

  7. The modal closes and the patient appears in the patient table

Step 4: View Patient Details

After creating the patient, you can view their full details:

  1. Find the patient in the table

  2. Click the “eye” icon (View/Read button) in the leftmost column

  3. A modal opens showing:

    • Patient ID and demographic information

    • Organizations: List of organizations this patient belongs to

    • Studies Pending Response: Studies awaiting patient consent

    • Studies Responded To: Studies with consent status (checkmarks for consented)

This is a key step - the patient needs an invitation link to connect their mobile app and start uploading health data.

  1. With the patient details modal open (from Step 4):

  2. Scroll down to the “Generate Invitation Link” section

  3. Configure email option:

    • Check “Send link by email” to automatically email the link to the patient

    • Or uncheck it to manually copy and send the link yourself

  4. Click the “Generate Invitation Link” button (green)

  5. The invitation link appears in the text area.

  6. Send Link to Patient Option A: Email sent automatically

    • If “Send link by email” was checked, the patient receives an email with the invitation link

    • Email template includes instructions for installing the CommonHealth app

    Option B: Copy link manually

    • Click “Copy to Clipboard” button

    • Send the link to the patient via:

      • Email

      • SMS

      • Patient portal

      • Printed QR code

      • In-person instruction

Link Components:

Step 6: Enroll Patient in Study (Optional)

To enroll one or more patients in a study:

  1. Navigate to the Patients section

  2. Select the organization from the “Organization” dropdown at the top

  3. Check the checkbox(es) next to the patient(s) you want to enroll

  4. Click the “Add Patient(s) to Study...” button (blue button)

  5. You’ll be taken to the Studies page where you can select which study to add the patients to

  6. Find the target study and click to add the selected patients

  7. All selected patients are enrolled in the study

Notes:

Step 7: Verify Patient Setup

After completing the above steps, verify the patient is properly configured:

  1. Click the “eye” icon to view patient details

  2. Check that:

    • ✅ Patient belongs to correct organization(s)

    • ✅ Patient is enrolled in desired study (appears in “Studies Pending Response”)

    • ✅ Invitation link has been generated and sent

  3. Patient should receive the invitation email (if email option was selected)

  4. Patient can now install the CommonHealth app and authenticate

Console Tips

Method 2: Using REST API

The REST API enables programmatic patient management, ideal for bulk imports and automated workflows.

Prerequisites

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: Create Patient via API

curl -X POST https://your-jhe-instance.com/api/v1/patients \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "telecomEmail": "john.smith@example.com",
    "nameFamily": "Smith",
    "nameGiven": "John",
    "birthDate": "1980-01-01",
    "telecomPhone": "555-1234",
    "organizationId": 1
  }'

Fields:

Response:

{
  "id": 10001,
  "jheUserId": 5,
  "identifier": null,
  "nameFamily": "Smith",
  "nameGiven": "John",
  "birthDate": "1980-01-01",
  "telecomPhone": "555-1234",
  "telecomEmail": "john.smith@example.com",
  "organizationId": 1
}

Note the patient ID (e.g., 10001) for subsequent operations.

Reference: jupyterhealth-exchange/core/views/patient.py

Create an invitation link for the patient to connect their mobile app:

curl https://your-jhe-instance.com/api/v1/patients/10001/invitation_link \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Response:

{
  "invitationLink": "https://play.google.com/store/apps/details?id=org.thecommonsproject.android.phr.dev&referrer=cloud_sharing=jhe.yourdomain.com|LhS05iR1rOnpS4JWfP6GeVUIhaRcRh"
}

Link Components:

Reference: jupyterhealth-exchange/core/models.py and jupyterhealth-exchange/core/views/patient.py

Step 4: Send Invitation to Patient

Option 1: Automatic Email
curl "https://your-jhe-instance.com/api/v1/patients/10001/invitation_link?send_email=true" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

This sends an email to the patient’s registered email address with the invitation link.

Reference: jupyterhealth-exchange/core/views/patient.py

Option 2: Manual Distribution

Send the invitation link via:

Example email template:

Subject: Join [Study Name] - Connect Your Health Data

Dear John,

You've been invited to participate in our health study. To get started:

1. Click this link on your mobile device: [INVITATION_LINK]
2. Install the CommonHealth app (if not already installed)
3. Follow the instructions to connect your health devices
4. Review and provide consent for data sharing

If you have questions, contact us at research@example.com.

Thank you,
[Your Organization Name]

Add Existing Patient to Organization

If a patient already exists in the Exchange but not in your organization, you can add them using either method.

Method 1: Using JupyterHealth Exchange Console

  1. Navigate to Patients tab

  2. Click “Add Patient...” button

  3. In the modal, enter the patient’s email in the “Patient E-mail” field

  4. Click “Lookup” button

  5. If the patient exists in another organization:

    • Patient details will appear

    • An alert shows: “This Patient already exists. Click the Update button below to add this Patient to the Organization”

  6. Click “Update” button

  7. Patient is added to your organization

Method 2: Using REST API

Step 1: Search for Patient

curl "https://your-jhe-instance.com/api/v1/patients/global_lookup?email=john.smith@example.com" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Response:

[
  {
    "id": 10001,
    "nameFamily": "Smith",
    "nameGiven": "John",
    "birthDate": "1980-01-01",
    "telecomEmail": "john.smith@example.com"
  }
]

Note: This searches across all organizations in the Exchange.

Reference: jupyterhealth-exchange/core/views/patient.py

Step 2: Add to Your Organization

curl -X PATCH "https://your-jhe-instance.com/api/v1/patients/10001/global_add_organization?organization_id=1" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Response:

{
  "id": 10001,
  "nameFamily": "Smith",
  "nameGiven": "John",
  "organizationId": 1
}

Reference: jupyterhealth-exchange/core/views/patient.py


Enroll Patient in Study

You can enroll patients in studies using either the Console or REST API.

Method 1: Using JupyterHealth Exchange Console

  1. Navigate to Patients tab

  2. Select your Organization from the dropdown

  3. Select the Study from the dropdown (not “All Studies”)

  4. Check the checkbox(es) next to the patient(s) you want to enroll

  5. Click “Add Patient(s) to Study...” button (blue button)

  6. Confirm the enrollment

  7. Patient(s) are enrolled in the selected study

Bulk enrollment: You can select multiple patients and enroll them all at once.

Note: Patient and study must be in the same organization.

Method 2: Using REST API

Step 1: List Available Studies

curl "https://your-jhe-instance.com/api/v1/studies?organization_id=1" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Response:

{
  "results": [
    {
      "id": 10001,
      "name": "Diabetes Management Study",
      "description": "Monitoring blood glucose levels",
      "scopeRequests": [
        {
          "codingCode": "omh:blood-glucose:4.0",
          "text": "Blood Glucose"
        }
      ]
    }
  ]
}

Step 2: Enroll Patient

curl -X POST https://your-jhe-instance.com/api/v1/studies/10001/patients \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "patient_ids": [10001]
  }'

Note: Patient and study must be in the same organization.

Reference: jupyterhealth-exchange/core/views/study.py

Step 3: Verify Enrollment

curl "https://your-jhe-instance.com/api/v1/patients?organization_id=1&study_id=10001" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Response should include the newly enrolled patient.


Patient consent can be viewed through the Console. To grant or revoke consent on behalf of a patient, use the REST API.

  1. Navigate to Patients tab

  2. Find the patient and click the “eye” icon (View button)

  3. In the patient details modal, scroll down to view:

    • Studies Pending Response: Studies awaiting patient’s consent decision

      • Shows which data types (scopes) are pending

    • Studies Responded To: Studies with consent decisions

      • Checkmark icon (✓) = Patient consented to this data type

      • X icon = Patient declined this data type

Note: Consent status in the Console is read-only. Patients typically grant consent via their mobile app. To grant or revoke consent on behalf of a patient (with appropriate authorization), use the REST API.

curl https://your-jhe-instance.com/api/v1/patients/10001/consents \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Response:

{
  "patient": {
    "id": 10001,
    "nameFamily": "Smith",
    "nameGiven": "John",
    "birthDate": "1980-01-01"
  },
  "consolidatedConsentedScopes": [
    {
      "id": 1,
      "codingCode": "omh:blood-glucose:4.0",
      "text": "Blood Glucose"
    }
  ],
  "studiesPendingConsent": [
    {
      "id": 10002,
      "name": "Cardiac Health Study",
      "pendingScopeConsents": [
        {
          "code": {
            "codingCode": "omh:blood-pressure:4.0",
            "text": "Blood Pressure"
          },
          "consented": null,
          "consentedTime": null
        }
      ]
    }
  ],
  "studies": [
    {
      "id": 10001,
      "name": "Diabetes Management Study",
      "scopeConsents": [
        {
          "code": {
            "codingCode": "omh:blood-glucose:4.0"
          },
          "consented": true,
          "consentedTime": "2024-05-01T10:30:00Z"
        }
      ]
    }
  ]
}

Key Fields:

Reference: jupyterhealth-exchange/core/views/patient.py

Practitioners with member or manager roles can grant consent on behalf of patients using the REST API.

Important Notes:

Prerequisites:

curl -X POST https://your-jhe-instance.com/api/v1/patients/10001/consents \
  -H "Authorization: Bearer $PRACTITIONER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "studyScopeConsents": [{
      "studyId": 10001,
      "scopeConsents": [{
        "codingSystem": "https://w3id.org/openmhealth",
        "codingCode": "omh:blood-glucose:4.0",
        "consented": true
      }]
    }]
  }'

Reference: jupyterhealth-exchange/core/views/patient.py and authorization check at lines 198-200

Practitioners with member or manager roles can revoke consent on behalf of patients using the REST API.

Important Notes:

To revoke consent, set consented: false:

curl -X POST https://your-jhe-instance.com/api/v1/patients/10001/consents \
  -H "Authorization: Bearer $PRACTITIONER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "studyScopeConsents": [{
      "studyId": 10001,
      "scopeConsents": [{
        "codingSystem": "https://w3id.org/openmhealth",
        "codingCode": "omh:blood-glucose:4.0",
        "consented": false
      }]
    }]
  }'

Effect: Patient’s existing data remains in the Exchange, but no new data of this type will be collected from the patient’s devices.


Update Patient Information

You can update patient demographics using either the Console or REST API.

Method 1: Using JupyterHealth Exchange Console

  1. Navigate to Patients tab

  2. Find the patient in the table

  3. Click the “pencil” icon (Edit/Update button)

  4. In the modal, update the demographic fields:

    • External Identifier

    • Family Name

    • Given Name

    • DOB

    • Cell phone

  5. Click “Update” button

  6. Patient information is updated

Note: Email address is read-only in the Console and cannot be changed through the UI. Changing email requires REST API access.

Method 2: Using REST API

curl -X PATCH https://your-jhe-instance.com/api/v1/patients/10001 \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "telecomPhone": "555-5678",
    "nameGiven": "Jonathan"
  }'

Updatable Fields:

Note: Email address is used for authentication. Changing it requires patient to re-authenticate.


Remove Patient from Study

You can remove patients from studies using either the Console or REST API.

Method 1: Using JupyterHealth Exchange Console

  1. Navigate to Patients tab

  2. Select the Organization from the dropdown

  3. Select the Study from the dropdown (the study you want to remove patients from)

  4. Check the checkbox(es) next to the patient(s) you want to remove

  5. Click “Remove Patient(s) from Study” button (orange/warning button)

  6. Confirm the removal

  7. Patient(s) are removed from the study

Bulk removal: You can select multiple patients and remove them all at once.

Method 2: Using REST API

curl -X DELETE https://your-jhe-instance.com/api/v1/studies/10001/patients \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "patient_ids": [10001]
  }'

Effect:

Reference: jupyterhealth-exchange/core/views/study.py


Remove Patient from Organization

You can remove patients from organizations using either the Console or REST API.

Method 1: Using JupyterHealth Exchange Console

  1. Navigate to Patients tab

  2. Select the Organization from the dropdown

  3. Ensure “All Studies” is selected (to see all patients in organization)

  4. Find the patient in the table

  5. Click the “trash” icon (Delete button)

  6. A confirmation modal appears: “Are you sure you want to delete this entire record?”

  7. Click “Delete” button to confirm

  8. Patient is removed from the selected organization

Warning:

Method 2: Using REST API

curl -X DELETE "https://your-jhe-instance.com/api/v1/patients/10001?organization_id=1" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Effect:

Reference: jupyterhealth-exchange/core/views/patient.py


View Patient’s Data

You can view patient data using either the Console or REST API.

Method 1: Using JupyterHealth Exchange Console

  1. Navigate to Observations tab in the Console

  2. Select the Organization from the dropdown

  3. Select the Study from the dropdown (optional)

  4. Use filters to narrow the data:

    • Patient: Select specific patient or view all

    • Data Type: Filter by codeable concept (e.g., blood-glucose, steps)

    • Date Range: Filter by time period

  5. The observations table displays:

    • Observation ID

    • Patient name

    • Data type (codeable concept)

    • Data source (device/wearable)

    • Status

    • Created date/time

  6. Click on an observation row to view full details including OMH data payload

  7. Use pagination controls to navigate large datasets

Tips:

Method 2: Using REST API

List Observations

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": 250,
  "next": "...",
  "previous": null,
  "results": [
    {
      "id": 1,
      "subjectPatient": 10001,
      "patientNameDisplay": "Smith, John",
      "codeableConcept": 1,
      "codingCode": "omh:blood-glucose:4.0",
      "dataSource": 70001,
      "status": "final",
      "created": "2024-05-02T08:30:00Z"
    }
  ]
}

Reference: jupyterhealth-exchange/core/models.py

Export Patient Data (FHIR)

curl "https://your-jhe-instance.com/fhir/r5/Observation?patient=10001&patient._has:Group:member:_id=10001" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Returns FHIR Bundle with all authorized observations for the patient.

Reference: See “Fetching and Exporting Data” guide for details.


Bulk Patient Import

For importing multiple patients at once, use the REST API with a script:

import requests
import csv

BASE_URL = "https://your-jhe-instance.com"
ACCESS_TOKEN = "your-access-token"
ORGANIZATION_ID = 1


def create_patient(email, family_name, given_name, birth_date, phone=None):
    response = requests.post(
        f"{BASE_URL}/api/v1/patients",
        headers={
            "Authorization": f"Bearer {ACCESS_TOKEN}",
            "Content-Type": "application/json",
        },
        json={
            "telecomEmail": email,
            "nameFamily": family_name,
            "nameGiven": given_name,
            "birthDate": birth_date,
            "telecomPhone": phone,
            "organizationId": ORGANIZATION_ID,
        },
    )

    if response.status_code == 201:
        patient = response.json()
        print(f"Created patient {patient['id']}: {given_name} {family_name}")
        return patient
    else:
        print(f"Error creating {given_name} {family_name}: {response.text}")
        return None


def generate_invitation(patient_id):
    response = requests.get(
        f"{BASE_URL}/api/v1/patients/{patient_id}/invitation_link?send_email=true",
        headers={"Authorization": f"Bearer {ACCESS_TOKEN}"},
    )

    if response.status_code == 200:
        data = response.json()
        print(f"  Invitation sent: {data['invitationLink']}")
    else:
        print(f"  Error generating invitation: {response.text}")


# Read from CSV
with open("patients.csv", "r") as f:
    reader = csv.DictReader(f)
    for row in reader:
        patient = create_patient(
            email=row["email"],
            family_name=row["last_name"],
            given_name=row["first_name"],
            birth_date=row["dob"],
            phone=row.get("phone"),
        )

        if patient:
            generate_invitation(patient["id"])

print("Bulk import complete!")

CSV Format (patients.csv):

email,last_name,first_name,dob,phone
john.smith@example.com,Smith,John,1980-01-01,555-1234
jane.doe@example.com,Doe,Jane,1975-05-15,555-5678

Common Issues

Patient Already Exists

Error: “User with this email already exists”

Cause: A patient with this email already has an account.

Solution: Use global lookup to find the patient and add them to your organization:

# Find patient
curl "https://your-jhe-instance.com/api/v1/patients/global_lookup?email=john.smith@example.com" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Add to organization
curl -X PATCH "https://your-jhe-instance.com/api/v1/patients/10001/global_add_organization?organization_id=1" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Reference: jupyterhealth-exchange/core/views/patient.py

Cannot Enroll Patient in Study

Error: “Patient and study must share the same organization”

Cause: Patient is in organization A but study is in organization B.

Solution: Ensure both patient and study are in the same organization:

# Check patient's organization
curl https://your-jhe-instance.com/api/v1/patients/10001 \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Check study's organization
curl "https://your-jhe-instance.com/api/v1/studies?organization_id=1" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Reference: jupyterhealth-exchange/core/views/study.py

Issue: Patient clicks link but app doesn’t open or connection fails.

Common Causes:

  1. Link expired: Authorization codes expire after 2 weeks

    • Solution: Generate new invitation link

  2. Wrong app package: Link targets wrong environment (dev vs prod)

    • Solution: Verify CH_INVITATION_LINK_PREFIX in .env

  3. App not installed: Patient doesn’t have CommonHealth app

    • Solution: Link should redirect to app store first

  4. Network issue: Can’t reach Exchange server

    • Solution: Verify Exchange URL is accessible

Reference: jupyterhealth-exchange/jhe/settings.py and jupyterhealth-exchange/core/models.py

Permission Denied

Error: 403 Forbidden when creating or viewing patient

Cause: User doesn’t have patient.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 and view permission check at jupyterhealth-exchange/core/views/patient.py


Best Practices

Patient Onboarding

  1. Verify information: Double-check email address and demographics before creating patient

  2. Immediate invitation: Generate and send invitation link right after creating patient

  3. Follow-up: Contact patients who don’t connect within 48 hours

  4. Test first: Create a test patient account to verify the onboarding flow

  1. Clear communication: Explain what data will be collected and why

  2. Study-specific consent: Patients consent per study, not globally

  3. Allow withdrawal: Make it easy for patients to revoke consent

  4. Document consent: Keep records of when patients consented

Data Privacy

  1. Minimum necessary: Only collect data types required for your study

  2. Role-based access: Ensure only authorized practitioners can view patient data

  3. Audit access: Regularly review who has accessed patient records

  4. De-identify for analysis: Use de-identified datasets when possible

Communication

  1. Multi-channel: Provide invitation links via multiple channels (email, SMS, portal)

  2. Technical support: Have a help desk for patients with connection issues

  3. Status updates: Regularly check which patients are actively uploading data

  4. Engagement: Reach out to patients who stop uploading data


Example: Complete Patient Onboarding via REST API

# Set variables
BASE_URL="https://your-jhe-instance.com"
ACCESS_TOKEN="your-access-token"
ORG_ID=1
STUDY_ID=10001

# 1. Create patient
PATIENT=$(curl -X POST "$BASE_URL/api/v1/patients" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "telecomEmail": "john.smith@example.com",
    "nameFamily": "Smith",
    "nameGiven": "John",
    "birthDate": "1980-01-01",
    "telecomPhone": "555-1234",
    "organizationId": '$ORG_ID'
  }')

PATIENT_ID=$(echo $PATIENT | jq -r '.id')
echo "Created patient ID: $PATIENT_ID"

# 2. Enroll in study
curl -X POST "$BASE_URL/api/v1/studies/$STUDY_ID/patients" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"patient_ids": ['$PATIENT_ID']}'

echo "Enrolled in study $STUDY_ID"

# 3. Generate and send invitation
INVITATION=$(curl "$BASE_URL/api/v1/patients/$PATIENT_ID/invitation_link?send_email=true" \
  -H "Authorization: Bearer $ACCESS_TOKEN")

echo "Invitation sent:"
echo $INVITATION | jq -r '.invitationLink'

# 4. Verify patient status
curl "$BASE_URL/api/v1/patients/$PATIENT_ID/consents" \
  -H "Authorization: Bearer $ACCESS_TOKEN" | jq

echo "Patient onboarding complete!"

Choosing Between JupyterHealth Exchange Console and REST API

When to Use JupyterHealth Exchange Console

Best for:

Not ideal for:

Key Features:

When to Use REST API

Best for:

Not ideal for:

Key Features:

Most organizations use both methods for different purposes:

Typical Workflow:

  1. Initial Setup (Console):

    • Create organizations via web portal

    • Create studies with scope requests

    • Configure data sources

    • Add initial test patients

  2. Bulk Import (REST API):

    • Import existing patients from EHR system

    • Enroll patients in studies programmatically

    • Generate and send invitation links in batch

  3. Daily Operations (Console):

    • Add new patients one-by-one as they enroll

    • View consent status and follow up with patients

    • Monitor data collection in real-time

    • Generate invitation links for individual patients

    • Troubleshoot patient issues

  4. Analysis and Reporting (REST API):

    • Export observation data for analysis

    • Generate reports via scripts

    • Integrate with data warehouses

    • Automated quality checks