# Share my record

Canonical page: https://docs.ovok.com/api/invites/share-my-record

`POST /v1/invites/record-share`

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