Most health apps treat consent as a checkbox at signup. Patients tick "I agree", and from then on every integration, every clinician and every AI assistant reads everything, forever.

That model breaks the moment a patient asks a reasonable question: "Can my cardiologist see my lab results for the next month, but not my mental-health notes?"

FHIR R4 already has the building block for this: the Consent resource. Here is how we model scoped, time-limited, revocable consent with it, and the enforcement traps we hit along the way.

The shape of a useful consent

A consent a patient can understand has four parts:

  1. Who gets access (a practitioner, an organisation, an app)
  2. What they can see (lab results, medications, everything)
  3. For how long (a start and an end date)
  4. Why (treatment, research, a second opinion)

All four map onto Consent.provision:

{ "resourceType": "Consent", "status": "active", "scope": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/consentscope", "code": "patient-privacy" }] }, "category": [{ "coding": [{ "system": "http://loinc.org", "code": "59284-0" }] }], "patient": { "reference": "Patient/123" }, "dateTime": "2026-11-06T10:00:00Z", "provision": { "type": "permit", "period": { "start": "2026-11-06", "end": "2026-12-06" }, "actor": [{ "role": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", "code": "IRCP" }] }, "reference": { "reference": "Practitioner/cardio-42" } }], "purpose": [{ "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason", "code": "TREAT" }], "class": [ { "system": "http://hl7.org/fhir/resource-types", "code": "Observation" }, { "system": "http://hl7.org/fhir/resource-types", "code": "DiagnosticReport" } ] } } 

Read it as: Practitioner cardio-42 may read Observations and DiagnosticReports for treatment, from 6 Nov to 6 Dec.

Revoking is a status change, not a delete

When the patient taps "revoke", set status to inactive and keep the resource. You want the history: who had access, when it started, when it ended. Deleting the Consent destroys the audit trail you will need the first time someone asks "who saw my results in March?"

Enforcement: where it actually gets hard

Storing a Consent resource does nothing on its own. FHIR servers don't enforce consent out of the box. The checks have to live in your access layer, on every read:

  • Check the period on each request, not when the token was issued. A token minted on day 29 of a 30-day consent must stop working on day 31.
  • Filter search results, not just reads. GET /Observation?patient=123 must drop resources whose type isn't in provision.class. This is the leak we see most often: single-resource reads are guarded, searches aren't.
  • Watch _include and _revinclude. A permitted DiagnosticReport can drag in resources the consent doesn't cover. Apply the same filter to included resources.
  • Nested provisions are deny-overrides. If you support "permit everything except X", evaluate the nested deny provision after the outer permit, and let the deny win.

Make it visible to the patient

The technical model is only half of it. Patients need one screen that lists every active connection: who, what, until when, plus a revoke button. If a patient can't see a consent, they didn't meaningfully give it.

Try it

We build Anpheros, a patient-owned health record on FHIR R4 where every app and clinician access goes through a scoped, time-limited consent like the one above. If you want to experiment with the pattern, there's a free FHIR sandbox with synthetic patients at developers.anpheros.com.

How are you handling consent in your health app: checkbox, scopes, or something in between?