VitrinaAPI

Firmar y revocar un consentimiento

Redactar la plantilla, pedir la firma y revocarla contra el texto exacto.

ClínicasSolo en los workspaces de clínicas.

Un consentimiento informado tiene dos mitades con reglas opuestas. La plantilla es el texto que la clínica redacta. No nombra a ningún paciente, se versiona como código y cualquier integración con permiso de configuración puede mantenerla. El consentimiento es lo que una persona concreta firmó, contra qué versión exacta, cuándo y para qué. Eso es dato de salud, pide su propio permiso y ninguna aplicación conectada lo alcanza.

Este capítulo cubre las dos, en ese orden: primero lo que es de todos, después lo que es de alguien.

Plantillas

Una plantilla de consentimiento tiene versiones y sólo una está viva. Se edita el borrador y se publica. Publicar congela ese texto para siempre: los consentimientos firmados contra él siguen apuntando a esa versión aunque mañana se redacte otra.

curl -X POST https://api.vitrinadev.com/api/v1/clinic/consent-templates \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Consentimiento de ortodoncia",
    "description": "Tratamiento de ortodoncia fija: alcance, riesgos y duración estimada.",
    "signature_methods": ["tablet", "public_link"],
    "body_html": "<p>Autorizo el tratamiento de ortodoncia fija descrito por el profesional tratante…</p>",
    "allows_photos": true,
    "allows_marketing_use": false
  }'

El ciclo es siempre el mismo. POST …/{id}/draft guarda el borrador, POST …/{id}/publish lo pone vivo, POST …/{id}/versions empieza la siguiente a partir de la viva y POST …/{id}/retire la retira sin tocar lo ya firmado. signature_methods acota cómo se puede firmar, en un tablet de la recepción o por un enlace que el paciente abre. allows_photos y allows_marketing_use son las dos cláusulas que habilitan cosas distintas más abajo.

Plantillas de ficha

Las fichas de ingreso funcionan igual, en /clinic/form-templates, con schema en vez de body_html. Tampoco son sensibles, por la misma razón: una pregunta no es la respuesta de nadie. Lo que una persona respondió está en Ficha clínica.

Conservación

GET /clinic/retention dice cuántos años se guarda cada tipo de documento, y PUT /clinic/retention lo cambia para uno:

{
  "data": {
    "data": [
      { "kind": "examen", "retention_years": 15, "legal_minimum_years": 15, "is_default": true },
      { "kind": "boleta", "retention_years": 6, "legal_minimum_years": 6, "is_default": true }
    ]
  }
}

legal_minimum_years es el piso y no se puede bajar: la clínica puede decidir guardar más, nunca menos. Es el número que manda cuando alguien pide que le borren la ficha (Documentos de la ficha).

Las plantillas no son sensibles

No nombran a ningún paciente y no escriben en el registro de accesos a la ficha. Una integración puede mantener los textos sin acceso a las fichas, y una aplicación conectada sí las lee.

Consentimientos firmados

Desde aquí, todo es sensible

Pide clinic_record:read, o clinic_record:write para escribir, además del permiso de clínica. Cada lectura queda en el registro de accesos de la ficha, y una aplicación conectada recibe 403 CONNECTED_APP_SENSITIVE_DATA tenga los permisos que tenga (Datos personales y de salud).

Pedir un consentimiento lo crea pending y lo clava a la versión viva de la plantilla en ese instante:

curl -X POST "https://api.vitrinadev.com/api/v1/clinic/patients/$PACIENTE/consents" \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "template_id": "66666666-0000-4000-8000-000000000001", "encounter_id": "44444444-0000-4000-8000-000000000001" }'

Desde ahí hay dos caminos. POST /clinic/consents/{id}/link emite el enlace con token que el paciente abre y firma por su cuenta. POST /clinic/consents/{id}/sign lo firma en la recepción, asistido por alguien de la clínica. Así queda uno firmado:

{
  "data": {
    "id": "77777777-0000-4000-8000-000000000001",
    "template_id": "66666666-0000-4000-8000-000000000001",
    "template_version_id": "88888888-0000-4000-8000-000000000001",
    "template_version": 1,
    "clinic_patient_id": "12121212-0000-4000-8000-000000000001",
    "encounter_id": "44444444-0000-4000-8000-000000000001",
    "status": "signed",
    "signed_by_name": "María José Fuentes Lagos",
    "signed_by_document": "12.345.678-5",
    "signed_by_role": "titular",
    "signature_method": "tablet",
    "signed_at": "2026-09-15T21:53:03.507Z",
    "photo_consent": true,
    "marketing_use_consent": false,
    "revoked_at": null,
    "expires_at": null
  }
}

Lo que conviene saber de cada campo:

  • template_version_id y template_version son el punto entero de esta ruta. Un consentimiento vale por el texto que la persona leyó, y GET /clinic/consents/{id} devuelve ese texto, no el vigente hoy.
  • signed_by_role dice quién firmó: el propio paciente (titular) o quien responde por él, del vínculo de familia (Registro de pacientes).
  • photo_consent y marketing_use_consent son dos permisos distintos. El primero habilita la galería clínica; el segundo, usar esas imágenes fuera de la ficha. Firmar el tratamiento no firma ninguno de los dos.
  • expires_at caduca el consentimiento solo, sin que nadie tenga que acordarse.

GET /clinic/consents los lista de toda la clínica, firmados, pendientes y revocados, filtrables por estado. GET /clinic/patients/{id}/consents devuelve los de una persona.

Revocar

POST /clinic/consents/{id}/revoke lo revoca con un motivo obligatorio. No es un borrado: la fila se queda, con revoked_at y el motivo. Hace falta poder decir que en tal fecha había consentimiento y desde tal otra no. Lo que la revocación sí hace es cerrar lo que ese consentimiento habilitaba.

La galería clínica

Las imágenes de antes y después cuelgan del paciente y sólo entran con consentimiento. POST /clinic/patients/{id}/photos falla si la persona no tiene un consentimiento firmado y vigente cuya plantilla declare allows_photos.

Cada imagen lleva su zone, su phase (before / after), la fecha en que se tomó y un pair_id que une el antes con el después. GET /clinic/patients/{id}/photos las devuelve agrupadas por zona y fecha. Borrar una es POST /clinic/photos/{id}/delete con motivo, y deja lápida: qué había y por qué ya no está.

Eventos

EventoCuándo
clinic_consent.signedSe firmó; trae la versión contra la que se firmó
clinic_consent.revokedSe revocó, con su motivo

Los dos llegan como aviso, con data_omitted: "sensitive": el texto firmado y el nombre de quien firmó no viajan en un webhook. El aviso alcanza para reaccionar, cerrar un flujo o avisar a la recepción, y quien tenga el permiso lee el detalle con su credencial.

El consentimiento renderizado queda colgado de la ficha como un documento más, con su plazo de conservación, en Documentos de la ficha.

En esta página