Share readings with a carer
Let a signed-in patient share chosen readings with a carer by email, how the carer accepts and gets an account, and what the carer can then read.
A signed-in patient shares chosen readings with a carer, such as a family member, by email. The carer reads only the Observation codes the patient picks, plus the patient's name. In FHIR a carer is a RelatedPerson.
| Step | Method | Path | Who |
|---|---|---|---|
| 1. Invite | POST | /v1/invites/record-share with "recipient": "related-person" | A patient |
| 2. Accept | POST | /v1/invites/record-share/accept | The carer: without a token for a new address, signed in otherwise |
Unlike a practitioner share, every carer invite must be accepted, and a new address gets its account at that moment. A carer account cannot be made any other way. See Carers for signing in and what a carer can do.
What the project needs
Every row must hold before the address is looked up.
| Requirement | Detail |
|---|---|
| Patient sharing on | enabled, set with PUT /v1/patient-sharing/settings. Off by default. This is the patient-to-patient switch, not practitionerSharingEnabled. |
| Carer invitations on | RELATED_PERSON_INVITATION_ENABLED must not be false. It also gates step 2. |
| A patient app URL | PATIENT_APP_URL. Carers use the patient app, so the link is built on it. The request's Origin is never used. |
| Fewer than 20 pending carer invites | Per patient. |
| Two email templates mapped | RELATED_PERSON_INVITED and RELATED_PERSON_RECORD_SHARED. If neither is mapped, Ovok sends PATIENT_INVITE and PATIENT_ASSIGNMENT_REQUEST instead. |
No default AccessPolicy is needed. Ovok creates the carer's built-in policy the first time one is needed.
Step 1: Invite
curl --request POST \
--url 'https://api.sandbox.ovok.com/v1/invites/record-share' \
--header "Authorization: Bearer ${PATIENT_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{
"recipient": "related-person",
"email": "sam@example.com",
"firstName": "Sam",
"lastName": "Doe",
"codes": ["8480-6", "8462-4"]
}'| Body field | Required | Description |
|---|---|---|
recipient | Yes | related-person. |
email | Yes | A valid address, up to 254 characters. Ovok lowercases it. |
firstName | Yes | 1 to 200 characters. Used when the carer's account is created. |
lastName | Yes | 1 to 200 characters. |
codes | Yes | 1 to 100 Observation codes to share, each made of letters, digits, . and -. The example shares systolic and diastolic blood pressure (LOINC 8480-6, 8462-4). |
The answer is always 202 Accepted with { "status": "sent" }, whatever the address turned out to be.
What happens, by address
| The address… | What Ovok does |
|---|---|
| Has no account | Creates a pending invite and emails RELATED_PERSON_INVITED with an accept link. No account yet: it is made when the carer accepts. |
| Belongs to exactly one carer of the project | Creates a pending invite and emails RELATED_PERSON_RECORD_SHARED with an accept link. The share starts when the carer, signed in, accepts it. |
| Anything else | Writes and sends nothing. For example a patient or a practitioner of the project. One address cannot be both a patient and a carer. |
The pending invite holds only a hash of the one-time code and grants nothing until it is accepted. The link is <patient app URL>/accept-invite?invite=<inviteId>&code=<code>, and it works for 7 days.
Step 2: Accept
Your patient app serves /accept-invite. It reads invite and code from the link and posts them. How depends on whether the carer already has an account.
A new carer: choose a password, no token
curl --request POST \
--url 'https://api.sandbox.ovok.com/v1/invites/record-share/accept' \
--header 'Content-Type: application/json' \
--data '{
"inviteId": "8c1e5a52-6f0b-4d9e-9a41-0b2f7c3d9e10",
"code": "<code from the link>",
"password": "<the password the carer chose>"
}'Holding the code proves the address is theirs, so no token is needed. In one write, Ovok creates the carer's user, a RelatedPerson linked to the patient, and a membership with the share. The carer then signs in with the address and that password. The answer contains no tokens.
An existing carer: signed in
curl --request POST \
--url 'https://api.sandbox.ovok.com/v1/invites/record-share/accept' \
--header "Authorization: Bearer ${CARER_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{"inviteId":"8c1e5a52-6f0b-4d9e-9a41-0b2f7c3d9e10","code":"<code from the link>","password":null}'The new share is added to the carer's account, next to any shares from other patients.
| Body field | Description |
|---|---|
inviteId | The invite value from the link. A UUID. |
code | The code value from the link, 16 to 128 characters. |
password | The new carer's password, which must meet the password policy. null, or left out, for anyone who already has an account. |
Which form to show
The link looks the same in both emails. To choose the screen, post the link's values with no token and "password": null:
| Answer | Show |
|---|---|
422 with error password_required | A "choose a password" form, then post again with password. |
401 | A sign-in form for the carer, then post again with their token. |
The code is checked first, so a wrong or used code answers 404, 409 or 410 before either of these.
The answer
On success the answer is 200 with the share:
| Field | Example | Meaning |
|---|---|---|
consentId | … | Id the patient uses to end the share. |
sharer.patientId | … | Patient whose readings are shared. |
sharer.name | Jane Doe | Patient's display name. |
relatedPerson.relatedPersonId | … | The carer's RelatedPerson id. |
relatedPerson.name | Sam Doe | Carer's display name. |
codes | ["8480-6", "8462-4"] | The shared Observation codes. |
startedAt | 2026-10-22T18:30:00.000Z | Time the share began. |
endsAt | null | No scheduled end time. |
The change applies on the carer's next request.
What the carer can read
| Resource | Access |
|---|---|
| The patient's Observations with a shared code | Read and search |
The patient's Patient resource | Read and search, with identifier, telecom, gender, birthDate, address, photo, contact, communication, generalPractitioner, managingOrganization, extensions, narrative and the other personal fields hidden. The name stays visible. |
The carer's own RelatedPerson | Read and search |
Nothing else, and nothing can be written or deleted. Another code, another patient's data, or any other resource answers 403 or 404 (an empty search). See Carers.
End a share
The patient ends a carer share, or cancels a pending invite, with DELETE /v1/patient-sharing/shares/:consentId. Access stops at once. The patient lists their carer shares in relatedPersons of GET /v1/patient-sharing/shares. A carer cannot list or leave shares yet.
What can go wrong
Invite
| Status | Message or error | Cause |
|---|---|---|
401 | The token is missing or invalid. | |
403 | Only patients can share their record. | The caller is not a patient. |
403 | Sharing is not enabled for this project. | Patient sharing is off. |
403 | Invitation is not enabled for this project. | RELATED_PERSON_INVITATION_ENABLED is false. |
409 | code app_url_not_configured | No patient app URL. Fix the configuration; retrying will not help. |
409 | Another write holds the address, or the records kept changing. Retry. | |
422 | A list of path and message | A field is missing or invalid: recipient is neither practitioner nor related-person, or codes is missing, empty, longer than 100 or holds a malformed code. |
429 | The patient already has 20 pending carer invites. |
Accept
| Status | Message or error | Cause |
|---|---|---|
401 | Sign in as the related person this invite is for. | No token for an invite to an existing carer. Also, with no message, when the token is invalid. |
403 | Invitation is not enabled for this project. | RELATED_PERSON_INVITATION_ENABLED is false, even for an invite sent while it was on. |
403 | Sharing is not enabled for this project. | Patient sharing is off. |
403 | Only the related person this invite is for can accept it. | The caller is signed in, but not as a carer, for an invite to an existing carer. |
404 | No live invite has this inviteId, the code does not match, the invite names another carer, or it belongs to another project than the caller's. | |
409 | The invite was already used, or the records kept changing. | |
409 | error address_has_account | A new carer's address got an account after the invite was sent, for example as a patient. Nothing was written. Ask the patient for a new invite to another address. |
409 | error sharing_not_configured | The project lost its patient-sharing AccessPolicy. An admin turns patient sharing on again. |
409 | error related_person_without_access_policy | The carer's membership has no AccessPolicy, so a share would narrow its access. |
410 | The invite expired. | |
422 | error password_required | The invite creates an account and password is null. |
422 | A list of path and message | inviteId is not a UUID, code is not 16 to 128 characters, or password fails the password policy. |
Gotchas
- Patient sharing gates this, not practitioner sharing. A project with only
practitionerSharingEnabledon answers403. Turnenabledon. - A new carer has no account until they accept. Until then, a reset or sign-in for that address finds nothing.
- One address, one kind of account. An address that belongs to a patient or practitioner of the project is ignored on invite and refused on accept with
address_has_account. 202says nothing about the outcome. It is the same answer whatever the address was. Tell the patient "if the address can receive it, an invitation is on its way".- A failed email is silent. If the message cannot be sent, the invite is undone and the answer is still
202. Map the templates first. - Turning invitations off also blocks pending invites. With
RELATED_PERSON_INVITATION_ENABLEDoff, accepting answers403and no account is made. - Carer accounts belong to one project. A carer of two projects has two accounts, one per tenant.
Related
- Carers: sign-in, password reset, and what a carer can do
- Invitations
- Share a record with a practitioner, the same route with
recipient: "practitioner" - RELATED_PERSON_INVITATION_ENABLED
- PATIENT_SHARING_ENABLED
Last updated on