Integração via iFrame

Guia completo para incorporar a plataforma LeoRad em sua aplicação web usando iFrame, com suporte a comunicação bidirecional em tempo real.

Recomendado para Web

#1. Visão Geral

Este guia tem como objetivo orientar, de forma clara e objetiva, a integração da plataforma LeoRad com aplicações web de terceiros.

A plataforma LeoRad (app.leorad.com.br) foi desenvolvida para analisar, processar e interagir com laudos radiológicos por meio de assistentes de inteligência artificial treinados especificamente para o domínio da radiologia.

Seu principal propósito é permitir que o radiologista concentre-se na análise das imagens, reduzindo o tempo gasto na documentação dos exames e aumentando a eficiência do fluxo de trabalho.

O LeoRad oferece diferentes formas de integração com aplicações externas. Este guia detalha a integração via iFrame — indicada para sistemas web — que permite incorporar a plataforma diretamente na interface do seu sistema, com suporte a comunicação bidirecional em tempo real via postMessage.

#2. Autenticação: Entendendo o Token

Cada usuário da aplicação precisa de um token de acesso exclusivo para utilizar a plataforma LeoRad. Esse token é necessário para autenticar e identificar o usuário em todas as chamadas à aplicação.

Como obter o token

Fornecido pela equipe LeoRad
Disponibilizado sob demanda pela equipe de suporte técnico da LeoRad.
Gerado pelo Painel Administrativo
Acessível para usuários com permissão de administrador na plataforma.
Revogado e recriado pelo próprio usuário
O usuário pode revogar e recriar seu token diretamente na interface do aplicativo.

#3. Acessando a Aplicação Web

Para acessar a aplicação web do LeoRad, é utilizado um endpoint HTTPS formado pela URL base da aplicação concatenada ao token do usuário:

url
https://app.leorad.com.br/<TOKEN>
Substitua <TOKEN> pelo token exclusivo do usuário. Cada usuário possui um token individual e intransferível.
O token deve ser mantido em segredo. Caso seja comprometido, o token deve ser revogado e recriado.
Importante: O token é exclusivo para cada usuário e não pode ser compartilhado com outros usuários.

#4. Parâmetros Opcionais

É possível utilizar parâmetros de query string para personalizar a experiência do usuário diretamente pelo endpoint. Os parâmetros são opcionais e podem ser combinados conforme necessário:

url
https://app.leorad.com.br/<TOKEN>?part=XXX&mod=YYY&ind=ZZZ&med=WWW&sex=F&age=45&age-unit=years&prior=Urgente&contrast=true
ParâmetroDescriçãoExemplo
ind ou
indication
Permite enviar a indicação clínica do caso. O conteúdo será automaticamente inserido no campo de prompt do LeoRad, sem necessidade de digitação manual pelo radiologista. Também aceito com o nome indication.ind=Dor+abdominal
part ou
body-part
Aplica um filtro automático nas máscaras e autotextos do usuário, segmentando por parte do corpo examinada. Também aceito com o nome body-part.part=abdome
mod ou
model
Carrega um modelo ou template HTML diretamente no editor. O conteúdo deste parâmetro deve estar codificado com URL encoding (encodeURIComponent). Também aceito com o nome model.mod=%3Ch1%3ETemplate%3C%2Fh1%3E
modzIdêntico ao parâmetro mod, com a diferença de que o conteúdo deve ser compactado com a biblioteca lz-string (usando decompressFromEncodedURIComponent) antes de ser inserido na URL. Indicado para templates de grande tamanho. Veja o exemplo de uso da biblioteca lz-string abaixo.modz=...
mea ou
measures
Permite enviar medidas do exame como contexto para a criação do laudo. O conteúdo deste parâmetro deve estar codificado com URL encoding (encodeURIComponent). Também aceito com os nomes measures e mea.mea=Rim+direito%3A+10cm
meazIdêntico ao parâmetro mea, com a diferença de que o conteúdo deve ser compactado com a biblioteca lz-string (usando decompressFromEncodedURIComponent) antes de ser inserido na URL. Indicado para conteúdos com muitas medidas. Veja o exemplo de uso da biblioteca lz-string abaixo.meaz=...
sexSexo do paciente. Reconhece M (masculino), F (feminino) e O (outro), exibidos por extenso no idioma do usuário. Qualquer outro valor é exibido exatamente como foi enviado.sex=F
ageIdade do paciente. Combine com age-unit para que a idade apareça por extenso; sozinho, o número é exibido como veio.age=45
age-unitUnidade da idade: years, months ou days. Não aparece como item próprio — completa o valor de age (ex.: "45 anos").age-unit=years
priorPrioridade do estudo. Texto livre, exibido exatamente como foi enviado.prior=Urgente
cont ou
contrast
Uso de contraste. Os valores true e false são exibidos como "Sim" e "Não"; qualquer outro valor é exibido como veio. Também aceito com o nome cont.cont=true
cont-det ou
contrast-details
Detalhes do uso de contraste. Não aparece como item próprio — completa o valor de contrast (ex.: "Sim — 10ml de gadolínio"). Também aceito com o nome cont-det.cont-det=10ml+de+gadol%C3%ADnio
prev-examExames pregressos do paciente. Texto livre, exibido exatamente como foi enviado. O conteúdo deve estar codificado com URL encoding (encodeURIComponent).prev-exam=TC+de+abdome+em+2024
prev-reportLaudo anterior do paciente, útil como contexto para comparação. Texto livre, exibido exatamente como foi enviado. O conteúdo deve estar codificado com URL encoding (encodeURIComponent).prev-report=F%C3%ADgado+de+dimens%C3%B5es+normais...
Certifique-se de codificar corretamente o conteúdo dos parâmetros mod, modz, mea e meaz antes de incluí-los na URL. Utilize encodeURIComponent() no JavaScript ou o equivalente na linguagem do seu backend.

Parâmetros personalizados

A lista acima não é um limite: qualquer chave e valor enviados na query string são aceitos e preservados. Chaves fora da tabela são exibidas ao radiologista com o próprio nome da chave como rótulo, o que permite levar dados do seu sistema — número do acesso, modalidade, equipamento — sem precisar de uma nova versão da integração.

url
https://app.leorad.com.br/<TOKEN>?accessionNumber=ACC-99123&modality=US&equipamento=GE+Logiq+E10

Como os parâmetros chegam ao radiologista

Tudo o que for enviado aparece no painel Parâmetros, no cabeçalho da aplicação. Cada item tem uma caixa de seleção: marcada, o conteúdo é inserido na caixa de mensagem; desmarcada, o conteúdo é retirado — sem alterar o que o radiologista já digitou ou ditou.

ind já chega marcado, então a indicação clínica continua sendo inserida sozinha, como sempre foi. part, além de filtrar máscaras e autotextos, também é inserido automaticamente quando o usuário não desativou a importação automática. Os demais parâmetros ficam disponíveis e são inseridos apenas quando o radiologista marca.

Exemplo de uso da biblioteca lz-string (parâmetros modz e meaz)

javascript
import LZString from "lz-string";

// Conteúdo original (template HTML ou medidas)
const template = "<h1>Laudo de Ultrassonografia</h1><p>Normal</p>";
const medidas = "Rim direito: 10,5cm | Rim esquerdo: 11cm";

// Compactar com lz-string
const modz = LZString.compressToEncodedURIComponent(template);
const meaz = LZString.compressToEncodedURIComponent(medidas);

// Montar a URL final
const url = `https://app.leorad.com.br/${token}?modz=${modz}&meaz=${meaz}`;
Instale a biblioteca com npm install lz-string ou yarn add lz-string. No lado do LeoRad, o conteúdo será descompactado automaticamente com LZString.decompressFromEncodedURIComponent().

#5. Integração via iFrame e Comunicação Bidirecional

A aplicação LeoRad pode ser incorporada em qualquer sistema web por meio de um <iframe>, permitindo uma integração transparente e rápida com sua interface existente.

O LeoRad utiliza a API window.postMessage para comunicação entre a aplicação pai (parent) e o iframe, possibilitando a troca de dados em tempo real e o controle da aplicação incorporada.

Código de incorporação

html
<iframe
  allow="clipboard-write; microphone; fullscreen; encrypted-media"
  src="https://app.leorad.com.br/<TOKEN>"
  width="100%"
  height="100%"
  style="border: none;"
></iframe>

Instruções de integração

  1. 1Substitua <TOKEN> pelo token exclusivo do usuário autenticado em sua aplicação.
  2. 2Os parâmetros opcionais part, mod e ind podem ser incluídos diretamente na URL do atributo src.
  3. 3Ajuste os atributos width e height conforme necessário para se adaptar ao layout do seu sistema.
  4. 4Personalize o estilo do iframe (bordas, sombras, arredondamento) para que ele se integre harmoniosamente à interface da sua aplicação.

Eventos postMessage disponíveis

O LeoRad suporta os seguintes eventos para comunicação bidirecional entre a aplicação pai e o iframe:

EventoDireçãoDescrição
setContentparent → iframeDefine o conteúdo HTML no editor do iFrame, substituindo completamente o conteúdo existente.
insertContentparent → iframeInsere conteúdo na posição atual do cursor no editor do iFrame, sem substituir o conteúdo existente.
getContentparent → iframeSolicita o conteúdo HTML atual do editor. Aceita o campo finish para sinalizar a finalização do laudo e acionar fluxos na aplicação pai.
setMeasuresparent → iframeEnvia para o LeoRad medidas para serem utilizadas na criação do laudo.
setBodyPartparent → iframeEnvia a parte do corpo examinada — mesmo efeito do parâmetro de URL part (filtro de máscaras/autotextos e importação automática).
setSexparent → iframeEnvia o sexo do paciente. Reconhece M, F e O, exibidos por extenso no idioma do usuário.
setAgeparent → iframeEnvia a idade do paciente. Aceita um valor simples (data: '45') ou um objeto { age, "age-unit" } com a unidade (years, months ou days).
setPriorityparent → iframeEnvia a prioridade do estudo (parâmetro prior). Texto livre.
setContrastparent → iframeEnvia o uso de contraste. Aceita um valor simples (data: 'true') ou um objeto { contrast, "contrast-details" } com os detalhes.
setPrevExamparent → iframeEnvia os exames pregressos do paciente (parâmetro prev-exam).
setPrevReportparent → iframeEnvia o laudo anterior do paciente (parâmetro prev-report). Conteúdo em HTML é convertido para texto puro.
setCommandparent → iframeExecuta um comando customizado. As frases aceitas dependem do idioma definido pela preferência do usuário.
loadediframe → parentEmitido pelo iFrame para indicar que a aplicação LeoRad terminou de carregar e está pronta para receber interações.

Commands disponíveis

Para o evento setCommand, os comandos aceitos incluem:

Exemplos de comandos
Inicia ditado por IA (turbo).
Pausa ditado IA.
Retoma ditado IA.
Para ditado IA.
Inicia ditado convencional (realtime).
Para ditado convencional.
Inicia assistente de voz.
Pausa assistente.
Retoma assistente.
Para assistente.
Exporta/finaliza o laudo (copia ou envia ao parent).
Copia o laudo para o clipboard.
Cola conteúdo do clipboard no editor.
Recorta o laudo (copia + limpa editor).
Apaga o conteúdo do editor.
Busca autotexto/máscara pelo nome falado e insere no editor.

Como usar via postMessage

O campo data enviado no evento setCommand deve ser o texto da frase/comando. O handleCommand faz o match por frase, não pelo nome técnico do comando.

javascript
const iframe = document.querySelector('iframe');
const LEORAD_ORIGIN = 'https://app.leorad.com.br';

// Define o conteúdo HTML no editor (substitui o conteúdo atual)
iframe.contentWindow.postMessage(
  { action: 'setContent', data: '<p>Conteúdo do laudo</p>' },
  LEORAD_ORIGIN
);

// Solicita o conteúdo atual do editor
iframe.contentWindow.postMessage(
  { action: 'getContent' },
  LEORAD_ORIGIN
);

// Envia medidas para contexto do laudo
iframe.contentWindow.postMessage(
  { action: 'setMeasures', data: 'Rim direito: 10 cm; Rim esquerdo: 10,5 cm' },
  LEORAD_ORIGIN
);

// Demais parâmetros de contexto (mesmo destino dos parâmetros de URL):
// setBodyPart, setSex, setAge, setPriority, setContrast, setPrevExam, setPrevReport
iframe.contentWindow.postMessage(
  { action: 'setBodyPart', data: 'USG Abdome Total' },
  LEORAD_ORIGIN
);

// setAge aceita a unidade junto ('age-unit' é opcional; valor solto também vale)
iframe.contentWindow.postMessage(
  { action: 'setAge', data: { age: '45', 'age-unit': 'years' } },
  LEORAD_ORIGIN
);

// setContrast aceita os detalhes junto ('contrast-details' é opcional)
iframe.contentWindow.postMessage(
  { action: 'setContrast', data: { contrast: 'true', 'contrast-details': '10 ml de gadolínio' } },
  LEORAD_ORIGIN
);

// Executa comando customizado por frase/comando textual
iframe.contentWindow.postMessage(
  { action: 'setCommand', data: 'Iniciar assistente' },
  LEORAD_ORIGIN
);

#5.1 Como emitir eventos para o iFrame LeoRad

Para enviar mensagens da sua aplicação ao iFrame do LeoRad, utilize o método postMessage na referência ao elemento iframe:

javascript
const iframe = document.querySelector('iframe');
const LEORAD_ORIGIN = 'https://app.leorad.com.br';

// Define o conteúdo HTML no editor (substitui o conteúdo atual)
iframe.contentWindow.postMessage(
  { action: 'setContent', data: '<p>Conteúdo do laudo</p>' },
  LEORAD_ORIGIN
);

// Insere conteúdo na posição atual do cursor
iframe.contentWindow.postMessage(
  { action: 'insertContent', data: 'Texto a ser inserido' },
  LEORAD_ORIGIN
);

// Solicita o conteúdo atual do editor
iframe.contentWindow.postMessage(
  { action: 'getContent' },
  LEORAD_ORIGIN
);

// Solicita o conteúdo e sinaliza finalização do laudo
iframe.contentWindow.postMessage(
  { action: 'getContent', finish: true },
  LEORAD_ORIGIN
);
Sempre especifique a origem de destino ('https://app.leorad.com.br') como segundo argumento do postMessage em vez de usar '*'. Isso garante que a mensagem seja entregue exclusivamente ao domínio correto.

#5.2 Como receber eventos do iFrame LeoRad

Quando o radiologista finalizar o laudo, o conteúdo será automaticamente enviado para a aplicação pai via postMessage. Outros eventos, como o carregamento inicial do iFrame, também podem ser capturados por meio de um event listener no window:

javascript
window.addEventListener('message', function(event) {
  // IMPORTANTE: sempre valide a origem da mensagem antes de processá-la
  if (event.origin !== 'https://app.leorad.com.br') return;

  const { action, data } = event.data || {};

  switch (action) {
    case 'loaded':
      // O iFrame do LeoRad terminou de carregar e está pronto
      console.log('LeoRad carregado com sucesso');
      break;

    case 'getContent':
      // Conteúdo do editor retornado em formato HTML
      console.log('Conteúdo do laudo:', data);
      // Processe o conteúdo conforme a necessidade da sua aplicação
      break;

    default:
      console.log('Evento recebido:', action, data);
  }
}, false);

#6. Segurança

Sempre valide a origem das mensagens. Verifique o campo event.origin antes de processar qualquer mensagem recebida. Isso garante que a comunicação ocorra exclusivamente com domínios confiáveis e evita a execução de scripts maliciosos.

Allowlist de origens (aplicações parent)

Para garantir maior segurança na integração, a equipe LeoRad solicita que você forneça a lista de URLs (origens) das aplicações que irão incorporar o iFrame. Essas URLs serão configuradas em uma lista de permissões (allowlist), restringindo o carregamento do conteúdo exclusivamente aos domínios autorizados.

Essa medida protege contra acessos não autorizados e garante a integridade da comunicação entre o iFrame e a aplicação integradora.

Exemplos de origens a serem fornecidas

texto
https://app.suaempresa.com.br
https://radiologia.xyz.com
Para cadastrar suas URLs na allowlist, entre em contato com nossa equipe pelo e-mail suporte@leorad.com.br.

#7. Exemplo Funcional

O exemplo a seguir demonstra uma integração completa em HTML e JavaScript puro, pronta para ser adaptada ao seu ambiente de desenvolvimento ou utilizada como ponto de partida para testes.

html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Integração LeoRad via iFrame</title>
  <style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body { font-family: sans-serif; display: flex; flex-direction: column; height: 100vh; }
    header { padding: 12px 16px; background: #111827; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
    button {
      padding: 8px 16px; border-radius: 6px; border: none;
      background: #ef4444; color: white; cursor: pointer;
      font-size: 13px; font-weight: 500;
    }
    button:hover { background: #dc2626; }
    #leorad { flex: 1; border: none; width: 100%; }
  </style>
</head>
<body>
  <header>
    <button onclick="setContent()">Definir Conteúdo</button>
    <button onclick="insertContent()">Inserir Conteúdo</button>
    <button onclick="getContent()">Obter Conteúdo</button>
    <button onclick="setMeasures()">setMeasures</button>
    <button onclick="setBodyPart()">setBodyPart</button>
    <button onclick="setSex()">setSex</button>
    <button onclick="setAge()">setAge</button>
    <button onclick="setPriority()">setPriority</button>
    <button onclick="setContrast()">setContrast</button>
    <button onclick="setPrevExam()">setPrevExam</button>
    <button onclick="setPrevReport()">setPrevReport</button>
  </header>

  <iframe
    id="leorad"
    allow="clipboard-write; microphone; fullscreen; encrypted-media"
    src="https://app.leorad.com.br/<TOKEN>"
  ></iframe>

  <script>
    const iframe = document.getElementById('leorad');
    const LEORAD_ORIGIN = 'https://app.leorad.com.br';

    function send(payload) {
      iframe.contentWindow.postMessage(payload, LEORAD_ORIGIN);
    }

    function setContent() {
      send({ action: 'setContent', data: '<p>Laudo de exemplo inserido via integração.</p>' });
    }

    function insertContent() {
      send({ action: 'insertContent', data: 'Texto inserido na posição do cursor.' });
    }

    function getContent() {
      send({ action: 'getContent' });
    }

    function setMeasures() {
      send({ action: 'setMeasures', data: 'Rim direito: 10 cm; Rim esquerdo: 10,5 cm' });
    }

    function setBodyPart() {
      send({ action: 'setBodyPart', data: 'USG Abdome Total' });
    }

    function setSex() {
      // Valores conhecidos: 'M', 'F', 'O' (outros passam como texto cru)
      send({ action: 'setSex', data: 'F' });
    }

    function setAge() {
      // 'age-unit' é opcional ('years', 'months', 'days'); também aceita só o valor: data: '45'
      send({ action: 'setAge', data: { age: '45', 'age-unit': 'years' } });
    }

    function setPriority() {
      send({ action: 'setPriority', data: 'Urgente' });
    }

    function setContrast() {
      // 'contrast-details' é opcional; também aceita só o valor: data: 'true'
      send({
        action: 'setContrast',
        data: { contrast: 'true', 'contrast-details': '10 ml de gadolínio' },
      });
    }

    function setPrevExam() {
      send({ action: 'setPrevExam', data: 'USG Abdome Total — 12/03/2025' });
    }

    function setPrevReport() {
      send({
        action: 'setPrevReport',
        data: '<p>Fígado de dimensões normais, contornos regulares. Vesícula biliar sem cálculos.</p>',
      });
    }

    window.addEventListener('message', function(event) {
      if (event.origin !== LEORAD_ORIGIN) return;

      const { action, data } = event.data || {};

      if (action === 'loaded') {
        console.log('LeoRad carregado e pronto para uso.');
      } else if (action === 'getContent') {
        console.log('Conteúdo do laudo recebido:', data);
        alert('Laudo recebido com sucesso! Verifique o console para visualizar o conteúdo.');
      }
    }, false);
  </script>
</body>
</html>

Precisa de ajuda?

Em caso de dúvidas, sugestões ou problemas técnicos relacionados à integração, entre em contato com nossa equipe de suporte.

contato@leorad.com.br