How to Use EHR APIs ?

Learn to integrate EHR systems via FHIR and proprietary APIs. Handle patient data, authentication, and compliance requirements for healthcare applications.

Ashley Innocent

Ashley Innocent

24 March 2026

How to Use EHR APIs ?

TL;DR

EHR APIs access patient health records stored in systems like Epic, Cerner, and Athenahealth. Most modern EHRs support FHIR (Fast Healthcare Interoperability Resources), a standard format for healthcare data. Authentication uses OAuth 2.0 with SMART on FHIR extensions. For testing, use Apidog to validate FHIR resources, test against sandboxes, and ensure your integration handles patient data correctly before connecting to production systems.

Introduction

Electronic Health Records contain everything about patient care: diagnoses, medications, lab results, allergies, and treatment plans. Hospitals, clinics, and health systems store this data in EHR platforms like Epic, Cerner, and Athenahealth.

Building healthcare applications means connecting to these systems. You can’t ask hospitals to export CSV files. You need APIs. But healthcare APIs are different from typical web APIs. They handle protected health information (PHI) and must comply with regulations like HIPAA in the US.

The good news: most EHR vendors now support FHIR, a standard API format. The challenging news: authentication, authorization, and data mapping remain complex.

If you’re building healthcare integrations, Apidog helps you test FHIR resources, validate data structures, and ensure your application handles patient data correctly. You can test against public sandboxes before working with real hospital systems.

Test FHIR APIs with Apidog - free

By the end of this guide, you’ll be able to:

Understanding FHIR

FHIR (Fast Healthcare Interoperability Resources) is the modern standard for healthcare APIs. It defines:

Base URL structure

https://ehr.example.com/fhir/r4/{resource-type}/{id}

Example:

GET https://ehr.example.com/fhir/r4/Patient/123

FHIR version

Most EHRs use FHIR R4 (Release 4). Some older systems use DSTU2. This guide covers R4.

Resource types

Resource Purpose
Patient Demographics and administrative data
Practitioner Healthcare providers
Organization Hospitals, clinics
Observation Lab results, vital signs
MedicationRequest Prescriptions
Condition Diagnoses, problems
Encounter Visits, admissions
DocumentReference Clinical documents
AllergyIntolerance Allergies and adverse reactions

FHIR resource structure

Patient resource example

{
  "resourceType": "Patient",
  "id": "123",
  "active": true,
  "name": [
    {
      "use": "official",
      "family": "Smith",
      "given": ["John", "Michael"]
    }
  ],
  "gender": "male",
  "birthDate": "1985-03-15",
  "address": [
    {
      "use": "home",
      "line": ["123 Main St"],
      "city": "Boston",
      "state": "MA",
      "postalCode": "02101",
      "country": "USA"
    }
  ],
  "telecom": [
    {
      "system": "phone",
      "value": "555-123-4567",
      "use": "home"
    },
    {
      "system": "email",
      "value": "john.smith@example.com"
    }
  ],
  "identifier": [
    {
      "system": "http://hospital.example.org/mrn",
      "value": "MRN-123456"
    }
  ]
}

Observation resource example

{
  "resourceType": "Observation",
  "id": "obs-123",
  "status": "final",
  "category": [
    {
      "coding": [
        {
          "system": "http://terminology.hl7.org/CodeSystem/observation-category",
          "code": "vital-signs",
          "display": "Vital Signs"
        }
      ]
    }
  ],
  "code": {
    "coding": [
      {
        "system": "http://loinc.org",
        "code": "8480-6",
        "display": "Systolic blood pressure"
      }
    ]
  },
  "subject": {
    "reference": "Patient/123"
  },
  "effectiveDateTime": "2026-03-24T09:30:00Z",
  "valueQuantity": {
    "value": 120,
    "unit": "mmHg",
    "system": "http://unitsofmeasure.org",
    "code": "mm[Hg]"
  }
}

Authentication with SMART on FHIR

SMART on FHIR extends OAuth 2.0 for healthcare. It handles patient context and EHR-specific scopes.

OAuth flow for patient access

Step 1: Get authorization URL

GET https://ehr.example.com/fhir/r4/.well-known/smart-configuration

Response includes:

{
  "authorization_endpoint": "https://ehr.example.com/oauth2/authorize",
  "token_endpoint": "https://ehr.example.com/oauth2/token",
  "scopes_supported": [
    "patient/*.read",
    "patient/*.write",
    "user/*.read",
    "launch/patient"
  ]
}

Step 2: Redirect user to authorize

https://ehr.example.com/oauth2/authorize?
  response_type=code&
  client_id=YOUR_CLIENT_ID&
  redirect_uri=https://yourapp.com/callback&
  scope=patient/*.read&
  state=random_state_value

Step 3: Exchange code for token

curl -X POST "https://ehr.example.com/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://yourapp.com/callback" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "patient/*.read",
  "patient": "123"
}

The patient field gives you the patient ID context.

SMART scopes

Scope Access
patient/*.read Read all patient data
patient/Patient.read Read patient demographics only
patient/Observation.read Read observations only
user/*.read Read all data for authorized user
launch/patient EHR launches your app with patient context

Querying patient data

Get patient demographics

curl -X GET "https://ehr.example.com/fhir/r4/Patient/123" \
  -H "Authorization: Bearer ACCESS_TOKEN"

Search for observations

curl -X GET "https://ehr.example.com/fhir/r4/Observation?patient=123&category=vital-signs" \
  -H "Authorization: Bearer ACCESS_TOKEN"

Response is a Bundle:

{
  "resourceType": "Bundle",
  "type": "searchset",
  "total": 5,
  "entry": [
    {
      "resource": { ... Observation resource ... }
    }
  ]
}

Common search parameters

# Lab results by date range
GET /Observation?patient=123&category=laboratory&date=gt2026-01-01

# Specific LOINC code
GET /Observation?patient=123&code=http://loinc.org|8480-6

# Medications
GET /MedicationRequest?patient=123&status=active

# Conditions (diagnoses)
GET /Condition?patient=123&clinical-status=active

# Encounters
GET /Encounter?patient=123&type=AMB

Pagination

Large result sets paginate:

GET /Observation?patient=123&_count=20

Response includes links:

{
  "link": [
    {
      "relation": "next",
      "url": "https://ehr.example.com/fhir/r4/Observation?patient=123&_count=20&page=2"
    }
  ]
}

Creating and updating resources

Create an observation

curl -X POST "https://ehr.example.com/fhir/r4/Observation" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "resourceType": "Observation",
    "status": "final",
    "code": {
      "coding": [{
        "system": "http://loinc.org",
        "code": "8480-6",
        "display": "Systolic blood pressure"
      }]
    },
    "subject": {
      "reference": "Patient/123"
    },
    "effectiveDateTime": "2026-03-24T09:30:00Z",
    "valueQuantity": {
      "value": 118,
      "unit": "mmHg",
      "system": "http://unitsofmeasure.org",
      "code": "mm[Hg]"
    }
  }'

Update a patient

curl -X PUT "https://ehr.example.com/fhir/r4/Patient/123" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "resourceType": "Patient",
    "id": "123",
    "name": [{
      "family": "Smith",
      "given": ["John", "Michael"]
    }],
    "telecom": [{
      "system": "phone",
      "value": "555-999-8888",
      "use": "home"
    }]
  }'

EHR vendor specifics

Epic

Epic’s FHIR API is available at most large hospitals.

Epic requires app registration in their app marketplace for production access.

Cerner

Cerner (Oracle Health) uses standard FHIR with some extensions.

Athenahealth

Athenahealth provides FHIR and legacy APIs.

Testing with Apidog

Healthcare APIs require careful testing. Patient data is sensitive.

1. Use public sandboxes

Test against public FHIR sandboxes:

# HAPI FHIR (open source)
https://hapi.fhir.org/baseR4

# SMART Health IT sandbox
https://launch.smarthealthit.org

2. Validate FHIR resources

pm.test('Resource is valid Patient', () => {
  const response = pm.response.json()
  pm.expect(response.resourceType).to.eql('Patient')
  pm.expect(response.id).to.exist
  pm.expect(response.name).to.be.an('array')
})

pm.test('Observation has required fields', () => {
  const resource = pm.response.json()
  pm.expect(resource.status).to.exist
  pm.expect(resource.code).to.exist
  pm.expect(resource.subject).to.exist
})

3. Test authentication flow

Save SMART configuration as environment:

AUTHORIZATION_ENDPOINT: https://ehr.example.com/oauth2/authorize
TOKEN_ENDPOINT: https://ehr.example.com/oauth2/token
CLIENT_ID: your_client_id
CLIENT_SECRET: your_client_secret
SCOPE: patient/*.read

Test FHIR APIs with Apidog - free

Compliance considerations

HIPAA

In the US, healthcare applications must comply with HIPAA. This affects:

SMART on FHIR security

Data minimization

Only request scopes you need:

Common errors and fixes

401 Unauthorized

Cause: Token expired or invalid.

Fix: Refresh the token using the refresh token from initial authorization.

403 Forbidden

Cause: Scope doesn’t include requested resource.

Fix: Check your scopes. If you need more access, request additional scopes during authorization.

404 Not Found

Cause: Patient or resource doesn’t exist.

Fix: Verify the resource ID. Check that the patient is accessible with your current token’s patient context.

422 Unprocessable Entity

Cause: FHIR resource validation failed.

Fix: Check required fields and terminologies:

{
  "resourceType": "OperationOutcome",
  "issue": [{
    "severity": "error",
    "code": "required",
    "details": {
      "text": "Observation.status is required"
    }
  }]
}

Alternatives and comparisons

Feature Epic Cerner Athenahealth OpenEMR
FHIR R4 Partial
SMART on FHIR No
Sandbox access Limited Self-host
API documentation Excellent Good Good Basic
Market share Large hospitals Health systems Small practices Open source

Epic and Cerner dominate large healthcare systems. Athenahealth serves smaller practices. OpenEMR is open source but has limited API support.

Real-world use cases

Patient portal. A health system builds a patient portal that pulls data from Epic. Patients view lab results, medications, and upcoming appointments. The portal uses FHIR APIs with SMART on FHIR authentication.

Clinical research. A pharmaceutical company needs to identify eligible patients for clinical trials. They query FHIR APIs across multiple hospital systems to find patients matching criteria, with proper consent management.

Remote monitoring. A telehealth company integrates patient-reported vitals with EHR systems. Observations are created via FHIR API and immediately visible to clinicians in Epic.

Wrapping up

Here’s what you’ve learned:

Your next steps:

  1. Explore the HAPI FHIR public sandbox
  2. Understand FHIR resource types for your use case
  3. Register for EHR developer programs
  4. Test with Apidog using mock patient data
  5. Implement HIPAA-compliant data handling

Test FHIR APIs with Apidog - free

button

FAQ

What’s the difference between FHIR and HL7 v2?HL7 v2 is an older messaging standard used in hospital interfaces. FHIR is a modern REST API standard. Most new integrations use FHIR, but HL7 v2 is still common in legacy systems.

Do I need a BAA to use EHR APIs?Yes, if you’re handling PHI. Business Associate Agreements are required between covered entities and business associates. Check with the EHR vendor’s compliance team.

How do I get access to Epic’s FHIR API?Register in Epic’s App Orchard marketplace. For sandbox testing, use their public sandbox. Production access requires hospital approval.

What’s a patient context?SMART on FHIR tokens include a patient ID. Your API calls are limited to that patient’s data. This ensures apps can only access data the patient authorized.

Can I write data to EHRs?Yes, but with limitations. Most EHRs allow creating observations and updating patient demographics. Writing diagnoses or medications usually requires clinical decision support approval.

How do I handle terminology codes?FHIR uses standard terminologies:

Use these systems when creating resources.

What about international healthcare?FHIR is global. Each country may have implementation guides. The US uses US Core profiles. Check your region’s specifications.

Explore more

How to Use Brevo APIs for SMS Marketing ?

How to Use Brevo APIs for SMS Marketing ?

Learn to integrate Brevo (formerly Sendinblue) APIs for email campaigns, SMS marketing, and transactional messages. Set up API keys, manage contacts, and track results.

24 March 2026

Shadow API: What It Is, Risks & How to Prevent It

Shadow API: What It Is, Risks & How to Prevent It

A shadow API is an undocumented or unmanaged API endpoint, posing major security and compliance risks. Learn how shadow APIs emerge, their dangers, and practical steps—using tools like Apidog—to detect and prevent them in your API landscape.

24 March 2026

How to Manage Multiple API Integrations Efficiently

How to Manage Multiple API Integrations Efficiently

Learn how to manage multiple API integrations efficiently with best practices, real-world examples, and tools like Apidog for seamless, scalable workflows.

24 March 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs