Share a record with a practitioner
A signed-in patient shares their whole record with a practitioner, by email. If the address is new, Ovok creates a practitioner account that already holds the share. If it belongs to a practitioner of the project, that practitioner receives an offer to accept.
| Step | Method | Path | Who |
|---|
| 1. Invite | POST | /v1/invites/practitioner | A patient |
| 2. Accept (existing practitioners only) | POST | /v1/invites/practitioner/accept | The invited practitioner |
What the project needs
Every row must hold before the address is even looked up.
Step 1: Invite
curl --request POST \
--url 'https://api.sandbox.ovok.com/v1/invites/practitioner' \
--header "Authorization: Bearer ${PATIENT_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{"email":"dr.smith@example.com","firstName":"Alex","lastName":"Smith"}'
| Body field | Required | Description |
|---|
email | Yes | A valid address, up to 254 characters. Ovok lowercases it. |
firstName | Yes | 1 to 200 characters. Used when a new account is created. |
lastName | Yes | 1 to 200 characters. |
The answer is always 202 Accepted, with the same response for every address outcome below:
What happens, by address
| The address… | What Ovok does |
|---|
| Has no account | Creates a practitioner of the project with the default practitioner AccessPolicy and the patient's share, in one write, and emails a set-password link (PRACTITIONER_INVITED_BY_PATIENT). |
| Belongs to exactly one active practitioner of the project | Creates a pending offer and emails an accept link (PRACTITIONER_PATIENT_SHARED), valid for 7 days. The share starts only when step 2 succeeds. |
| Already holds this patient's share | Sends nothing, unless their account still has no password, in which case the set-password email goes out again. |
| Anything else | Writes and sends nothing. For example an account that is not a practitioner of this project, or a practitioner with full project access. |
Step 2: Accept
The practitioner opens the link <practitioner app URL>/accept-invite?invite=<inviteId>&code=<code> in your app, signs in, and your app posts both values:
curl --request POST \
--url 'https://api.sandbox.ovok.com/v1/invites/practitioner/accept' \
--header "Authorization: Bearer ${PRACTITIONER_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{"inviteId":"8c1e5a52-6f0b-4d9e-9a41-0b2f7c3d9e10","code":"<code from the link>"}'
| Body field | Description |
|---|
inviteId | The invite value from the link. A UUID. |
code | The code value from the link, 16 to 128 characters. |
On success the answer is 200 with the share:
| Field | Example | Meaning |
|---|
consentId | … | Id used to end the share later. |
sharer.patientId | … | Patient whose record is shared. |
sharer.name | Jane Doe | Patient's display name. |
practitioner.practitionerId | … | Practitioner receiving access. |
practitioner.name | Dr. Alex Smith | Practitioner's display name. |
startedAt | 2026-10-06T08:15:00.000Z | Time the share began. |
endsAt | null | No scheduled end time. |
The practitioner now has access to the patient's whole record: they can read, search, create and update Observations, Communications, DocumentReferences, QuestionnaireResponses, ServiceRequests, Tasks and Appointments; read CommunicationRequests, Goals, CarePlans, Flags, EpisodeOfCare and DeviceUseStatements; and read, search and update the Patient. Nothing can be deleted. The change applies on the practitioner's next request.
What can go wrong
Invite
| Status | Message or error | Cause |
|---|
401 | | The token is missing or invalid. |
403 | Only patients can invite practitioners. | The caller is not a patient. |
403 | | Practitioner sharing is off, or PRACTITIONER_INVITATION_ENABLED is false. |
409 | code app_url_not_configured | No practitioner app URL. Fix the configuration; retrying will not help. |
409 | error invitation_not_configured | No default practitioner AccessPolicy. |
409 | | Another write holds the address, or the records kept changing. Retry. |
429 | | The patient already has 20 pending offers. |
422 | A list of path and message | A field is missing or invalid. |
Accept
| Status | Message or error | Cause |
|---|
401 | | The token is missing or invalid. |
403 | Practitioner sharing is not enabled for this project. | Sharing is off. Checked before the caller's role. |
403 | | PRACTITIONER_INVITATION_ENABLED is false, or the caller is not a practitioner. |
404 | | No live offer has this inviteId, the code does not match, the offer names another practitioner, or the caller has no practitioner membership in the project. |
409 | | The offer was already used, the patient is no longer a member, or the records kept changing. |
409 | error practitioner_without_access_policy | The practitioner has full project access, which a share would narrow. |
410 | | The offer expired. |
422 | A list of path and message | inviteId is not a UUID, or code is shorter than 16 characters. |
Gotchas
202 says nothing about the outcome. It is the same answer whether the address was new, existing, already shared, or ignored, so it cannot be used to learn which emails have accounts. Tell the patient "if they have an account, they will be emailed".
- A failed email is silent. If the message cannot be sent, everything the invitation wrote is undone and the answer is still
202. Map the two templates first.
- Practitioners with full project access can never receive a share. A project admin with no AccessPolicy is ignored on invite and refused at accept with
practitioner_without_access_policy. Give people who should receive shares a limited AccessPolicy.
- An offer is single use and lasts 7 days. A second accept answers
409.
- Sharing is off until an admin turns it on. Check it first when every call answers
403.
- The share covers the whole record. Unlike patient-to-patient sharing, there is no list of codes to choose.
- The patient ends it. The share lasts until the patient ends it with
DELETE /v1/patient-sharing/shares/:consentId.
- Your app must serve the link. The email points at your practitioner app's
/accept-invite and /setpassword paths.