Skip to main content

Visão Geral de Telemedicina

Gerencia as salas de videochamada (LiveKit) usadas nas consultas online: criação/busca de sala, geração de token de acesso, notificação do paciente via WebSocket, gravação e transcrição.

Autenticação necessária

Todas as rotas exigem o header Authorization: Bearer {accessToken} (JWT do Auth0) ou x-api-key. Veja Autenticação.

Nenhuma rota exige permissão específica

Diferente da maioria dos outros módulos, nenhum endpoint de telemedicina usa @CheckPermissions — qualquer usuário autenticado (com qualquer permissão) pode chamar qualquer rota deste módulo, incluindo criar/encerrar salas e ativar gravação.


Base

https://api-dev.imagemais.com.br/api/telemedicine

Rotas

MétodoRotaDescrição
GET/telemedicine/room/{consultationId}Busca a sala LiveKit já criada para a consulta
POST/telemedicine/tokenGera um token LiveKit para o usuário atual entrar numa sala
POST/telemedicine/roomCria a sala da consulta (ou retorna a existente)
POST/telemedicine/notifyNotifica o paciente (via WebSocket) que a sala está pronta
DELETE/telemedicine/deleteEncerra a sala e finaliza a consulta
POST/telemedicine/activate-recordingInicia a gravação (áudio) da sala
GET/telemedicine/transcriptionBusca a transcrição salva da consulta
GET/telemedicine/transcription-preferenceVerifica se a transcrição está habilitada para a consulta
PATCH/telemedicine/transcription-preferenceHabilita/desabilita a transcrição da consulta
GET/telemedicine/recording-presigned-urlGera URL assinada para baixar um arquivo de gravação

Fluxo típico de uma teleconsulta

  1. Médico chama POST /telemedicine/room para criar a sala (idempotente — se já existe, retorna a mesma).
  2. Médico chama POST /telemedicine/notify — isso busca/gera um token para o paciente e emite telemedicine.room.ready via WebSocket (gateway de pacientes) com o token. Exige que a sala já exista (passo 1).
  3. Médico e paciente entram na sala usando POST /telemedicine/token (gera o token de cada lado) + SDK do LiveKit no client.
  4. Com participantes conectados, o frontend chama POST /telemedicine/activate-recording para começar a gravar (requer feature flag habilitada e a flag LIVEKIT_ENABLE_RECORDING).
  5. Ao final, DELETE /telemedicine/delete encerra a sala no LiveKit, finaliza a consulta (consultationStatus = FINAL) e para qualquer gravação em andamento.
Identificação dos participantes no LiveKit

O médico entra com identity = user-{userId} e o paciente com identity = patient-{patientId}. O nome de sala segue o padrão telemedicine-{consultationId}-{consultation.createdAt em ms}.


Notificação ao paciente (WebSocket)

POST /telemedicine/notify não empurra nada por HTTP para o paciente — ele emite eventos internos que o PatientGateway (Socket.io, ver Gateways) repassa para a sala WS do paciente:

Evento internoEvento WebSocket (para o paciente)Payload
patient.room.ready (emitido por notify)telemedicine.room.ready{ token, timestamp }
patient.room.closed (emitido por delete)telemedicine.room.closed
Falha silenciosa se o paciente não estiver conectado por WS

Se o paciente não tiver uma conexão WebSocket ativa (sem "room hash" registrado no gateway), o evento simplesmente não é enviado — só um warn no log do servidor. A resposta HTTP de POST /telemedicine/notify continua { "success": true } mesmo assim, então a API não tem como saber (por essa rota) se o paciente foi de fato avisado.


Gravação

Gravação é somente áudio (audioOnly: true, formato OGG), feita via LiveKit Egress e enviada direto para o Cloudflare R2. Dois egresses são iniciados em paralelo:

  • Room composite: uma faixa combinada de toda a sala, salva em telemedicine/{sha256(consultationId)}/{room_name}.
  • Por participante: uma faixa de áudio individual por participante conectado, salva em telemedicine/{sha256(consultationId)}/tracks/{participantName}-{time}.

O consultationId é hasheado (SHA-256) no path do arquivo — não aparece em texto puro no storage.


Transcrição

A transcrição em si (texto) é gerada fora deste módulo e fica salva no campo telemedicineTranscription da consulta — GET /telemedicine/transcription só lê esse campo. A "preferência" de transcrição é um flag independente, guardado no Redis (chave telemedicine:transcription:disabled:{consultationId}, sem TTL), que controla se a geração de transcrição deve rodar para aquela consulta.

transcription-preference não valida a conta (multi-tenant)

GET e PATCH /telemedicine/transcription-preference não verificam se a consulta existe nem se pertence à accountId do token — qualquer usuário autenticado de qualquer conta pode ler ou alterar a preferência de transcrição de um consultationId de outra conta, só adivinhando o número. As demais rotas do módulo (transcription, room, notify, recording-presigned-url etc.) fazem essa checagem corretamente via findConsultation.