Invites

Invite a patient into my care

  • Sandbox: available
  • Staging: available
  • Production: unknown
POST
/v1/invites/care

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

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"  }'

Authorization

bearer
headerAuthorizationBearer <JWT>

Request Body

application/json
  1. body
email*string
Formatemail
Lengthlength <= 254
firstName*string
Length1 <= length <= 200
lastName*string
Length1 <= length <= 200

Response Body

Always { status: "sent" }, whichever case applied.

application/json
  1. response
status*"sent"
Value in"sent"
Example Request
curl -X POST 'https://api.sandbox.ovok.com/v1/invites/care' \  -H 'Content-Type: application/json' \  -d '{  "email": "user@example.com",  "firstName": "string",  "lastName": "string"}'
Example Response
{  "status": "sent"}

Accept a patient's record share POST

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 `invite` and `code` values from the email's accept link as `inviteId` and `code`. `password` is only for a new related person; send `null` (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 `code` 404, whoever calls. - On success the invite's Consent becomes `active` and 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_ENABLED` must not be `false`. - 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_policy` means 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 `codes` stay as the sharer chose them. - **A new address** (`RELATED_PERSON_INVITED`): no token. Send a `password` that meets the password policy; without one the answer is a 422 with `password_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 with `address_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_configured` means the project lost its patient-sharing template; turn patient sharing on again. ## Example ```bash 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: ```bash 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" }' ```

Accept a practitioner's care invite POST

The signed-in patient accepts a practitioner's invite into their care from a `PATIENT_ASSIGNMENT_REQUEST` email. From then on their whole record is shared with the inviting practitioner. **Auth:** bearer token of a Patient. **Scope:** the caller's project (from the token). ## Behaviour - Send the `invite` and `code` values from the email's accept link as `inviteId` and `code`. - Gates: practitioner sharing must be on for the project, and `PATIENT_INVITATION_ENABLED` must not be `false`. - Only the patient the invite names can accept it. The invite is single use and expires 7 days after it was sent. - On success the invite's Consent becomes `active` and a grant for the caller's record is added to the practitioner's membership, in one atomic write. The practitioner's cached sessions are refreshed. - The practitioner gets the access described on `POST /v1/invites/record-share/accept`: the patient's whole compartment, with no delete. - The share lasts until the patient ends it (`DELETE /v1/patient-sharing/shares/{consentId}`). - A 409 with `practitioner_without_access_policy` means the practitioner has full project access, which a share would narrow. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/v1/invites/care/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>" }' ```