Patient Portal
Build with AI Agent
Patient Portal Backend

Patient Portal App Backend Template
Deliver lab results, manage treatment plans, and enable secure doctor–patient messaging

A production-ready patient portal backend on Back4app with secure lab result delivery, treatment plan management, clinician messaging, appointment linking, and centralized audit logs. Includes ER diagram, data dictionary, JSON schema, API playground, and an AI Agent prompt for rapid bootstrap.

Key Takeaways

Ship a patient-facing backend with secure access controls, lab versioning, treatment plan histories, threaded messaging, and audit trails so your product team can focus on UX and compliance.

  1. Patient-first data modelKeep patient identity, lab results, treatments, and messages modeled separately but linked for clear provenance and authorization.
  2. Secure messagingThreaded, attachment-friendly messages between patients and providers with clear read receipts and retention controls.
  3. Versioned lab resultsStore lab results with provenance and version metadata so updated reports and addenda are tracked.
  4. Treatment plan lifecycleManage treatment plan drafts, approvals by providers, patient acknowledgement, and version history.
  5. Compliance-friendly loggingCentralized AuditLog class records sensitive events for review, monitoring, and compliance.

What Is the Patient Portal App Backend Template?

Back4app is a backend-as-a-service (BaaS) for rapid delivery. The Patient Portal App Backend Template is a pre-built schema for patient profiles, lab results, treatment plans, secure messaging, appointments, and audit logs. Connect your preferred frontend (React, Flutter, Next.js, and more) and ship faster.

Best for:

Patient portalsTelehealth messagingSecure lab result deliveryTreatment plan managementClinician–patient communicationTeams building HIPAA-aware prototypes

Overview

Patient portals require strong data boundaries, auditable changes, and reliable delivery of sensitive items like lab results and treatment plans.

This template defines PatientProfile, LabResult, TreatmentPlan, Message, ProviderProfile, Appointment, and AuditLog with ownership and role-based rules so teams can implement patient portals quickly and securely.

Core Patient Portal Features

Every technology card in this hub uses the same patient portal backend schema with PatientProfile, LabResult, TreatmentPlan, Message, ProviderProfile, Appointment, and AuditLog.

Patient profile & authentication

PatientProfile stores identity, contact details, and preferences with a pointer to the authenticated User.

Versioned lab results

LabResult stores test type, raw result payload, reportedAt, version, and provider provenance.

Treatment plan lifecycle

TreatmentPlan stores plan content, provider approver, status (draft, active, completed), and effective window.

Secure doctor–patient messaging

Message supports threads, attachments, sender/recipient pointers, and delivery/read status.

Appointment linking

Appointment links patient, provider, scheduled time, and status for visit context.

Centralized audit logs

AuditLog captures actor identity, action type, entity context, and payload metadata for compliance.

Why Build Your Patient Portal App Backend with Back4app?

Back4app handles the backend fundamentals—security, persistence, APIs, and realtime—so you can focus on patient experience, privacy workflows, and clinical integration.

  • Secure delivery of clinical data: Built-in auth and ACL/CLP patterns let you control exactly which users can see each lab result, treatment plan, or message.
  • Audit and provenance: AuditLog captures who viewed, published, or modified sensitive records so you can support compliance and debugging.
  • Messaging and notifications: Threaded messages, attachments, and optional live updates make clinician–patient conversations smooth and timely.

Deploy a secure patient portal backend quickly and iterate on clinical workflows instead of backend plumbing.

Core Benefits

A patient portal backend that emphasizes privacy, provenance, and rapid delivery.

Accelerated patient experiences

Ship lab result views, treatment plan delivery, and secure messaging faster by reusing a validated backend contract.

Strong data provenance

Version lab results and treatment plans so clinical changes are auditable and traceable.

Fine-grained permissions

Protect sensitive items with ACL/CLP and role checks so only permitted clinicians and patients can access them.

Integrated messaging

Threaded messages with attachments and optional real-time updates improve clinician–patient collaboration.

Compliance-ready logging

Centralized AuditLog supports reviews, incident investigation, and compliance reporting.

AI-assisted bootstrap

Jumpstart development with a curated AI Agent prompt that scaffolds schema, ACLs, and basic integration code.

Ready to build a secure patient portal?

Let the Back4app AI Agent scaffold your patient portal backend and generate patient profiles, lab results, treatment plans, messaging, and audit logs from one prompt.

Free to start — 50 AI Agent prompts/month, no credit card required

Technical Stack

Everything included in this Patient Portal backend template.

Frontend
13+ technologies
Backend
Back4app
Database
MongoDB
Auth
Built-in auth + sessions
API
REST and GraphQL
Realtime
Live Queries

ER Diagram

Entity relationship model for the Patient Portal backend schema.

View diagram source
Mermaid
erDiagram
    PatientProfile ||--o{ LabResult : "has"
    PatientProfile ||--o{ TreatmentPlan : "receives"
    PatientProfile ||--o{ Message : "context for"
    PatientProfile ||--o{ Appointment : "scheduled in"
    _User ||--o{ Message : "sends/receives"
    _User ||--o{ TreatmentPlan : "authors"
    _User ||--o{ Appointment : "provides"

    PatientProfile {
        String objectId PK
        Pointer user FK
        String medicalRecordNumber
        String displayName
        Date dateOfBirth
        String primaryClinic
        Boolean isActive
        Date createdAt
        Date updatedAt
    }

    LabResult {
        String objectId PK
        Pointer patient FK
        Pointer orderedBy FK
        String testCode
        String testName
        String resultValue
        String units
        String referenceRange
        String status
        Date publishedAt
        Array attachments
        Date createdAt
        Date updatedAt
    }

    TreatmentPlan {
        String objectId PK
        Pointer patient FK
        Pointer createdBy FK
        String summary
        String details
        String status
        Date startDate
        Date endDate
        Date createdAt
        Date updatedAt
    }

    Message {
        String objectId PK
        String conversationId
        Pointer from FK
        Pointer to FK
        Pointer patient FK
        String body
        Array attachments
        Boolean isRead
        Date sentAt
        Date createdAt
        Date updatedAt
    }

    Appointment {
        String objectId PK
        Pointer patient FK
        Pointer provider FK
        Date startAt
        Date endAt
        String location
        String status
        String reason
        Date createdAt
        Date updatedAt
    }

    AuditLog {
        String objectId PK
        Pointer actor FK
        String entityType
        String entityId
        String action
        String summary
        Object metadata
        Date createdAt
        Date updatedAt
    }

Integration Flow

Typical runtime flow for authentication, lab result delivery, treatment plan updates, and messaging.

View diagram source
Mermaid
sequenceDiagram
  participant Patient
  participant App as Patient Portal App
  participant Clinician
  participant Back4app as Back4app Cloud

  Patient->>App: Sign in with email or SSO
  App->>Back4app: POST /login (credentials/SSO token)
  Back4app-->>App: Return Session Token + Patient context

  Patient->>App: Open Dashboard (profile & recent labs)
  App->>Back4app: GET /classes/PatientProfile?where={"user":Pointer("_User", "u123")}
  Back4app-->>App: PatientProfile object
  App->>Back4app: GET /classes/LabResult?where={"patient":Pointer("PatientProfile","p123")}&order=-publishedAt
  Back4app-->>App: List of LabResult (latest first)

  Patient->>App: View active Treatment Plan
  App->>Back4app: GET /classes/TreatmentPlan?where={"patient":Pointer("PatientProfile","p123"),"status":"active"}
  Back4app-->>App: TreatmentPlan object

  Patient->>App: Send secure message to clinician
  App->>Back4app: POST /classes/Message (conversationId, body, to: Pointer(_User, clinicianId))
  Back4app-->>App: Message objectId

  Back4app-->>App: LiveQuery -> new Message or LabResult update
  App-->>Patient: Real-time notification (new message / result available)

  Clinician->>Back4app: Update LabResult (finalize)
  Back4app-->>App: LiveQuery event -> App fetches updated LabResult
  App-->>Patient: Alert: "New lab result available"

Data Dictionary

Full field-level reference for every class in the Patient Portal schema.

FieldTypeDescriptionRequired
objectIdStringAuto-generated unique identifierAuto
userPointer<_User>Linked Back4app user account
medicalRecordNumberStringUnique MRN for the patient
displayNameStringPatient full name shown in UI
dateOfBirthDatePatient date of birth
primaryClinicStringPrimary clinic or provider group
isActiveBooleanActive portal access flag
createdAtDateAuto-generated creation timestampAuto
updatedAtDateAuto-generated last-update timestampAuto

9 fields in PatientProfile

Security and Permissions

How ACL, CLP, and encryption strategies secure lab results, treatment plans, messages, and audit logs.

Role-based access and ownership

Apply ACLs so patients can see their own records and providers see assigned patient data; CLPs prevent unauthorized class operations.

Encrypted payloads and attachments

Store sensitive blobs (lab attachments, PDFs) behind signed URLs and use storage-level encryption for at-rest protection.

Append-only audit trails

Write AuditLog entries from server-side Cloud Code to ensure users cannot tamper with historical compliance records.

Schema (JSON)

Raw JSON schema definition ready to copy into Back4app or use as implementation reference.

JSON
{
  "classes": [
    {
      "className": "PatientProfile",
      "fields": {
        "objectId": {
          "type": "String",
          "required": false
        },
        "user": {
          "type": "Pointer",
          "required": true,
          "targetClass": "_User"
        },
        "medicalRecordNumber": {
          "type": "String",
          "required": true
        },
        "displayName": {
          "type": "String",
          "required": true
        },
        "dateOfBirth": {
          "type": "Date",
          "required": false
        },
        "primaryClinic": {
          "type": "String",
          "required": false
        },
        "isActive": {
          "type": "Boolean",
          "required": true
        },
        "createdAt": {
          "type": "Date",
          "required": false
        },
        "updatedAt": {
          "type": "Date",
          "required": false
        }
      }
    },
    {
      "className": "LabResult",
      "fields": {
        "objectId": {
          "type": "String",
          "required": false
        },
        "patient": {
          "type": "Pointer",
          "required": true,
          "targetClass": "PatientProfile"
        },
        "orderedBy": {
          "type": "Pointer",
          "required": false,
          "targetClass": "_User"
        },
        "testCode": {
          "type": "String",
          "required": false
        },
        "testName": {
          "type": "String",
          "required": true
        },
        "resultValue": {
          "type": "String",
          "required": false
        },
        "units": {
          "type": "String",
          "required": false
        },
        "referenceRange": {
          "type": "String",
          "required": false
        },
        "status": {
          "type": "String",
          "required": true
        },
        "publishedAt": {
          "type": "Date",
          "required": false
        },
        "attachments": {
          "type": "Array",
          "required": false
        },
        "createdAt": {
          "type": "Date",
          "required": false
        },
        "updatedAt": {
          "type": "Date",
          "required": false
        }
      }
    },
    {
      "className": "TreatmentPlan",
      "fields": {
        "objectId": {
          "type": "String",
          "required": false
        },
        "patient": {
          "type": "Pointer",
          "required": true,
          "targetClass": "PatientProfile"
        },
        "createdBy": {
          "type": "Pointer",
          "required": true,
          "targetClass": "_User"
        },
        "summary": {
          "type": "String",
          "required": true
        },
        "details": {
          "type": "String",
          "required": false
        },
        "status": {
          "type": "String",
          "required": true
        },
        "startDate": {
          "type": "Date",
          "required": false
        },
        "endDate": {
          "type": "Date",
          "required": false
        },
        "createdAt": {
          "type": "Date",
          "required": false
        },
        "updatedAt": {
          "type": "Date",
          "required": false
        }
      }
    },
    {
      "className": "Message",
      "fields": {
        "objectId": {
          "type": "String",
          "required": false
        },
        "conversationId": {
          "type": "String",
          "required": true
        },
        "from": {
          "type": "Pointer",
          "required": true,
          "targetClass": "_User"
        },
        "to": {
          "type": "Pointer",
          "required": true,
          "targetClass": "_User"
        },
        "patient": {
          "type": "Pointer",
          "required": true,
          "targetClass": "PatientProfile"
        },
        "body": {
          "type": "String",
          "required": true
        },
        "attachments": {
          "type": "Array",
          "required": false
        },
        "isRead": {
          "type": "Boolean",
          "required": true
        },
        "sentAt": {
          "type": "Date",
          "required": false
        },
        "createdAt": {
          "type": "Date",
          "required": false
        },
        "updatedAt": {
          "type": "Date",
          "required": false
        }
      }
    },
    {
      "className": "Appointment",
      "fields": {
        "objectId": {
          "type": "String",
          "required": false
        },
        "patient": {
          "type": "Pointer",
          "required": true,
          "targetClass": "PatientProfile"
        },
        "provider": {
          "type": "Pointer",
          "required": true,
          "targetClass": "_User"
        },
        "startAt": {
          "type": "Date",
          "required": true
        },
        "endAt": {
          "type": "Date",
          "required": true
        },
        "location": {
          "type": "String",
          "required": false
        },
        "status": {
          "type": "String",
          "required": true
        },
        "reason": {
          "type": "String",
          "required": false
        },
        "createdAt": {
          "type": "Date",
          "required": false
        },
        "updatedAt": {
          "type": "Date",
          "required": false
        }
      }
    },
    {
      "className": "AuditLog",
      "fields": {
        "objectId": {
          "type": "String",
          "required": false
        },
        "actor": {
          "type": "Pointer",
          "required": true,
          "targetClass": "_User"
        },
        "entityType": {
          "type": "String",
          "required": true
        },
        "entityId": {
          "type": "String",
          "required": true
        },
        "action": {
          "type": "String",
          "required": true
        },
        "summary": {
          "type": "String",
          "required": true
        },
        "metadata": {
          "type": "Object",
          "required": false
        },
        "createdAt": {
          "type": "Date",
          "required": false
        },
        "updatedAt": {
          "type": "Date",
          "required": false
        }
      }
    }
  ]
}

Build with AI Agent

Use the Back4app AI Agent to generate a Patient Portal app from this template, including backend schema, ACLs, and starter frontend integration.

Back4app AI Agent
Ready to build
Create a Patient Portal backend on Back4app with this exact schema and behavior.

Schema:
1. PatientProfile: user (Pointer to User, required), fullName (String, required), dob (Date, optional), contact (Object), medicalRecordNumber (String, required, unique); objectId, createdAt, updatedAt.
2. ProviderProfile: user (Pointer to User, required), specialty (String), clinic (String), contact (Object); objectId, createdAt, updatedAt.
3. LabResult: patient (Pointer to PatientProfile, required), provider (Pointer to ProviderProfile, required), reportType (String), resultData (Object), reportedAt (Date, required), version (Number, default 1), attachments (Array of File), visibility (String: patient-only, provider-only, shared); objectId, createdAt, updatedAt.
4. TreatmentPlan: patient (Pointer to PatientProfile, required), provider (Pointer to ProviderProfile, required), summary (String), details (Object), status (String: draft, active, completed), effectiveFrom (Date), effectiveTo (Date), version (Number); objectId, createdAt, updatedAt.
5. Message: sender (Pointer to User, required), recipient (Pointer to User, required), threadId (String, required), body (String), attachments (Array of File), status (String: sent, delivered, read), sentAt (Date); objectId, createdAt, updatedAt.
6. Appointment: patient (Pointer to PatientProfile, required), provider (Pointer to ProviderProfile, required), scheduledAt (Date, required), status (String: scheduled, canceled, completed), location (String); objectId, createdAt, updatedAt.
7. AuditLog: actor (Pointer to User, required), action (String, required), entityType (String, required), entityId (String, required), payload (Object, optional), createdAt (Date); objectId, createdAt, updatedAt.

Security:
- Enforce ACLs so patients only read their LabResult and TreatmentPlan records. Providers see assigned patients. Use Cloud Code for sensitive transitions and to write AuditLog entries server-side. Protect attachments with signed URLs and storage encryption.

Auth:
- Support sign-up for patients and providers; role assignment; secure login and session management.

Behavior:
- Patient logs in, fetches latest LabResult versions and TreatmentPlans, sends messages to provider threads, and receives notifications. Providers publish lab results and treatment plans; system writes AuditLog entries for publish actions.

Deliver:
- Back4app app with schema, CLPs, ACLs, Cloud Code hooks for publishing and audit logging, and starter frontend integration for patient and provider views.

Press the button below to open the Agent with this template prompt pre-filled.

This is the base prompt without a technology suffix. You can adapt the generated frontend stack afterward.

Deploy in minutes50 free prompts / monthNo credit card required

API Playground

Try REST and GraphQL endpoints against the Patient Portal schema. Responses use mock data and do not require a Back4app account.

common.loadingPlayground

Uses the same schema as this template.

Choose Your Technology

Expand each card for integration steps, state patterns, data model examples, and offline notes.

Flutter Patient Portal Backend

React Patient Portal Backend

React Native Patient Portal Backend

Next.js Patient Portal Backend

JavaScript Patient Portal Backend

Android Patient Portal Backend

iOS Patient Portal Backend

Vue Patient Portal Backend

Angular Patient Portal Backend

GraphQL Patient Portal Backend

REST API Patient Portal Backend

PHP Patient Portal Backend

.NET Patient Portal Backend

What You Get with Every Technology

Every stack uses the same Patient Portal backend schema and API contracts.

Unified patient data structure

Easily manage and access all patient information in one schema.

Secure messaging for patient portal

Facilitate safe communication between patients and healthcare providers.

Real-time appointment scheduling

Allow patients to book and manage appointments seamlessly.

Comprehensive lab results tracking

Enable patients to view and track their lab results securely.

Access control for sensitive data

Ensure that only authorized personnel can view patient records.

REST/GraphQL APIs for patient portal

Integrate easily with various frontends using flexible APIs.

Patient Portal Framework Comparison

Compare setup speed, SDK style, and AI support across all supported technologies.

FrameworkSetup TimePatient Portal BenefitSDK TypeAI Support
Rapid (5 min) setupSingle codebase for patient portal on mobile and web.Typed SDKFull
~5 minFast web dashboard for patient portal.Typed SDKFull
About 5 minCross-platform mobile app for patient portal.Typed SDKFull
Under 5 minutesServer-rendered web app for patient portal.Typed SDKFull
~3 minLightweight web integration for patient portal.Typed SDKFull
Rapid (5 min) setupNative Android app for patient portal.Typed SDKFull
~5 minNative iOS app for patient portal.Typed SDKFull
About 5 minReactive web UI for patient portal.Typed SDKFull
Under 5 minutesEnterprise web app for patient portal.Typed SDKFull
Quick (2 min) setupFlexible GraphQL API for patient portal.GraphQL APIFull
~2 minREST API integration for patient portal.REST APIFull
Under 5 minServer-side PHP backend for patient portal.REST APIFull
About 5 min.NET backend for patient portal.Typed SDKFull

Setup time reflects expected duration from project bootstrap to first patient login and lab result query using this template schema.

Frequently Asked Questions

Common questions about building a Patient Portal backend with this template.

What is a Patient Portal backend?
What does the Patient Portal template include?
Why use Back4app for a patient portal?
How do I fetch the latest lab result and its provider in one query?
How do I mark a message as read?
Can React Native cache treatment plans for offline use?
How do I prevent unauthorized sharing of lab PDFs?
What is the best way to surface appointment context on mobile?
How does the audit logging flow work end-to-end?
How do I support patient acknowledgment of a treatment plan?

Trusted by developers worldwide

Join teams shipping secure patient portals faster with Back4app templates

G2 Users Love Us Badge

Ready to Build Your Patient Portal App?

Start your patient portal project in minutes. No credit card required.

Choose Technology