Accept a patient's record share
- Sandbox: available
- Staging: available
- Production: unknown
Accepts a patient's record share from its email: a practitioner's PRACTITIONER_PATIENT_SHARED offer, or a related person's RELATED_PERSON_INVITED or RELATED_PERSON_RECORD_SHARED invite. From then on the share is in place. The invite decides how it is accepted.
Auth: bearer token of the Practitioner or RelatedPerson the invite names; none for an invite to a new address. Scope: the caller's project (from the token); for a new address, the invite's project.
Behaviour
- Send the
inviteandcodevalues from the email's accept link asinviteIdandcode.passwordis only for a new related person; sendnull(or leave it out) otherwise. - Every invite is single use and expires 7 days after it was sent. A used one answers 409, an expired one 410, and an unknown one or a wrong
code404, whoever calls. - On success the invite's Consent becomes
activeand its grant is added to the recipient's membership, in one atomic write. The recipient's cached sessions are refreshed, so the new access applies on the next request. - The share lasts until the patient ends it (
DELETE /v1/patient-sharing/shares/{consentId}).
A practitioner's offer
- Signed in as the practitioner the offer names; without a token the answer is 401.
- Gates: practitioner sharing must be on for the project, and
PRACTITIONER_INVITATION_ENABLEDmust not befalse. - The share covers the patient's whole compartment. Observations, Communications, DocumentReferences, QuestionnaireResponses, ServiceRequests, Tasks and Appointments can be read, searched, created and updated; CommunicationRequests, Goals, CarePlans, Flags, EpisodeOfCare and DeviceUseStatements are read-only; the Patient can be read, searched and updated. Nothing can be deleted.
- A 409 with
practitioner_without_access_policymeans the caller has full project access, which a share would narrow. - The answer is the practitioner share:
consentId,sharer,practitioner,startedAt,endsAt.
A related person's invite
- Gate: patient sharing must be on for the invite's project.
- The share covers the sharer's Observations with the invite's codes (read and search), and the sharer's Patient resource with contact details, identifiers and most other fields hidden.
- A share also covers a multi-value reading's group Observation when it covers every value the group repeats (systolic and diastolic for blood pressure, the waveform for an ECG, any part of an SpO2 or urine-strip reading), so the whole reading can be read and nothing more. The share's
codesstay as the sharer chose them. - A new address (
RELATED_PERSON_INVITED): no token. Send apasswordthat meets the password policy; without one the answer is a 422 withpassword_required. In one atomic write under the address's account lock, the account is made: a User scoped to the project, a RelatedPerson of the sharer, and a membership holding the built-in related-person base policy (read and search of its own RelatedPerson only, created the first time it is needed) and the share's grant. If the address has any account by now, nothing is written and the answer is a 409 withaddress_has_account. Sign in afterwards with the address and that password. - A related person of the project (
RELATED_PERSON_RECORD_SHARED): signed in as the related person the invite names; without a token the answer is 401, as another related person or in another project 404. The grant is added to their membership, keeping its base policy. - The answer is the related-person share:
consentId,sharer,relatedPerson,codes,startedAt,endsAt. - A 409 with
sharing_not_configuredmeans the project lost its patient-sharing template; turn patient sharing on again.
Example
curl -X POST 'https://api.sandbox.ovok.com/v1/invites/record-share/accept' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk' \ -H 'Content-Type: application/json' \ -d '{ "inviteId": "c3499c27-2973-0a7f-807e-fb8676a92dcb", "code": "<code from the accept link>", "password": null }'A new related person, without a token:
curl -X POST 'https://api.sandbox.ovok.com/v1/invites/record-share/accept' \ -H 'Content-Type: application/json' \ -d '{ "inviteId": "c3499c27-2973-0a7f-807e-fb8676a92dcb", "code": "<code from the accept link>", "password": "Ex4mple-Passw0rd" }'bearerAuthorizationBearer <JWT>application/json- body
inviteId*stringuuidcode*string16 <= length <= 128password?string12 <= length <= 128nullThe share that started: a practitioner share, or a related-person share with its codes.
application/json- response
consentId*stringsharer*practitioner*startedAt*stringendsAt*stringcurl -X POST 'https://api.sandbox.ovok.com/v1/invites/record-share/accept' \ -H 'Content-Type: application/json' \ -d '{ "inviteId": "14ca54c2-5d85-4c93-81b5-495a2e7e0ca4", "code": "stringstringstri"}'{ "consentId": "string", "sharer": { "patientId": "string", "name": "string" }, "practitioner": { "practitionerId": "string", "name": "string" }, "startedAt": "string", "endsAt": "string"}Share my record POST
The signed-in patient shares their record by email, with a practitioner or a related person (a carer): - `"recipient": "practitioner"` shares the whole record. A new address gets a practitioner account that already holds the share; a practitioner of the project gets an offer to accept. - `"recipient": "related-person"` shares only the Observation `codes` named in the body, and optionally the patient's MedicationStatements and MedicationAdministrations when `includeMedications` is `true`. The patient record's contact fields stay hidden. Either way the address gets an invite to accept; a new address makes its related-person account when it accepts. Any other `recipient` is a 422 naming `recipient`. **Auth:** bearer token of a Patient. **Scope:** the caller's project (from the token). ## Behaviour ### Practitioner - **Gates**, checked before the address is looked up, in this order: - practitioner sharing (`practitionerSharingEnabled` on `PUT /v1/patient-sharing/settings`) is on; it is off by default; - `PRACTITIONER_INVITATION_ENABLED` is not `false`; - the project has a practitioner app URL; - the project has a default practitioner access policy (`DEFAULT_PRACTITIONER_ACCESS_POLICY`, else `CLINICIAN_INVITE_ACCESS_POLICY`); - the patient has fewer than 20 pending offers. - **What happens, by address:** - No User has the address: a practitioner account of the project is created with the default practitioner access policy and the patient's share on its membership, in one atomic write. The address gets a `PRACTITIONER_INVITED_BY_PATIENT` email with a set-password link on the practitioner app. - The address belongs to exactly one active practitioner of the project: a pending offer is created and the address gets a `PRACTITIONER_PATIENT_SHARED` email with an accept link, `<practitioner app URL>/accept-invite?invite=<inviteId>&code=<code>`, valid for 7 days. The share starts only when that practitioner, signed in, posts both values to `POST /v1/invites/record-share/accept`. - The record is already shared with that practitioner: nothing is sent, unless their account has no password yet, in which case the set-password email goes out again. - Anything else (a User that is not a practitioner of this project, or a practitioner with full project access): nothing is written or sent. - Each email is sent as the last step of the write. Map the email templates named above in the project's email configuration first. - Do not enable practitioner sharing in projects whose practitioners use the carehub dashboard: its route guard checks resource types only, so a practitioner who only holds shared patients could see project-wide data there. - A 409 with `invitation_not_configured` means the project has no default practitioner access policy. It needs project configuration, not a retry. - A 429 means the patient already has 20 pending offers. ### Related person - **Body:** `email`, `firstName`, `lastName`, `codes` (1 to 100 Observation codes, each letters, digits, `.` and `-` only), and optional `includeMedications` (defaults to `false`). - **Gates**, checked before the address is looked up, in this order: - patient sharing (`enabled` on `PUT /v1/patient-sharing/settings`) is on; it is off by default; - `RELATED_PERSON_INVITATION_ENABLED` is not `false` (403 `Invitation is not enabled for this project.`, as for a practitioner); - the project has a patient app URL; - the patient has fewer than 20 pending related-person invites. - **What happens, by address:** - No User has the address: a pending share is created and the address gets a `RELATED_PERSON_INVITED` email with an accept link, `<patient app URL>/accept-invite?invite=<inviteId>&code=<code>`, valid for 7 days. Nothing else is created yet: the account is made when the link is accepted (`POST /v1/invites/record-share/accept` with a `password`). - The address belongs to exactly one active related person of the project: a pending share is created and the address gets a `RELATED_PERSON_RECORD_SHARED` email with the same kind of link. The share starts when that related person, signed in, accepts it. - Anything else (a patient, a practitioner, or a User that is not a related person of this project): nothing is written or sent. - The pending share is a `draft` Consent holding only a hash of the one-time code. It grants nothing until it is accepted. - `RELATED_PERSON_INVITED` and `RELATED_PERSON_RECORD_SHARED` carry `firstName`, `lastName`, `sharerName` (the patient's name), `invitationUrl` (the accept link) and `baseUrl`. A project whose email configuration maps neither sends `PATIENT_INVITE` and `PATIENT_ASSIGNMENT_REQUEST` instead, with `inviterName` set to the patient's name. - A 429 means the patient already has 20 pending related-person invites. ### Both - The answer is always `202 { "status": "sent" }`, whichever case applied, so it does not reveal whether the address has an account. If the email cannot be sent, everything the invite wrote is undone, and the answer is still 202. - A 409 with `app_url_not_configured` means the project has no app URL for the recipient: the practitioner app, or the patient app for a related person. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/v1/invites/record-share' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk' \ -H 'Content-Type: application/json' \ -d '{ "recipient": "practitioner", "email": "max.mustermann@example.com", "firstName": "Max", "lastName": "Mustermann" }' ``` ```bash curl -X POST 'https://api.sandbox.ovok.com/v1/invites/record-share' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk' \ -H 'Content-Type: application/json' \ -d '{ "recipient": "related-person", "email": "max.mustermann@example.com", "firstName": "Max", "lastName": "Mustermann", "codes": ["8480-6", "8462-4"], "includeMedications": true }' ```
Invite a patient into my care POST
A signed-in practitioner invites a patient into their care, by email. A new address gets a patient account whose record is already shared with the inviter; a patient of the project gets an invite to accept. **Auth:** bearer token of a Practitioner. **Scope:** the caller's project (from the token). ## Behaviour - **Gates**, checked before the address is looked up, in this order: - practitioner sharing (`practitionerSharingEnabled` on `PUT /v1/patient-sharing/settings`) is on; it is off by default; - `PATIENT_INVITATION_ENABLED` is not `false`; - the project has a patient app URL; - the project has a default patient access policy; - the inviter's membership has an access policy (a membership with full project access is refused, because a share would narrow it); - the inviter has fewer than 20 pending invites. - **What happens, by address:** - No User has the address: a patient account of the project is created with the default patient access policy, and its record is shared with the inviter, in one atomic write. The address gets a `PATIENT_INVITE` email with a set-password link on the patient app. - The address belongs to exactly one active patient of the project: a pending invite is created and the address gets a `PATIENT_ASSIGNMENT_REQUEST` email with an accept link, `<patient app URL>/accept-invite?invite=<inviteId>&code=<code>`, valid for 7 days. The share starts only when that patient, signed in, posts both values to `POST /v1/invites/care/accept`. - The patient already shares their record with the inviter: nothing is sent, unless their account has no password yet, in which case the set-password email goes out again. - Anything else (a User that is not a patient of this project): nothing is written or sent. - The answer is always `202 { "status": "sent" }`, whichever case applied, so it does not reveal whether the address has an account. If the email cannot be sent, everything the invite wrote is undone, and the answer is still 202. - Each email is sent as the last step of the write. Map the email templates named above in the project's email configuration first. - Do not enable practitioner sharing in projects whose practitioners use the carehub dashboard: its route guard checks resource types only, so a practitioner who only holds shared patients could see project-wide data there. - A 409 with `app_url_not_configured` means the project has no patient app URL; `invitation_not_configured` means it has no default patient access policy; `practitioner_without_access_policy` means the inviter has full project access. None of these is fixed by retrying. - A 429 means the practitioner already has 20 pending invites. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/v1/invites/care' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk' \ -H 'Content-Type: application/json' \ -d '{ "email": "max.mustermann@example.com", "firstName": "Max", "lastName": "Mustermann" }' ```