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.projectin 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
| Purpose | URL |
|---|---|
| FHIR R4 base | https://api.sandbox.ovok.com/fhir/R4 |
| Default version | https://api.sandbox.ovok.com/fhir, which serves R4 |
| CapabilityStatement | https://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:
- The project. A token is issued for one project. Resources of other projects do not exist for it: a read answers
404and a search leaves them out. - 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:
| Interaction | Method | Path |
|---|---|---|
| Read | GET | /fhir/R4/[type]/[id] |
| Vread | GET | /fhir/R4/[type]/[id]/_history/[vid] |
| Search | GET | /fhir/R4/[type]?[parameters] |
| Create | POST | /fhir/R4/[type] |
| Update | PUT | /fhir/R4/[type]/[id] |
| Patch | PATCH | /fhir/R4/[type]/[id], with a JSON Patch body (application/json-patch+json) |
| Delete | DELETE | /fhir/R4/[type]/[id] |
| History | GET | /fhir/R4/[type]/[id]/_history |
| Batch or transaction | POST | /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:
| Operation | Method and path | What it does |
|---|---|---|
| Last observations | GET /fhir/R4/Observation/$lastn | The newest Observations per code, for example the last heart rate and blood pressure of a patient. |
| Populate a Questionnaire | POST /fhir/R4/Questionnaire/[id]/$populate | Pre-fills a QuestionnaireResponse for the signed-in patient. The caller must be a patient. |
| Extract observations | POST /fhir/R4/QuestionnaireResponse/[id]/$extract | Builds Observations from a saved QuestionnaireResponse. |
| Enable Signals | POST /fhir/R4/Patient/[id]/$enable-signals | Enrols an existing Patient in Signals. Idempotent. |
| Create a Patient | POST /fhir/R4/Patient | A standard create. With ?withSignals=true, the Patient is also enrolled in Signals, all or nothing. |
| Patient's Signals status | GET /fhir/R4/Patient/[id]/signals | Whether 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
$lastnandObservationsearches return both. Wearable Observations carry a source tag inmeta.tag, systemhttps://api.ovok.com/fhir/CodeSystem/wearables-source. Filter with_tagor_tag:notto 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/metadatabefore relying on a less common interaction or search parameter.
Last updated on
Check a wearable webhook URL with a token HEAD
Answers whether a webhook URL is live, for a provider that checks it before it sends notifications (Withings does). You never call it yourself. **Auth:** none. A token at the end of the URL is not checked here. **Scope:** the project in the path. ## Answers - `200` with no body when the project has set up and switched on the provider, and ovok takes notifications from it. - Otherwise the same `404` and `422` answers as `POST` on the same URL.
FHIR resources
Detailed FHIR R4 resource reference for structure, interactions, search, and maturity.