Mira EMR patient and population APIs
Developer: Mira Technologies, Inc. Product: Mira EMR, version 1.0.
This page covers three API capabilities:
- (g)(7) application access, patient selection
- (g)(9) application access, all data request (C-CDA)
- (g)(10) standardized API for patient and population services (FHIR R4, US Core 6.1.0, SMART App Launch 2.0.0, Bulk Data 1.0.1)
Hosts: Mira EMR is https://miraemr.com. The FHIR server for the development stage is https://fhir-dev.mirahealth.care (its CapabilityStatement and SMART configuration); the production FHIR server's address is published before production opens. Each practice's own FHIR base URL is published in the service base URL Bundle (§2).
1. Terms of use
-
Who may use the APIs. Patients and their authorized representatives may use any app they choose to reach their own records. Healthcare organizations that use Mira EMR (the "API Information Sources") may use the APIs and may authorize other apps to reach their population data.
-
No fees.
- Mira charges no fee to patients or to app developers to register an app or to call these APIs.
- Any fee Mira charges a customer for deploying the APIs is stated in our mandatory disclosures, per §170.404(a)(3).
-
Use. Apps must:
- use the APIs as documented here
- keep their credentials confidential
- request only the scopes they need
- not attempt to reach data their user is not authorized to see
Mira does not require app developers to sign a business associate agreement to serve a patient's chosen app. Mira does not vet patient-chosen apps for security beyond the registration steps in §3.
-
Rights. Mira grants the rights needed to develop, test, market and distribute apps that use these APIs. Those rights do not depend on fees, exclusivity, non-compete terms, or reciprocal data sharing (§170.404(a)(4)).
-
Changes. Mira gives registered developers and customers advance notice of changes to the APIs, and reasonable time to update, except where a security issue requires faster action.
-
Support. support@mirahealth.care. We answer within 2 business days.
2. Service base URLs (§170.404(b)(2))
Every customer organization whose FHIR API is live is published, free of charge and with no sign-in, as a FHIR R4 Bundle (type: collection) of Organization and Endpoint resources:
- Bundle:
GEThttps://miraemr.com/api/v1/api-access/service-base-urls. Response200 application/fhir+json. Organization(US Core Organization):name,address,identifier(the NPI when the organization has one, and always the Mira organization idhttps://mirahealth.care/fhir/sid/organization-id),telecom, andendpointreferencing itsEndpoint.Endpoint:statusactive,connectionTypehl7-fhir-rest,payloadTypeany,payloadMimeTypeapplication/fhir+json,managingOrganization, andaddress, the organization's FHIR base URL (on the development stage,https://fhir-dev.mirahealth.care/fhir/R4).- References inside the Bundle are
urn:uuid:full URLs.
The Bundle is generated from the live configuration. It is served with Cache-Control: public, max-age=300, so a change (a customer going live or changing its endpoint) shows within 5 minutes.
3. Registering an app (§170.404(b)(1))
-
Register online at https://miraemr.com/developers/register (no sign-in). The form asks for:
- the practice the app will connect to (the practices listed in §2)
- app name, your organization, a contact name and email, your website
- who uses the app: patients, clinicians or practice staff, or a back-end system
- redirect URIs (https;
http://localhostfor development), and whether to register a SMART on FHIR client (required for a patient app) - for a SMART client, optionally your key set URL (
jwksUri, https) forprivate_key_jwt - what the app does with the data
- acceptance of these terms
Registration is free. You may also email support@mirahealth.care with the same details.
-
Authenticity verification. The practice's administrator, in Mira, confirms your identity and contact (for example a reply from an address on your own domain, and a working website). The decision is made within 10 business days of registration; Mira shows the administrator the due date. The same steps apply to every developer.
-
Credentials. When the registration is activated, Mira issues the credentials within 5 business days of verification (normally at once):
- Patient apps get a SMART client only. A patient app reaches a record only when that patient signs in and authorizes it (§4, §5.1); it never receives a key to the practice's records.
- Provider and back-end apps get a Mira API key
mira_<client id>.<secret>for §5. It reads every patient of that practice, so the administrator activates it as an explicit authorization of practice-wide access. It is shown once to the administrator, who sends it to your contact email; Mira keeps only a SHA-256 fingerprint. A lost key is revoked and a new registration made. - When you asked for one, a SMART client (
client_idandclient_secret) on the practice's FHIR server (§4) with your redirect URIs (and key set URL). A back-end SMART client reads every patient of the practice except restricted charts, read only, and the status and files of its own bulk exports (§4); Mira proves it can obtain a token before reporting it ready. If the FHIR server cannot take the registration at that moment, it stays on the administrator's work list with the 5-business-day deadline until it is completed.
A declined registration is told why. An administrator can revoke a key at any time; the next call with it is refused.
-
A healthcare organization that uses Mira EMR may also enable an app for its own users through the same screen.
4. (g)(10) Standardized API for patient and population services (FHIR R4)
This section is the (g)(10) API documentation required by §170.315(g)(10)(viii): the API syntax and function names (§4.4 to §4.6), the required and optional parameters with their data types and the return variables with their types and structures (§4.3 to §4.6), exceptions and their handling (§4.7), the software components and configuration an app needs (§4.2), and what an app needs to register with the authorization server (§3 and §4.3). The machine-readable source of the same facts is the live CapabilityStatement (§4.1).
Below, [base] stands for a practice's FHIR base URL. On the development stage every practice's base is https://fhir-dev.mirahealth.care/fhir/R4; the production FHIR server's address is published before production opens. Each practice's base is also in the service base URL Bundle (§2). The base URL answers only API requests (with a token); open its CapabilityStatement to read it in a browser.
4.1 Endpoints, capability statement and conformance
| Document | Link (development stage) |
|---|---|
CapabilityStatement (GET [base]/metadata) | https://fhir-dev.mirahealth.care/fhir/R4/metadata |
| SMART configuration | https://fhir-dev.mirahealth.care/fhir/R4/.well-known/smart-configuration (also at the host root: https://fhir-dev.mirahealth.care/.well-known/smart-configuration) |
| OpenID Connect configuration | https://fhir-dev.mirahealth.care/.well-known/openid-configuration |
Signing keys (JWKS) for id_token | https://fhir-dev.mirahealth.care/.well-known/jwks.json |
| Service base URL Bundle (§2) | https://miraemr.com/api/v1/api-access/service-base-urls |
| Sign-in page the authorize endpoint sends users to | https://fhir-login-dev.mirahealth.care |
The CapabilityStatement needs no token. It names the server software (Medplum 5.2.3), FHIR version 4.0.1, the JSON format, every resource type with its supported profiles, interactions and search parameters, the Group $export operation, and the OAuth endpoints (in rest.security). It instantiates the US Core server and Bulk Data CapabilityStatements.
| Standard | Version | Specification |
|---|---|---|
| HL7 FHIR | R4 (4.0.1) | FHIR R4: RESTful API, Search, Bundle, OperationOutcome, CapabilityStatement |
| US Core Implementation Guide | 6.1.0 (USCDI v3) | US Core 6.1.0 and its server CapabilityStatement; each profile is linked in §4.5 |
| SMART App Launch | 2.0.0 | SMART App Launch 2.0.0: App Launch, Scopes and launch context, Backend Services, Token introspection, Conformance |
| Bulk Data Access | 1.0.1 (STU 1) | Bulk Data Access 1.0.1: Export request flow; the operations are linked in §4.6 |
| OAuth 2.0 and related | RFCs | RFC 6749 (OAuth 2.0), RFC 6750 (bearer tokens), RFC 7636 (PKCE), RFC 7523 (private_key_jwt), RFC 7662 (introspection) |
| ONC test method | §170.315(g)(10) | Standardized API for patient and population services |
4.2 Software components and configuration
What Mira runs.
- FHIR server and authorization server: Medplum 5.2.3, one project per practice. It serves the FHIR API, the SMART authorization and token endpoints, token introspection and bulk export.
- Sign-in page: the Medplum sign-in app at
fhir-login-dev.mirahealth.care, where a user signs in, chooses which scopes to grant, and consents. - Mira EMR: the system of record. It writes each practice's chart to the FHIR server, publishes the service base URLs (§2), handles registration (§3), and serves the bytes of clinical documents (§4.4).
What an app needs.
- An HTTPS client (TLS 1.2 or later) that can send an
Authorization: Bearerheader and parse JSON. The FHIR server speaks JSON only (application/fhir+json); XML is not offered. - An OAuth 2.0 client that follows SMART App Launch 2.0.0 (any SMART client library will do): the authorization code grant with PKCE
S256for patient and clinician apps, orclient_credentialswithprivate_key_jwt(or the client secret) for back-end apps. - A client registered through §3, with these settings:
- Register redirect URIs exactly; no wildcards.
- Every SMART client registered through Mira receives a
client_idand aclient_secret. The authorization code grant always requires PKCE (S256). An app that cannot keep a secret (a browser or native app) sends only itsclient_idwith PKCE, as a public client; the secret is not checked in that grant. - Any SMART client may register a key set URL (
jwksUri) forprivate_key_jwt, signed with RS256, RS384 or ES384. - Request
launch/patientfor a standalone patient launch, orlaunchfor an EHR launch.
- For bulk export: the ability to poll a status URL and download NDJSON files (§4.6).
4.3 Authorization (SMART App Launch 2.0.0)
Endpoints. These are API endpoints, not pages: each answers only the request shown. They are also listed in the SMART configuration.
| Function | HTTP syntax (development stage) | Notes |
|---|---|---|
| Authorize | GET or POST https://fhir-dev.mirahealth.care/oauth2/authorize | Opened in the user's browser. Sends the user to the sign-in page, then back to redirect_uri |
| Token | POST https://fhir-dev.mirahealth.care/oauth2/token | Body application/x-www-form-urlencoded |
| Token introspection | POST https://fhir-dev.mirahealth.care/oauth2/introspect | Body token={access or refresh token}. The caller authenticates as the client the token was issued to |
| UserInfo (OpenID Connect) | GET https://fhir-dev.mirahealth.care/oauth2/userinfo | Authorization: Bearer {access_token} |
| Sign out and revoke the app's access | GET https://fhir-dev.mirahealth.care/oauth2/logout | Authorization: Bearer {access_token}. Revokes the sign-in, so its access and refresh tokens stop working. There is no RFC 7009 revocation endpoint |
Authorization request (GET [authorize]?…, or the same fields form-encoded in a POST). Every parameter is a string.
| Parameter | Type | Required | Value |
|---|---|---|---|
response_type | string | yes | code |
client_id | string | yes | Your client_id |
redirect_uri | string (URL) | yes | Exactly one of your registered redirect URIs |
scope | string (scopes separated by spaces) | yes | See Scopes below |
state | string | yes | An unguessable value; returned unchanged |
aud | string (URL) | yes | The FHIR base URL, https://fhir-dev.mirahealth.care/fhir/R4. Another server is refused (invalid_request) |
code_challenge | string (base64url SHA-256 of the verifier) | yes | PKCE challenge |
code_challenge_method | string | yes | S256 |
launch | string | EHR launch only | The launch value Mira passed to your launch URL |
nonce | string | no | OpenID Connect nonce, echoed in the id_token |
Success redirects to {redirect_uri}?code={code}&state={state}. An error after the client and redirect URI are known redirects to {redirect_uri}?error={code}&error_description={text}&state={state} (for example invalid_request or unsupported_response_type).
Token request (POST [token], Content-Type: application/x-www-form-urlencoded).
| Grant | Parameters (all strings) |
|---|---|
| Authorization code | grant_type=authorization_code, code, redirect_uri, code_verifier; a public client also sends client_id. A confidential client authenticates as below |
| Refresh | grant_type=refresh_token, refresh_token; a confidential client authenticates as below |
| Client credentials (back-end, bulk) | grant_type=client_credentials, scope (system/ scopes); client authentication as below |
| Client authentication | client_secret_basic (Authorization: Basic base64(client_id:client_secret)), client_secret_post (client_id and client_secret in the body), or private_key_jwt (client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer and client_assertion, a JWT signed with your registered key per SMART Backend Services) |
Token response (200 application/json):
| Field | Type | When |
|---|---|---|
access_token | string (JWT) | Always. Send it as Authorization: Bearer {access_token} |
token_type | string | Always Bearer |
expires_in | integer (seconds) | Always. The access token's lifetime |
scope | string (space-separated) | Always. The scopes granted, which may be fewer than requested: the patient chooses which to grant |
id_token | string (JWT) | When openid and fhirUser were granted. Signed RS256; keys at the JWKS URL (§4.1) |
refresh_token | string | When offline_access or online_access was granted |
patient | string (Patient id) | When the token has a patient context (patient launch, patient account, or an EHR launch with a patient) |
encounter | string (Encounter id) | When an EHR launch carried a visit |
need_patient_banner | boolean | Always. true when there is a patient context |
smart_style_url | string (URL) | Always. https://fhir-dev.mirahealth.care/fhir/R4/.well-known/smart-styles.json |
The server also returns project, profile and fhirContext (Medplum fields); apps can ignore them. A refused token request answers 400 with {"error": string, "error_description": string}, for example {"error":"invalid_request","error_description":"Invalid client"}; invalid_grant means the code or refresh token was already used, expired or revoked.
Token introspection response (200 application/json): active (boolean). An active token adds scope (string), client_id (string), sub (string), iss (string), iat and exp (integer, seconds since 1970) and patient (string, when there is a patient context). An unknown, expired or revoked token answers {"active": false}.
Scopes. SMART v1 and v2 syntax are both accepted (the SMART configuration lists permission-v1 and permission-v2).
| Scope | Form |
|---|---|
| Resource scopes, v1 | patient/{Type}.read, user/{Type}.read, system/{Type}.read (also .write, .*), for one resource type or *. Example: patient/Observation.read |
| Resource scopes, v2 | patient/{Type}.rs, user/{Type}.rs, system/{Type}.rs and the other c r u d s combinations, for one resource type or *. Example: patient/*.rs |
| Granular scopes, v2 (Condition) | patient/Condition.rs?category=http://terminology.hl7.org/CodeSystem/condition-category|encounter-diagnosis, …|problem-list-item, and patient/Condition.rs?category=http://hl7.org/fhir/us/core/CodeSystem/condition-category|health-concern (also with user/) |
| Granular scopes, v2 (Observation) | patient/Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|laboratory, …|vital-signs, …|social-history, …|survey, …|procedure (clinical tests), and patient/Observation.rs?category=http://hl7.org/fhir/us/core/CodeSystem/us-core-category|sdoh (also with user/) |
| Launch context | launch (EHR launch), launch/patient (standalone patient launch) |
| Identity | openid, fhirUser |
| Refresh | offline_access, online_access |
patient/scopes need a patient context (a patient launch or a patient account).system/scopes are for back-end clients (client_credentials).- A token reads only what both its scopes and its account's access rules allow. The access rules are read only, so a write scope grants nothing.
- A granular scope never authorizes the whole resource type: a token with only
patient/Observation.rs?category=…|laboratorygets laboratory Observations and nothing else. scopes_supportedin the SMART configuration listspatient/*.rs,user/*.cruds,openid,fhirUser,launch,launch/patient,offline_accessandonline_access. That list is fixed by the FHIR server software (Medplum 5.2.3) and is not complete: every scope form above is accepted.
Sign-in accounts. A patient or clinician signs in on the FHIR server's own sign-in page with an account Mira creates on the practice's request; the FHIR server emails an invitation to set a password. Mira EMR has no self-service screen for this yet. A patient account reads only that patient's own record; a clinician account reads every patient of the practice except restricted charts, read only.
Launches.
- Standalone patient launch: the patient signs in with that account.
- EHR launch: Mira creates the launch context (the patient, and the visit when given) on the FHIR server and opens the app's launch URL with
iss(the FHIR base URL) andlaunch; the app then authorizes withlaunchand the clinician signs in. Mira EMR's chart has no launch button yet: an EHR launch is started with Mira'slaunchFhirAppcommand, and never for a restricted chart.
Refresh tokens.
- Issued to: apps granted
offline_access(oronline_access). This includes native apps that can keep a secret or use PKCE. - Life: 100 days, for the first refresh token and for every renewed one. Mira sets this lifetime on every app it registers on the FHIR server (the FHIR server's own default is two weeks).
- Renewal: using a refresh token at the token endpoint (
grant_type=refresh_token) returns a new access token and a new refresh token without the user signing in again, per §170.315(g)(10)(v)(A).
Registration. Apps register through §3. What the authorization server needs: the redirect URIs (https; http://localhost for development), whether the app is a patient app, a clinician app or a back-end system, and optionally a key set URL (jwksUri, https) for private_key_jwt. Mira issues the client_id and client_secret (§3, step 3).
4.4 Requests and responses
Functions. The API's functions are the FHIR RESTful interactions and one operation:
| Function | HTTP syntax | Returns |
|---|---|---|
| capabilities | GET [base]/metadata | 200 CapabilityStatement (no token needed) |
| read | GET [base]/{Type}/{id} | 200 the resource |
| vread | GET [base]/{Type}/{id}/_history/{versionId} | 200 that version of the resource |
| history | GET [base]/{Type}/{id}/_history | 200 Bundle of type history |
| search | GET [base]/{Type}?{parameters}, or POST [base]/{Type}/_search with the parameters form-encoded in the body | 200 Bundle of type searchset |
$export | GET [base]/Group/{id}/$export, GET [base]/Patient/$export, GET [base]/$export | 202 and a status URL (§4.6) |
Send on every request: Authorization: Bearer {access_token} and Accept: application/fhir+json. Responses are application/fhir+json. The API is read only for apps: the create, update, patch and delete interactions the CapabilityStatement lists are refused.
Parameter data types (FHIR search parameter types):
| Type | Syntax | Example |
|---|---|---|
| reference | {id} or {Type}/{id} | patient=6f0c9a8e-2c3b-4f7e-9a51-0d2b8c7e1a44 |
| token | {system}|{code}, or {code} alone | category=http://terminology.hl7.org/CodeSystem/observation-category|laboratory |
| date | YYYY, YYYY-MM, YYYY-MM-DD or a dateTime, with an optional prefix eq, gt, lt, ge or le; repeat the parameter for a range | date=ge2026-01-01&date=le2026-06-30 |
| string | text; matches values that start with it, ignoring case | name=riv |
| number | integer | _count=50 |
Several values of one parameter separated by commas match any of them (status=active,completed). No US Core search below uses a composite parameter.
Search results. A search returns a Bundle:
| Field | Type | Notes |
|---|---|---|
resourceType | string | Bundle |
type | code | searchset |
link[] | {relation: string, url: string} | self, and next while there are more pages. Follow next until it is absent |
entry[].fullUrl | string (URL) | The resource's absolute URL |
entry[].resource | resource | A resource of the searched type, or a Provenance added by _revinclude |
entry[].search.mode | code | match for a result, include for a resource added by _revinclude |
No match returns 200 with no entries. _revinclude=Provenance:target adds each result's US Core Provenance (author and author organization). _count sets the page size.
Document content. A DocumentReference (and a report-type DiagnosticReport) holds its document in content[].attachment.url (presentedForm[].url), an address on Mira EMR of the form https://{Mira EMR host}/fhir-binary/{documentId}. Fetch it with GET and the same Authorization: Bearer token; it returns the document's bytes with its own content type. It serves only documents the token may read.
What a patient token reads. A patient-context token reads that patient's own record. On the current server software (Medplum 5.2.3), patient/ scopes reach only resources in the patient's compartment, so a patient app cannot read the Practitioner or Organization resources a record refers to; a clinician (user/) or back-end (system/) token can.
4.5 Supported resources and searches
The US Core 6.1.0 resources Mira sends for USCDI v3, and the searches each supports. Every search below is a SHALL or SHOULD search of the US Core server CapabilityStatement, and every parameter in it is in the live CapabilityStatement's list for that resource (checked 2026-10-22). The read row links the profile every returned resource conforms to; the resources in a search's Bundle conform to the same profile.
- Observation categories:
laboratory,vital-signs,social-history,survey,imaging(a report's impression),procedure(a clinical test result, US Core Observation Clinical Result: one recorded by its LOINC code, such as an EKG's QT interval 44975-1 in seconds, or a signed EKG report), and the US Core categoriessdoh,functional-status,disability-statusandcognitive-status. - MedicationDispense: a prescription's pharmacy fill status (USCDI v3 Fill Status).
statusiscompleted(filled),in-progress(partly filled) ordeclined(not filled);authorizingPrescriptionis the MedicationRequest; the drug and dosage instruction are the prescription's; the pharmacy is theperformer(an Organization). The fill comes from DoseSpot when the pharmacy reports it (RxFill), or staff record it on the prescription. - DiagnosticReport: a laboratory pathology report (LOINC 11526-1, 11529-5, 60567-5, 60568-3) carries both the
LABand the LOINC Pathology category, so it is returned for either category and itsresultpoints at its laboratory Observations. - DocumentReference: the clinical notes (category
clinical-note). - Not sent: Medication (a medication is coded inside its MedicationRequest and MedicationDispense), PractitionerRole and QuestionnaireResponse.
AllergyIntolerance
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/AllergyIntolerance/{id} | id (id, in the path) | AllergyIntolerance (US Core AllergyIntolerance) |
| search | GET [base]/AllergyIntolerance?patient={id} | patient (reference) | Bundle (searchset) of AllergyIntolerance |
| search | GET [base]/AllergyIntolerance?patient={id}&clinical-status={token} | patient (reference), clinical-status (token) | Bundle (searchset) of AllergyIntolerance |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
CarePlan
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/CarePlan/{id} | id (id, in the path) | CarePlan (US Core CarePlan) |
| search | GET [base]/CarePlan?patient={id}&category={token} | patient (reference), category (token) | Bundle (searchset) of CarePlan |
| search | GET [base]/CarePlan?patient={id}&category={token}&status={token} | patient (reference), category (token), status (token) | Bundle (searchset) of CarePlan |
| search | GET [base]/CarePlan?patient={id}&category={token}&date={date} | patient (reference), category (token), date (date) | Bundle (searchset) of CarePlan |
| search | GET [base]/CarePlan?patient={id}&category={token}&status={token}&date={date} | patient (reference), category (token), status (token), date (date) | Bundle (searchset) of CarePlan |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
CareTeam
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/CareTeam/{id} | id (id, in the path) | CareTeam (US Core CareTeam) |
| search | GET [base]/CareTeam?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of CareTeam |
| search | GET [base]/CareTeam?patient={id}&role={token} | patient (reference), role (token) | Bundle (searchset) of CareTeam |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Condition
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Condition/{id} | id (id, in the path) | Condition (US Core Condition Encounter Diagnosis or US Core Condition Problems and Health Concerns) |
| search | GET [base]/Condition?patient={id} | patient (reference) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&category={token} | patient (reference), category (token) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&recorded-date={date} | patient (reference), recorded-date (date) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&asserted-date={date} | patient (reference), asserted-date (date) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&onset-date={date} | patient (reference), onset-date (date) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&abatement-date={date} | patient (reference), abatement-date (date) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&clinical-status={token} | patient (reference), clinical-status (token) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&code={token} | patient (reference), code (token) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&category={token}&clinical-status={token} | patient (reference), category (token), clinical-status (token) | Bundle (searchset) of Condition |
| search | GET [base]/Condition?patient={id}&category={token}&encounter={id} | patient (reference), category (token), encounter (reference) | Bundle (searchset) of Condition |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Coverage
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Coverage/{id} | id (id, in the path) | Coverage (US Core Coverage) |
| search | GET [base]/Coverage?patient={id} | patient (reference) | Bundle (searchset) of Coverage |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Device
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Device/{id} | id (id, in the path) | Device (US Core Implantable Device) |
| search | GET [base]/Device?patient={id} | patient (reference) | Bundle (searchset) of Device |
| search | GET [base]/Device?patient={id}&type={token} | patient (reference), type (token) | Bundle (searchset) of Device |
| search | GET [base]/Device?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of Device |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
DiagnosticReport
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/DiagnosticReport/{id} | id (id, in the path) | DiagnosticReport (US Core DiagnosticReport for Laboratory Results Reporting or US Core DiagnosticReport for Report and Note Exchange) |
| search | GET [base]/DiagnosticReport?patient={id} | patient (reference) | Bundle (searchset) of DiagnosticReport |
| search | GET [base]/DiagnosticReport?patient={id}&category={token} | patient (reference), category (token) | Bundle (searchset) of DiagnosticReport |
| search | GET [base]/DiagnosticReport?patient={id}&code={token} | patient (reference), code (token) | Bundle (searchset) of DiagnosticReport |
| search | GET [base]/DiagnosticReport?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of DiagnosticReport |
| search | GET [base]/DiagnosticReport?patient={id}&category={token}&date={date} | patient (reference), category (token), date (date) | Bundle (searchset) of DiagnosticReport |
| search | GET [base]/DiagnosticReport?patient={id}&code={token}&date={date} | patient (reference), code (token), date (date) | Bundle (searchset) of DiagnosticReport |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
DocumentReference
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/DocumentReference/{id} | id (id, in the path) | DocumentReference (US Core DocumentReference) |
| search | GET [base]/DocumentReference?_id={id} | _id (token) | Bundle (searchset) of DocumentReference |
| search | GET [base]/DocumentReference?patient={id} | patient (reference) | Bundle (searchset) of DocumentReference |
| search | GET [base]/DocumentReference?patient={id}&type={token} | patient (reference), type (token) | Bundle (searchset) of DocumentReference |
| search | GET [base]/DocumentReference?patient={id}&category={token} | patient (reference), category (token) | Bundle (searchset) of DocumentReference |
| search | GET [base]/DocumentReference?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of DocumentReference |
| search | GET [base]/DocumentReference?patient={id}&category={token}&date={date} | patient (reference), category (token), date (date) | Bundle (searchset) of DocumentReference |
| search | GET [base]/DocumentReference?patient={id}&type={token}&period={date} | patient (reference), type (token), period (date) | Bundle (searchset) of DocumentReference |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Encounter
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Encounter/{id} | id (id, in the path) | Encounter (US Core Encounter) |
| search | GET [base]/Encounter?_id={id} | _id (token) | Bundle (searchset) of Encounter |
| search | GET [base]/Encounter?patient={id} | patient (reference) | Bundle (searchset) of Encounter |
| search | GET [base]/Encounter?identifier={token} | identifier (token) | Bundle (searchset) of Encounter |
| search | GET [base]/Encounter?patient={id}&date={date} | patient (reference), date (date) | Bundle (searchset) of Encounter |
| search | GET [base]/Encounter?patient={id}&type={token} | patient (reference), type (token) | Bundle (searchset) of Encounter |
| search | GET [base]/Encounter?patient={id}&class={token} | patient (reference), class (token) | Bundle (searchset) of Encounter |
| search | GET [base]/Encounter?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of Encounter |
| search | GET [base]/Encounter?patient={id}&location={id} | patient (reference), location (reference) | Bundle (searchset) of Encounter |
| search | GET [base]/Encounter?patient={id}&discharge-disposition={token} | patient (reference), discharge-disposition (token) | Bundle (searchset) of Encounter |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Goal
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Goal/{id} | id (id, in the path) | Goal (US Core Goal) |
| search | GET [base]/Goal?patient={id} | patient (reference) | Bundle (searchset) of Goal |
| search | GET [base]/Goal?patient={id}&target-date={date} | patient (reference), target-date (date) | Bundle (searchset) of Goal |
| search | GET [base]/Goal?patient={id}&description={token} | patient (reference), description (token) | Bundle (searchset) of Goal |
| search | GET [base]/Goal?patient={id}&lifecycle-status={token} | patient (reference), lifecycle-status (token) | Bundle (searchset) of Goal |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Immunization
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Immunization/{id} | id (id, in the path) | Immunization (US Core Immunization) |
| search | GET [base]/Immunization?patient={id} | patient (reference) | Bundle (searchset) of Immunization |
| search | GET [base]/Immunization?patient={id}&date={date} | patient (reference), date (date) | Bundle (searchset) of Immunization |
| search | GET [base]/Immunization?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of Immunization |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Location
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Location/{id} | id (id, in the path) | Location (US Core Location) |
| search | GET [base]/Location?name={string} | name (string) | Bundle (searchset) of Location |
| search | GET [base]/Location?address={string} | address (string) | Bundle (searchset) of Location |
| search | GET [base]/Location?address-city={string} | address-city (string) | Bundle (searchset) of Location |
| search | GET [base]/Location?address-state={string} | address-state (string) | Bundle (searchset) of Location |
| search | GET [base]/Location?address-postalcode={string} | address-postalcode (string) | Bundle (searchset) of Location |
Optional on every search: _count (number).
MedicationDispense
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/MedicationDispense/{id} | id (id, in the path) | MedicationDispense (US Core MedicationDispense) |
| search | GET [base]/MedicationDispense?patient={id} | patient (reference) | Bundle (searchset) of MedicationDispense |
| search | GET [base]/MedicationDispense?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of MedicationDispense |
| search | GET [base]/MedicationDispense?patient={id}&status={token}&type={token} | patient (reference), status (token), type (token) | Bundle (searchset) of MedicationDispense |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
MedicationRequest
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/MedicationRequest/{id} | id (id, in the path) | MedicationRequest (US Core MedicationRequest) |
| search | GET [base]/MedicationRequest?patient={id}&intent={token} | patient (reference), intent (token) | Bundle (searchset) of MedicationRequest |
| search | GET [base]/MedicationRequest?patient={id}&intent={token}&status={token} | patient (reference), intent (token), status (token) | Bundle (searchset) of MedicationRequest |
| search | GET [base]/MedicationRequest?patient={id}&intent={token}&encounter={id} | patient (reference), intent (token), encounter (reference) | Bundle (searchset) of MedicationRequest |
| search | GET [base]/MedicationRequest?patient={id}&intent={token}&authoredon={date} | patient (reference), intent (token), authoredon (date) | Bundle (searchset) of MedicationRequest |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Observation
Profiles: Laboratory Result, Clinical Result, Screening and Assessment, Smoking Status, Occupation, Pregnancy Status, Pregnancy Intent, Sexual Orientation, Vital Signs, Blood Pressure, BMI, Body Height, Body Weight, Body Temperature, Head Circumference, Heart Rate, Respiratory Rate, Pulse Oximetry, Pediatric BMI for Age, Pediatric Weight for Height, Pediatric Head Occipital-frontal Circumference Percentile.
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Observation/{id} | id (id, in the path) | Observation (one of the profiles above) |
| search | GET [base]/Observation?patient={id}&category={token} | patient (reference), category (token) | Bundle (searchset) of Observation |
| search | GET [base]/Observation?patient={id}&code={token} | patient (reference), code (token) | Bundle (searchset) of Observation |
| search | GET [base]/Observation?patient={id}&category={token}&date={date} | patient (reference), category (token), date (date) | Bundle (searchset) of Observation |
| search | GET [base]/Observation?patient={id}&code={token}&date={date} | patient (reference), code (token), date (date) | Bundle (searchset) of Observation |
| search | GET [base]/Observation?patient={id}&category={token}&status={token} | patient (reference), category (token), status (token) | Bundle (searchset) of Observation |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Organization
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Organization/{id} | id (id, in the path) | Organization (US Core Organization) |
| search | GET [base]/Organization?name={string} | name (string) | Bundle (searchset) of Organization |
| search | GET [base]/Organization?address={string} | address (string) | Bundle (searchset) of Organization |
Optional on every search: _count (number).
Patient
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Patient/{id} | id (id, in the path) | Patient (US Core Patient) |
| search | GET [base]/Patient?_id={id} | _id (token) | Bundle (searchset) of Patient |
| search | GET [base]/Patient?identifier={token} | identifier (token) | Bundle (searchset) of Patient |
| search | GET [base]/Patient?name={string} | name (string) | Bundle (searchset) of Patient |
| search | GET [base]/Patient?birthdate={date}&name={string} | birthdate (date), name (string) | Bundle (searchset) of Patient |
| search | GET [base]/Patient?gender={token}&name={string} | gender (token), name (string) | Bundle (searchset) of Patient |
| search | GET [base]/Patient?birthdate={date}&family={string} | birthdate (date), family (string) | Bundle (searchset) of Patient |
| search | GET [base]/Patient?family={string}&gender={token} | family (string), gender (token) | Bundle (searchset) of Patient |
| search | GET [base]/Patient?death-date={date}&family={string} | death-date (date), family (string) | Bundle (searchset) of Patient |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Practitioner
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Practitioner/{id} | id (id, in the path) | Practitioner (US Core Practitioner) |
| search | GET [base]/Practitioner?name={string} | name (string) | Bundle (searchset) of Practitioner |
| search | GET [base]/Practitioner?identifier={token} | identifier (token) | Bundle (searchset) of Practitioner |
| search | GET [base]/Practitioner?_id={id} | _id (token) | Bundle (searchset) of Practitioner |
Optional on every search: _count (number).
Procedure
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Procedure/{id} | id (id, in the path) | Procedure (US Core Procedure) |
| search | GET [base]/Procedure?patient={id} | patient (reference) | Bundle (searchset) of Procedure |
| search | GET [base]/Procedure?patient={id}&date={date} | patient (reference), date (date) | Bundle (searchset) of Procedure |
| search | GET [base]/Procedure?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of Procedure |
| search | GET [base]/Procedure?patient={id}&code={token}&date={date} | patient (reference), code (token), date (date) | Bundle (searchset) of Procedure |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Provenance
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Provenance/{id} | id (id, in the path) | Provenance (US Core Provenance) |
RelatedPerson
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/RelatedPerson/{id} | id (id, in the path) | RelatedPerson (US Core RelatedPerson) |
| search | GET [base]/RelatedPerson?_id={id} | _id (token) | Bundle (searchset) of RelatedPerson |
| search | GET [base]/RelatedPerson?patient={id} | patient (reference) | Bundle (searchset) of RelatedPerson |
| search | GET [base]/RelatedPerson?name={string} | name (string) | Bundle (searchset) of RelatedPerson |
| search | GET [base]/RelatedPerson?patient={id}&name={string} | patient (reference), name (string) | Bundle (searchset) of RelatedPerson |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
ServiceRequest
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/ServiceRequest/{id} | id (id, in the path) | ServiceRequest (US Core ServiceRequest) |
| search | GET [base]/ServiceRequest?patient={id} | patient (reference) | Bundle (searchset) of ServiceRequest |
| search | GET [base]/ServiceRequest?_id={id} | _id (token) | Bundle (searchset) of ServiceRequest |
| search | GET [base]/ServiceRequest?patient={id}&category={token} | patient (reference), category (token) | Bundle (searchset) of ServiceRequest |
| search | GET [base]/ServiceRequest?patient={id}&code={token} | patient (reference), code (token) | Bundle (searchset) of ServiceRequest |
| search | GET [base]/ServiceRequest?patient={id}&status={token} | patient (reference), status (token) | Bundle (searchset) of ServiceRequest |
| search | GET [base]/ServiceRequest?patient={id}&category={token}&authored={date} | patient (reference), category (token), authored (date) | Bundle (searchset) of ServiceRequest |
| search | GET [base]/ServiceRequest?patient={id}&code={token}&authored={date} | patient (reference), code (token), authored (date) | Bundle (searchset) of ServiceRequest |
Optional on every search: _count (number), _revinclude=Provenance:target (string).
Specimen
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Specimen/{id} | id (id, in the path) | Specimen (US Core Specimen) |
| search | GET [base]/Specimen?_id={id} | _id (token) | Bundle (searchset) of Specimen |
| search | GET [base]/Specimen?patient={id} | patient (reference) | Bundle (searchset) of Specimen |
Optional on every search: _count (number).
Group (bulk export)
One Group per practice: every patient of the practice except restricted charts. It has no US Core profile.
| Interaction | HTTP syntax | Required parameters (type) | Returns |
|---|---|---|---|
| read | GET [base]/Group/{id} | id (id, in the path) | Group |
| search | GET [base]/Group | none | Bundle (searchset) of Group: the practice's one Group |
$export | GET [base]/Group/{id}/$export | see §4.6 | see §4.6 |
4.6 Bulk Data Access 1.0.1 ($export)
| Operation | Kick-off syntax | Exports | OperationDefinition |
|---|---|---|---|
| Group export | GET [base]/Group/{id}/$export | The practice's patients and their data, with the Practitioner, Organization and Location resources that data refers to. Declared in the CapabilityStatement | group-export |
| Patient export | GET [base]/Patient/$export | Every patient the client may read, with their data. A patient's own token exports only that patient's record | patient-export |
| System export | GET [base]/$export | Every resource the client may read | export |
Authorization. A back-end client (client_credentials with private_key_jwt or its client secret, §4.3) with a system/ read scope, for example system/*.rs or system/*.read. The practice's Group excludes restricted charts. A patient token may not use Group export.
Kick-off request. Headers Accept: application/fhir+json, Prefer: respond-async and Authorization: Bearer {access_token}.
| Parameter | Type | Required | Supported |
|---|---|---|---|
_outputFormat | string | no | Accepted; the output is always NDJSON (application/fhir+ndjson), whatever the value |
_since | instant (YYYY-MM-DDThh:mm:ss[.sss]Z or with an offset) | no | Yes, on all three. Only resources changed at or after _since are exported, including the Practitioner, Organization and Location resources a group export adds |
_type | string: resource types separated by commas | no | Yes, on all three. Only those resource types are exported |
_typeFilter | string: a FHIR search, for example Observation?category=laboratory | no | Patient and system export only; a group export with _typeFilter answers 400 |
Kick-off response. 202 Accepted with the header Content-Location: https://fhir-dev.mirahealth.care/fhir/R4/bulkdata/export/{exportId}, the status URL. A refused request answers 4xx with an OperationOutcome (§4.7).
Status request. GET {Content-Location} with Authorization: Bearer {access_token}. A client reads only its own exports.
202 Accepted, no body: still running. Poll again after a few seconds.200 OK,application/json: complete. The body is the manifest below.404: the export was cancelled or does not exist for this client.
Cancelling a running export (DELETE {Content-Location}) is not available to clients registered through Mira.
Completion manifest.
| Field | Type | Value |
|---|---|---|
transactionTime | string (FHIR instant) | When the export started; use it as the next _since |
request | string (URL) | The kick-off request URL |
requiresAccessToken | boolean | false: the file URLs are signed and expire, so download them without the access token |
output[] | array of {type: string, url: string} | One entry per file: type is the resource type (for example Patient), url the file's signed URL |
error[] | array of {type: string, url: string} | Files of OperationOutcome resources for anything that could not be exported; empty when nothing failed |
The server also returns a deleted array (a Bulk Data 2.0 field); Bulk Data 1.0.1 clients can ignore it.
{
"transactionTime": "2026-10-22T15:00:00.000Z",
"request": "https://fhir-dev.mirahealth.care/fhir/R4/Group/{id}/$export",
"requiresAccessToken": false,
"output": [
{"type": "Patient", "url": "https://fhir-dev.mirahealth.care/storage/…"},
{"type": "Condition", "url": "https://fhir-dev.mirahealth.care/storage/…"}
],
"error": []
}
File request. GET {output[].url} with no Authorization header returns 200 and the file in NDJSON: one FHIR resource, as JSON, per line, all of the file's type.
4.7 Errors and exception handling
FHIR API. Every error is an HTTP status code with a FHIR OperationOutcome body (application/fhir+json):
| Field | Type | Value |
|---|---|---|
resourceType | string | OperationOutcome |
issue[] | array | One or more issues |
issue[].severity | code | error (or fatal, warning, information) |
issue[].code | code | The FHIR issue type, for example login, forbidden, not-found, invalid, processing |
issue[].details.text | string | A plain-language message |
issue[].expression[] | string | The parameter or element at fault, when there is one |
extension[] (tracing) | object | The request's requestId; quote it to support |
{
"resourceType": "OperationOutcome",
"id": "unauthorized",
"issue": [{"severity": "error", "code": "login", "details": {"text": "Unauthorized"}}]
}
| HTTP | When | What the app should do |
|---|---|---|
| 400 | Invalid search or parameter (an unknown parameter, a malformed value, _typeFilter on a group export) | Fix the request; do not retry it unchanged |
| 401 | Missing, expired, revoked or invalid access token | Use the refresh token for a new access token, or authorize again; then retry |
| 403 | The token's scopes or the account's access rules refuse the request (including any write); or the firewall limit (§4.8) | Do not retry; request the scope the call needs |
| 404 | No such resource, or a resource the token may not read (the same answer for both) | Treat as not found |
| 410 | The resource was deleted | Remove your copy |
| 429 | Too many sign-in attempts (§4.8) | Wait a minute, then retry |
| 5xx | Server error | Retry with backoff; quote the requestId to support |
Bulk export: 202 while running, then 200 with the manifest (§4.6).
Authorization server. The token and introspection endpoints answer errors as {"error": string, "error_description": string} (§4.3). The authorize endpoint returns its errors to the app's redirect_uri as error, error_description and state query parameters; when the client_id or redirect_uri itself is invalid, it shows an error page instead of redirecting.
4.8 Limits
Sign-in allows 5 attempts per minute per address (429 Too Many Requests). The token endpoint takes at most 300 requests per 5 minutes per address; past that the firewall answers 403.
5. (g)(7) patient selection and (g)(9) all data request
Mira EMR serves these two APIs itself, under https://miraemr.com/api/v1/api-access. Version: v1. A breaking change gets a new path version and the notice in §1.5.
5.1 Authentication and app configuration
Send one credential as Authorization: Bearer <credential> on every request. A request with an access_token query parameter is refused (400). There are no cookies; browser apps may call cross-origin (CORS *, preflight answered).
| Credential | How you get it | What it reaches |
|---|---|---|
Mira API key mira_<client id>.<secret> | Registration (§3) | Every patient of the one practice it was registered for, both endpoints. Issued to provider and back-end apps only. Only an active key works |
SMART access token from the practice's FHIR server (/oauth2/token, §4): authorization_code with PKCE for a patient-facing or clinician app, client_credentials (private_key_jwt or client_secret_basic) for a back-end app | §3 or the practice | A patient-context token (patient launch): that patient only. Any other token: the practice whose FHIR project registered the client; and in every case only the patients and resources the token's own FHIR access policy shows it. Scopes: a Patient read scope for §5.2 (system/Patient.rs, user/Patient.read, patient/*.rs …); for §5.3, an unconstrained read of every resource the CCD carries, in practice patient/*.rs, user/*.rs or system/*.rs. A constrained scope (…?category=…) never authorizes a whole resource type |
Software you need: any HTTPS client (TLS 1.2 or later) that can set a header, parse JSON (§5.2) and save XML (§5.3). For SMART tokens, a SMART App Launch 2.0 client library (§4). Responses are never cached (Cache-Control: no-store).
Results never cross practices. With a SMART token, Mira asks the FHIR server, as that token, which of the matching patients it may see (§5.2) and whether it may read the patient and every resource type of the CCD (§5.3); anything refused is left out or refused. A restricted chart (a confidential chart the practice limits to named staff) is reachable only by the patient's own token.
5.2 (g)(7) Patient selection: GET /api/v1/api-access/patients
Returns the Mira patient id (the token for §5.3) of every patient of the practice who matches and whom the credential may reach.
Query parameters. Provide either identifier, or name with birthdate.
| Parameter | Format | Rule |
|---|---|---|
identifier | <system>|<value>, for example https://mirahealth.care/fhir/sid/mrn/<organizationId>|12345 | Exact match. Systems: the practice's MRN system https://mirahealth.care/fhir/sid/mrn/<organizationId> and the Mira patient id https://mirahealth.care/fhir/sid/patient-id. Any other system matches nothing |
name | text, 1–100 characters: family or family,given | Family name: exact, ignoring case and accents. Given name: matches the start of the first name, ignoring case and accents |
birthdate | YYYY-MM-DD | Exact date. Required with name |
_count | integer 1–50, default 20 | Page size |
page | opaque cursor from next | Next page |
Only charts the CCD (§5.3) can be produced for are listed: a merged chart is not, and neither is a chart with no date of birth or of a minor (the patient record export Mira serves today is for adults).
Response 200 application/json:
{
"patients": [
{
"id": "6f0c9a8e-2c3b-4f7e-9a51-0d2b8c7e1a44",
"identifier": [
{"system": "https://mirahealth.care/fhir/sid/mrn/<organizationId>", "value": "12345"},
{"system": "https://mirahealth.care/fhir/sid/patient-id", "value": "6f0c9a8e-2c3b-4f7e-9a51-0d2b8c7e1a44"}
],
"name": {"family": "Rivera", "given": ["Ana"]},
"birthDate": "1971-04-05",
"sex": "female"
}
],
"total": 1,
"next": null
}
| Field | Type | Notes |
|---|---|---|
patients[].id | string (UUID) | Pass to §5.3 |
patients[].identifier[] | {system: string, value: string} | MRN (when the chart has one) and the Mira patient id |
patients[].name | {family: string, given: string[]} | Legal name |
patients[].birthDate | string YYYY-MM-DD | |
patients[].sex | female | male | other | unknown | |
total | integer | Matches on this page and after |
next | string | null | Cursor for page |
No match returns 200 with "patients": [], not 404.
5.3 (g)(9) All data request: GET /api/v1/api-access/patients/{id}/ccd
Returns a C-CDA R2.1 Continuity of Care Document (Companion Guide R4.1, USCDI v3) for one patient: every USCDI data class Mira holds for the patient, as section narrative and discrete entries, in one document.
| Parameter | Where | Format | Rule |
|---|---|---|---|
id | path | UUID from §5.2 | Must be a patient the credential may reach |
start | query | YYYY-MM-DD | Optional. Inclusive start of the date range |
end | query | YYYY-MM-DD | Optional. Inclusive end of the date range |
Date semantics.
- With neither
startnorend, the document holds all of the patient's data. - A specific date: send the same day as
startandend. - A date range: the document holds the data relevant to that period: encounters, procedures, results, vital signs, immunizations, notes and assessments dated in it, and problems, medications, allergies, goals and care plans active at any time in it. Either end may be left open.
- Patient demographics, the care team, the author and custodian are always included.
- Dates are compared at day precision on the date as recorded; a timestamped entry counts on its UTC calendar date.
documentationOf/serviceEvent/effectiveTimegives the span of the data in the document.startafterendis a400.
What the practice withholds. The document is the same record the practice releases to the patient in its patient portal: an item the practice has held from release (for example under a HIPAA or state-law restriction), a result not yet released, and a visit note not yet released are left out.
Response 200 application/xml. A single ClinicalDocument:
templateId2.16.840.1.113883.10.20.22.1.2, extension2015-08-01- sections per the C-CDA R2.1 CCD and Companion Guide R4.1, including Assessment and Plan of Treatment, Goals, Health Concerns, and implantable device UDIs in Medical Equipment
Headers: Content-Type: application/xml; charset=utf-8, Content-Disposition: attachment; filename="ccd-<id>.xml", Cache-Control: no-store.
5.4 Errors
Every error is JSON: {"error": {"code": "<code>", "message": "<plain words>"}}. Every response of §5.2 and §5.3 carries an X-Request-Id header.
| HTTP | code | When |
|---|---|---|
| 400 | invalid_request | Missing or malformed parameter; name without birthdate; a bad date; start after end; a patient id that is not a UUID; an access_token query parameter |
| 401 | invalid_token | Missing, expired, unknown or revoked credential (with header WWW-Authenticate: Bearer error="invalid_token") |
| 403 | insufficient_scope | The token lacks the scope, a patient token asked for another patient, or the FHIR server's access rules refuse the patient to the token |
| 404 | not_found | No such patient for this credential. The same answer is given whether the patient does not exist, belongs to another practice, or is not visible |
| 406 | not_acceptable | §5.3 called with an Accept other than application/xml, text/xml, application/* or */* |
| 429 | rate_limited | More than 600 requests per minute per client on one Mira server (each server counts separately); Retry-After gives the seconds to wait |
| 500 | server_error | Unexpected failure. Retry with backoff; quote the response's X-Request-Id to support |
| 503 | unavailable | The FHIR server cannot check the SMART token or its access right now; Retry-After is set when the token itself could not be checked |
5.5 Specifications
- C-CDA R2.1 (HL7 CDA R2 IG: C-CDA Templates for Clinical Notes R2.1; HL7 product brief, where R2.1 is listed among the releases) with the Companion Guide R4.1
- USCDI v3
- RFC 6749 (OAuth 2.0), RFC 6750 (bearer tokens)
- RFC 7523 (
private_key_jwt) - SMART App Launch 2.0.0
- ONC test procedures: (g)(7) application access, patient selection, (g)(9) application access, all data request
5.6 Example
GET /api/v1/api-access/patients?identifier=https%3A%2F%2Fmirahealth.care%2Ffhir%2Fsid%2Fmrn%2F<org>%7C12345 HTTP/1.1
Host: miraemr.com
Authorization: Bearer mira_0b8a…_c1.Yc3…
GET /api/v1/api-access/patients/6f0c9a8e-2c3b-4f7e-9a51-0d2b8c7e1a44/ccd?start=2026-01-01&end=2026-06-30 HTTP/1.1
Host: miraemr.com
Authorization: Bearer mira_0b8a…_c1.Yc3…
Accept: application/xml
curl -H "Authorization: Bearer $MIRA_API_KEY" \
"https://miraemr.com/api/v1/api-access/patients?name=Rivera,Ana&birthdate=1971-04-05"
curl -H "Authorization: Bearer $MIRA_API_KEY" -o ccd.xml \
"https://miraemr.com/api/v1/api-access/patients/<id>/ccd?start=2026-01-10&end=2026-01-10"
6. Security
- TLS 1.2 or later only.
- HSTS: Mira EMR and the FHIR server send
Strict-Transport-Security; the FHIR sign-in page host does not yet. - Every request is audited.
- Tokens are bearer tokens: keep them secret, and never put them in URLs.
- Report a vulnerability to support@mirahealth.care.