FHIR API

Read and write your project's FHIR R4 data through Ovok, with project-scoped bearer tokens, standard FHIR interactions and Ovok's own operations.

Ovok's FHIR R4 API is your door to the FHIR store behind Ovok. It speaks standard FHIR R4: resources, search, history, batches and transactions. On top of that, Ovok adds a few operations of its own.

  • Every request is scoped to your project. The bearer token names one project, and every read, search and write runs inside it. The token's project decides this, never a meta.project in the request body.
  • Ovok is the only door. There is no direct access to the FHIR store. Every FHIR call goes through the Ovok API, which applies project scoping and serves Ovok's own operations.

Only FHIR R4 is available.

Base URL

PurposeURL
FHIR R4 basehttps://api.sandbox.ovok.com/fhir/R4
Default versionhttps://api.sandbox.ovok.com/fhir, which serves R4
CapabilityStatementhttps://api.sandbox.ovok.com/fhir/R4/metadata

Resource paths follow the FHIR pattern: /fhir/R4/Patient, /fhir/R4/Patient/[id], /fhir/R4/Observation?patient=Patient/[id]. Use Content-Type: application/fhir+json for request bodies.

GET /fhir/R4/metadata needs no token. It returns Ovok's own CapabilityStatement: every resource and search parameter the store supports, plus the operations Ovok adds ($lastn, $populate, $extract and $enable-signals). Read it when a client must decide at runtime what it may call. The other unauthenticated discovery routes are listed under Health and discovery.

Authentication

Send an access token on every call except metadata:

Authorization: Bearer <accessToken>

Patients and practitioners get a token by signing in to a tenant; see Authentication, Patient sign-in and Practitioner sign-in. A missing or expired token answers 401.

What a call can read or change depends on two things:

  1. The project. A token is issued for one project. Resources of other projects do not exist for it: a read answers 404 and a search leaves them out.
  2. The member's AccessPolicy. The policy decides which resource types and interactions the member may use, and can narrow them with criteria, for example to one patient's own records. A call the policy does not grant is refused, and a search returns only what the policy lets the member read. A membership without a policy is not restricted by one; see AccessPolicy model and membership and Default policies.

Ovok's Signals operations check named Signals capabilities as well as Patient access; see Signals route policies.

Supported interactions

All standard FHIR R4 REST interactions are available, subject to your AccessPolicy:

InteractionMethodPath
ReadGET/fhir/R4/[type]/[id]
VreadGET/fhir/R4/[type]/[id]/_history/[vid]
SearchGET/fhir/R4/[type]?[parameters]
CreatePOST/fhir/R4/[type]
UpdatePUT/fhir/R4/[type]/[id]
PatchPATCH/fhir/R4/[type]/[id], with a JSON Patch body (application/json-patch+json)
DeleteDELETE/fhir/R4/[type]/[id]
HistoryGET/fhir/R4/[type]/[id]/_history
Batch or transactionPOST/fhir/R4, with a Bundle of type batch or transaction

A transaction Bundle is all or nothing when the project has the transaction-bundles feature, which new projects have. Without it, a transaction runs as a batch.

Each resource's structure, interaction paths and search parameters are in the FHIR R4 resource reference, for example Patient, Observation and Device. Data types are in FHIR Elements. New to FHIR? Start with FHIR Basics.

Ovok's own operations

Ovok serves these routes itself, under the same base URL and with the same token:

OperationMethod and pathWhat it does
Last observationsGET /fhir/R4/Observation/$lastnThe newest Observations per code, for example the last heart rate and blood pressure of a patient.
Populate a QuestionnairePOST /fhir/R4/Questionnaire/[id]/$populatePre-fills a QuestionnaireResponse for the signed-in patient. The caller must be a patient.
Extract observationsPOST /fhir/R4/QuestionnaireResponse/[id]/$extractBuilds Observations from a saved QuestionnaireResponse.
Enable SignalsPOST /fhir/R4/Patient/[id]/$enable-signalsEnrols an existing Patient in Signals. Idempotent.
Create a PatientPOST /fhir/R4/PatientA standard create. With ?withSignals=true, the Patient is also enrolled in Signals, all or nothing.
Patient's Signals statusGET /fhir/R4/Patient/[id]/signalsWhether the Patient is enrolled in Signals, its reading and alert counts, and its newest alerts. Needs signals_alerts:read.

Errors

FHIR routes answer errors as a FHIR OperationOutcome, not as Ovok Problem Details. Read its issue entries: severity, code, details and expression. The HTTP status carries the same meaning as on every Ovok route. See Error responses for how FHIR errors differ from the rest of the API.

Examples

Set OVOK_TOKEN to an access token and PATIENT_ID to a Patient in your project.

Read a Patient:

curl "https://api.sandbox.ovok.com/fhir/R4/Patient/${PATIENT_ID}" \
  --header "Authorization: Bearer ${OVOK_TOKEN}"

Search a patient's heart rates, newest first:

curl --get 'https://api.sandbox.ovok.com/fhir/R4/Observation' \
  --header "Authorization: Bearer ${OVOK_TOKEN}" \
  --data-urlencode "patient=Patient/${PATIENT_ID}" \
  --data-urlencode 'code=http://loinc.org|8867-4' \
  --data-urlencode '_sort=-date' \
  --data-urlencode '_count=10'

The answer is a searchset Bundle. Follow its link with relation: next for the next page.

Create a Patient:

curl --request POST 'https://api.sandbox.ovok.com/fhir/R4/Patient' \
  --header "Authorization: Bearer ${OVOK_TOKEN}" \
  --header 'Content-Type: application/fhir+json' \
  --data '{
    "resourceType": "Patient",
    "name": [{ "given": ["Jane"], "family": "Example" }],
    "birthDate": "1960-04-12"
  }'

The answer is 201 Created with the stored Patient, including its server-assigned id.

$lastn: the last heart rate and respiratory rate of a patient:

curl --get 'https://api.sandbox.ovok.com/fhir/R4/Observation/$lastn' \
  --header "Authorization: Bearer ${OVOK_TOKEN}" \
  --data-urlencode "patient=Patient/${PATIENT_ID}" \
  --data-urlencode 'max=1' \
  --data-urlencode 'code=8867-4,9279-1'

Caveats

  • Wearable and device Observations sit together. A heart rate from a connected wearable uses the same LOINC code as one from a device, so $lastn and Observation searches return both. Wearable Observations carry a source tag in meta.tag, system https://api.ovok.com/fhir/CodeSystem/wearables-source. Filter with _tag or _tag:not to keep them apart; see Keep wearable and device readings apart and Cloud wearables.
  • Your project's capabilities decide. The resource reference documents the FHIR R4 standard. Read /fhir/R4/metadata before relying on a less common interaction or search parameter.

Last updated on

On this page