Add documents to a patient record
Upload documents to a record and answer access and erasure requests.
ClinicsOnly in clinic workspaces.
POST /clinic/patients/{id}/documents hangs a file off a record and GET /clinic/documents/{id}/content downloads its bytes. Every document carries a date until which it must be kept. Answering the person who asks for their data, or for its erasure, is a legal obligation with deadlines.
Sensitive, and with an extra rule about the bytes
It demands clinic_record:read, or clinic_record:write to write, on top of
the clinic scope. Every read lands in the access log, and a connected app
receives 403 CONNECTED_APP_SENSITIVE_DATA. The file download doesn't go to a
connected app either, even when the clinic has allowed names
(Personal and health data).
What hangs off a record
curl "https://api.vitrinadev.com/api/v1/clinic/patients/$PACIENTE/documents" \
-H "Authorization: Bearer $VITRINA_KEY"{
"data": {
"data": [
{
"id": "99999999-0000-4000-8000-000000000001",
"clinic_patient_id": "12121212-0000-4000-8000-000000000001",
"encounter_id": "44444444-0000-4000-8000-000000000001",
"kind": "imagen",
"title": "Radiografía panorámica",
"mime_type": "application/pdf",
"size_bytes": 182344,
"sensitivity": "phi",
"uploaded_source": "staff",
"retention_until": "2041-09-22",
"purged_at": null,
"purge_reason": null,
"created_at": "2026-09-22T21:53:03.510Z"
}
],
"total": 1,
"page": 1,
"limit": 50
}
}kindsays what it is, and with that its retention deadline:examen,imagen,informe,receta,indicaciones,consentimiento,presupuesto,boleta,certificado,otro.sensitivitysplits the clinical (phi) from the administrative. A receipt and an X-ray share a list without sharing treatment.uploaded_sourcesays who uploaded it:staff, thepatientfrom their own link, anagent, animportor thesystem.retention_untilcomes from the kind and the clinic's policy (Retention).purged_atandpurge_reasonare the tombstone. A deleted document doesn't leave the list: what was there and why it no longer is stays behind.
POST /clinic/documents/{id}/delete removes it before its deadline, and therefore demands a reason.
The patient's rights
Ley 21.719 gives a person the right to take their data with them and to ask for it to be erased. Both are requests with a status: a whole record has to be assembled, and an erasure has to be weighed against the legal deadline.
curl -X POST "https://api.vitrinadev.com/api/v1/clinic/patients/$PACIENTE/export" \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Solicitud de acceso de la paciente, recibida en la recepción el 2026-09-22" }'GET /clinic/privacy-requests lists the requests with their status, and GET /clinic/privacy-requests/{id}/download fetches the archive once the export is ready. The reason is mandatory on both routes: who asked for what and when is part of showing it was answered in time.
Erasure
POST /clinic/patients/{id}/erase requests erasure, and what can go is bounded by the retention floor. What the law requires to be kept isn't deleted because somebody asks. The response says what was deleted and what is kept, with its date.
Events
| Event | When |
|---|---|
clinic_document.uploaded | A document entered a record |
clinic_document.deleted | It was deleted before its deadline, with its reason |
clinic_privacy_request.completed | An export or an erasure is ready |
All three arrive as a notice, with data_omitted: "sensitive". An event never carries the file, nor a link that would hand it over without a credential. It carries the id, and whoever holds the scope downloads it with theirs. That download is logged too.