VitrinaAPI

Registrar la atención de un paciente

Abrir atenciones, firmar evoluciones y leer los antecedentes de un paciente.

ClínicasSolo en los workspaces de clínicas.

La ficha clínica cuenta qué se le hizo a una persona y por qué. Ahí viven la atención, sus evoluciones, los antecedentes, las alertas, las fichas de ingreso y el odontograma. Es dato de salud del artículo 2 g) de la Ley 21.719, con régimen propio en el 16 bis. El contrato aquí es más estrecho.

Tres reglas de acceso

  1. Todo pide clinic_record:read —o clinic_record:write para escribir— además del permiso de clínica. clinic:read no alcanza.
  2. Ninguna aplicación conectada llega: 403 CONNECTED_APP_SENSITIVE_DATA, con nombres de pacientes permitidos o sin ellos.
  3. Cada lectura queda registrada, en la misma transacción que la respuesta. Una lectura que no puede escribir su registro de acceso falla.

La atención y sus evoluciones

Una atención (encounter) es una visita: quién atendió, dónde y cuándo. Las evoluciones cuelgan de ella.

curl "https://api.vitrinadev.com/api/v1/clinic/patients/$PACIENTE/encounters" \
  -H "Authorization: Bearer $VITRINA_KEY"
{
  "data": {
    "data": [
      {
        "id": "44444444-0000-4000-8000-000000000001",
        "clinic_patient_id": "12121212-0000-4000-8000-000000000001",
        "appointment_id": null,
        "professional_id": "ffffffff-0000-4000-8000-000000000001",
        "location_id": "b1b1b1b1-0000-4000-8000-000000000002",
        "kind": "consulta",
        "status": "closed",
        "starts_at": "2026-09-15T21:52:49.352Z",
        "closed_at": "2026-09-15T22:32:49.352Z",
        "notes": [
          {
            "id": "55555555-0000-4000-8000-000000000001",
            "kind": "evolucion",
            "body": "Control de ortodoncia. Se ajusta arco superior.",
            "author_user_id": null,
            "author": {
              "kind": "api_key",
              "id": "c1c1c1c1-0000-4000-8000-000000000001",
              "name": "Ficha clínica (migración)"
            },
            "signed_at": "2026-09-15T22:27:49.352Z",
            "amends_note_id": null
          }
        ]
      }
    ]
  }
}

POST /clinic/patients/{id}/encounters abre una atención y POST /clinic/encounters/{id}/close la cierra. El cierre es idempotente: cerrar dos veces responde lo mismo.

Quién escribió cada línea

author_user_id, y opened_by_user_id en la atención, es el miembro que escribió y nadie más; con una API key viene null. author distingue las tres formas de escribir en una ficha:

  • una persona en el panel: author_user_id con su id y author en null;
  • una API key del workspace: author con la llave y el nombre que tenía entonces, porque revocarla no puede reescribir quién firmó una ficha;
  • una persona a través de una credencial: su id, y author.via con el token personal o la aplicación por la que entró, «Camila vía Claude».

Un relato clínico se escribe una vez y las correcciones son filas nuevas: un autor mal anotado ya no se arregla.

Firmar, y por qué no se puede editar después

Una evolución se escribe con POST /clinic/encounters/{id}/notes. Mientras está sin firmar se corrige en su lugar con PATCH /clinic/notes/{id}. POST /clinic/notes/{id}/sign la firma, y desde ese momento el texto no se toca nunca más.

Corregir una evolución firmada es POST /clinic/notes/{id}/amend, y eso crea una fila nueva que apunta a la anterior con amends_note_id y lleva su motivo. La original se queda donde estaba: la ficha tiene que decir qué se sabía cuando se decidió.

Antecedentes y alertas

GET /clinic/patients/{id}/antecedentes responde las dos cosas juntas, porque quien atiende necesita las dos:

{
  "data": {
    "antecedentes": [],
    "flags": [
      {
        "id": "13131313-0000-4000-8000-000000000001",
        "kind": "alergia",
        "label": "Alergia a penicilina",
        "detail": null,
        "severity": "severa",
        "shown_on_agenda": true,
        "recorded_source": "staff",
        "resolved_at": null
      }
    ]
  }
}

Un antecedente es historia: una enfermedad de base, una cirugía, un medicamento. No se borra ni se edita: se supersede con POST /clinic/antecedentes/{id}/supersede, que deja el anterior visible con su fecha.

Una alerta (flag) es algo que hay que ver ahora. shown_on_agenda: true es la que la clínica decidió pintar sobre la cita. POST /clinic/patients/{id}/flags la levanta y POST /clinic/flags/{id}/resolve la baja con motivo.

GET /clinic/record/agenda-flags responde las alertas de una página entera de pacientes, lo que la agenda necesita para dibujarlas sin una llamada por cita. Es una operación de ficha: pide clinic_record:read y está marcada como sensible. Por eso mismo, el flags que la agenda incluye en cada cita no llega nunca a una aplicación conectada, ni vacío ni con nada (Agenda).

Fichas de ingreso

Una ficha de ingreso es un formulario que el paciente responde antes de una cita. Sus preguntas no son sensibles y están en Plantillas y conservación. Lo que una persona respondió sí lo es.

  • POST /clinic/patients/{id}/forms abre una ficha contra la versión viva de la plantilla y la congela ahí. Si mañana cambian las preguntas, esta ficha sigue diciendo contra cuáles se respondió.
  • PATCH /clinic/forms/{id} guarda respuestas mientras está sin terminar y POST /clinic/forms/{id}/submit las cierra. Después sólo queda POST /clinic/forms/{id}/amend, que crea una respuesta nueva con su motivo.
  • POST /clinic/forms/{id}/link emite el enlace con token que el paciente abre en su teléfono.
  • GET /clinic/forms/pending es «Fichas pendientes», lo que se debe antes de una cita próxima, y GET /clinic/forms/requirements responde si esa cita se puede confirmar.

El odontograma y sus hallazgos

GET /clinic/patients/{id}/charts lista las fichas gráficas de un paciente y GET /clinic/patients/{id}/charts/{kind} devuelve una, con sus hallazgos y su vocabulario. Guardar el dibujo (POST …/charts/{kind}/versions) crea una versión, y las anteriores siguen en GET /clinic/charts/{chartId}/versions.

Un hallazgo se registra con POST /clinic/charts/{chartId}/findings, se marca tratado con resolve y se deshace con reopen. GET /clinic/chart-findings/{findingId}/plan-item dice en qué línea de presupuesto se convertiría, al precio de hoy (Presupuestos y caja).

Quién miró esta ficha

GET /clinic/patients/{id}/record-events devuelve el registro de accesos de una ficha, y GET /clinic/patients/{id}/record-events/export lo mismo en CSV. Además del permiso de ficha piden clinic_admin:write: quién miró una ficha lo revisa la administración.

Cada línea trae el actor, la ruta y la fecha. Así se ve la de una API key de la clínica:

{
  "route": "GET /clinic/patients/:id/antecedentes",
  "actor_kind": "api_key",
  "actor_id": "aaaa1111-0000-4000-8000-000000000015",
  "action": "view",
  "entity": "clinic_record",
  "at": "2026-09-22T22:00:27.764Z"
}

La exportación en CSV no sale a una aplicación conectada

Ni esta ni ninguna otra. En una clínica, una respuesta exportada, transmitida o binaria se le responde a una aplicación conectada con 403 CONNECTED_APP_SENSITIVE_DATA, con nombres permitidos o sin ellos.

Eventos

EventoCuándo
clinic_encounter.opened · .closedSe abrió o se cerró una atención
clinic_note.signedSe firmó una evolución; desde ahí es inmutable
clinic_note.amendedSe corrigió una firmada, con una fila nueva y su motivo

Los tres llegan como aviso, con data_omitted: "sensitive", aunque la suscripción pida los datos del recurso. El cuerpo de una evolución no viaja en un webhook. El aviso trae el id y la url; quien tenga el permiso la lee con su credencial.

En esta página