Widget Marco · Documentação técnica

Guia de implementação

O widget do Marco é instalado de três formas diferentes, conforme o lugar onde a sua aplicação vive e onde os dados da sessão precisam permanecer. Este guia cobre as três. Escolha o seu fluxo e siga apenas essa coluna: cada uma é autocontida.

Versão de mensagens 1 Produção production.deep-talk.ai Homologação staging.deep-talk.ai

Passo zero

Escolher o fluxo

A pergunta que decide é onde a sessão é criada e o que o navegador recebe. Todo o resto decorre disso.

Fluxo A

Página pública

Sites sem autenticação. Duas tags HTML e nada mais: a sessão começa sozinha. A confiança se apoia na origem do domínio e no appId.

Fluxo B

Página privada

Seu frontend já gerencia usuários autenticados. Você inicia a sessão com init() e uma identidade assinada com HMAC pelo seu backend. Sem endpoint próprio.

Fluxo C

Servidor a servidor

O contexto clínico nunca toca o navegador. Seu backend cria a sessão pela API e o frontend recebe apenas um token opaco de uso único.

Comparação

Página pública Página privada Servidor a servidor
Quem cria a sessão O script, automaticamente Seu frontend, via init() Seu backend, pela API
O que o navegador recebe Apenas o appId user_id, assinatura e metadata Apenas um token opaco
Autenticação Origem + appId Assinatura HMAC-SHA256 Bearer client_secret
Incorporação Script + elemento <marco> Script + API JavaScript <iframe> com o token na URL
Backend necessário Não Só para assinar Sim
Contexto clínico Não se aplica Passa pelo navegador, assinado Nunca sai do servidor
Renderização inline Não, sempre flutuante Sim, via component_id Sim, você controla o iframe
Sessões retomáveis Sim, via localStorage Sim, por user_id/external_id Não, por design

Os estados se escrevem igual nos três fluxos

Os três publicam os nomes de estado em maiúsculo (READY, SESSION_CREATED, STARTED), então um handler escrito para um fluxo pode ser reaproveitado em outro sem normalizar. O que muda entre fluxos é quais estados existem, não como são escritos.

Guia por fluxo

Instalação

A sessão é identificada por origem (domínio) e appId, ambos configurados com o Marco de antemão. O widget é carregado com uma única tag de script e começa sozinho, sem chamar nenhuma API JavaScript.

Quando usar
Landing pages, sites informativos, portais sem login.
Configuração
Vive no backend do Marco, associada ao seu appId.
Renderização
Sempre uma bolha flutuante ancorada à viewport.
Backend próprio
Nenhum é necessário.
Sequência do fluxo entre Navegador, Marco NAVEGADOR MARCO 01 Carrega o widget.js com o app-id na tag <marco> 02 Verifica a origem compara o domínio com a lista do appId 03 SESSION_CREATED ou SESSION_RELOADED se já havia uma no localStorage 04 Conversa STARTED · RESPONSE_CREATED 05 COMPLETED created_at e finished_at
O navegador é o único ator do lado do cliente. Não há backend seu na sequência: a origem do domínio e o appId são toda a verificação.

Integração básica

Adicione estas duas tags à sua página, uma no head e outra no body. É só isso: nenhuma outra chamada é necessária.

html
<html>
  <head>
    <script
      src="https://production.deep-talk.ai/widget/widget.js"
      defer>
    </script>
  </head>
  <body>
    <marco
      id="my-marco-widget"
      api-base-url="https://production.deep-talk.ai/widget"
      app-id="YOUR_APP_ID">
    </marco>
  </body>
</html>

Substitua YOUR_APP_ID pelo identificador que o Marco fornece. Carregar o script é suficiente: o widget aparece automaticamente como bolha flutuante.

A configuração vive no backend do Marco

Cores da marca, comportamento e demais ajustes são configurados uma vez com o seu contato no Marco e ficam associados ao seu appId. Uma mudança é aplicada do lado do Marco e aparece automaticamente na sua página, sem novo deploy. A URL do script também é estática: as correções do produto chegam sozinhas.

Ciclo de vida e persistência

A sessão é criada assim que o widget termina de carregar. Cada navegador mantém uma única conversa contínua, identificada pelo seu próprio session_id.

Identificador anônimo

O widget gera um identificador de sessão aleatório na primeira vez que carrega em um navegador e o guarda no localStorage. Ele não está vinculado a nenhuma identidade real: serve apenas para retomar a conversa naquele mesmo navegador e como identificador de correlação para eventos e auditoria.

Retomada

Recarregar a página, navegar e voltar, ou fechar e reabrir a aba ou o navegador (mesmo perfil): em todos esses casos o widget encontra o identificador guardado e, se a sessão ainda estiver dentro do seu tempo limite de inatividade, retoma a conversa e publica SESSION_RELOADED em vez de SESSION_CREATED.

Tempo limite de inatividade

Uma sessão sem atividade além do limite configurado é encerrada automaticamente. O carregamento seguinte do widget naquele navegador já não encontra sessão para retomar e publica SESSION_CREATED.

Encerramento explícito

Por padrão a sessão só termina por inatividade ou por ação do usuário dentro do widget. Se você precisar encerrá-la de forma programática, use MarcoWidget.finish().

API opcional: MarcoWidget

Para a maioria das integrações, a seção anterior é tudo o que é preciso. Se a sua aplicação precisa reagir a eventos ou encerrar a sessão explicitamente, o script expõe um namespace global opcional, MarcoWidget, em window.

javascript
MarcoWidget.on('READY', function () {
  console.log('Widget Marco pronto');
});

MarcoWidget.on('SESSION_CREATED', function (msg) {
  console.log('Nova sessão:', msg.session_id);
});

// Encerra a sessão e limpa o identificador do localStorage.
// O próximo carregamento inicia uma sessão nova.
MarcoWidget.finish();

MarcoWidget.on() inscreve um callback nos eventos de estado e cuida da verificação de origem para você. Neste fluxo a sessão já está ativa quando o script carrega, então MarcoWidget serve apenas para ouvir eventos e, opcionalmente, encerrar a sessão.

Eventos

O widget publica o estado da sessão com postMessage, emitido do seu iframe para a janela que o contém. MarcoWidget.on() é um wrapper sobre esse mesmo fluxo.

Estado Publicado quando
READY O script terminou de carregar. A sessão ainda está sendo criada.
SESSION_CREATED Uma nova sessão foi criada para este navegador.
SESSION_RELOADED Uma sessão ativa existente foi encontrada e retomada neste navegador.
STARTED O visitante enviou uma consulta e a interação está em andamento.
RESPONSE_CREATED O agente produziu uma nova resposta dentro da sessão ativa.
COMPLETED A sessão terminou normalmente. Inclui created_at e finished_at.
CANCELLED Terminou antes da hora: ação do visitante, finish() ou inatividade.
ERROR A sessão ou a chamada em andamento terminou por uma falha.

Estados terminais

COMPLETED, CANCELLED e ERROR são terminais. Nenhum deles pode ser seguido de mais atividade na mesma sessão, e o próximo carregamento do widget publicará SESSION_CREATED.

Estrutura da mensagem

READY, STARTED, CANCELLED e ERROR compartilham esta estrutura base. session_id está ausente em READY e presente a partir de SESSION_CREATED ou SESSION_RELOADED.

json
{
  "source": "marco-widget",
  "version": 1,
  "type": "STATE_CHANGE",
  "state": "READY",
  "session_id": "sess_9f2a1c",
  "timestamp": "2026-08-20T14:32:04Z"
}

COMPLETED acrescenta dois campos sobre a base: created_at e finished_at.

Erros

Os erros chegam como um evento de estado ERROR, na mesma estrutura acima, com os campos code e message.

Código Causa comum
unauthorized_origin A requisição veio de uma origem fora da lista permitida para este appId.
invalid_app_id O appId não corresponde a nenhuma conta configurada, ou foi omitido.
rate_limited O limite de requisições para este appId ou endereço IP foi excedido.
network_error A requisição ao backend do Marco falhou: conectividade ou timeout.

Segurança

A origem é o sinal de confiança primário deste fluxo. Cada carregamento do widget é comparado com os domínios autorizados para o appId informado, e toda requisição de uma origem fora dessa lista é rejeitada com unauthorized_origin. O Marco também aplica limites de taxa por appId e por endereço IP.

O script e suas chamadas são servidos apenas por HTTPS, e a sua aplicação deve ser servida por HTTPS em todos os ambientes. O widget roda dentro de um iframe em sandbox com permissões mínimas, gerenciado automaticamente pelo script carregador.

Se a sua aplicação aplica uma Content-Security-Policy, autorize o domínio do widget nas três diretivas que governam o carregamento do script, a incorporação do iframe e as chamadas de rede do widget.

http
Content-Security-Policy:
  script-src  https://production.deep-talk.ai;
  frame-src   https://production.deep-talk.ai;
  connect-src 'self' https://production.deep-talk.ai;

Comum aos três fluxos

Tratamento de dados

O Marco não utiliza o conteúdo das conversas nem o metadata das sessões para treinar, ajustar ou melhorar nenhum modelo.

O conteúdo da sessão e os registros de auditoria são retidos por prazos diferentes, porque atendem a propósitos diferentes.

Dados Propósito Retenção
Conteúdo da sessão metadata, transcrição e resumo. Serve à consulta em si. Eliminado dentro de 48 horas após a sessão atingir um estado terminal.
Registros de auditoria Monitoramento de segurança e evidência de conformidade. session_id, external_id quando se aplica, timestamps e estado final, sem conteúdo clínico. 6 anos desde a criação, alinhado ao padrão do setor para registros de acesso em saúde.

session_id é o identificador de correlação nos três fluxos, e vincula os eventos de uma sessão, as entradas de auditoria e o payload de COMPLETED. No fluxo de página privada, external_id o acompanha quando usado. Não existe um ID de correlação independente.

Estabilidade dos códigos de erro

Nos três fluxos, code é um identificador estável e seguro para usar em lógica de negócio; novos códigos podem ser adicionados com o tempo, então inclua sempre um caso padrão. message é para logs e depuração: o seu texto exato pode mudar e não deve ser comparado por padrão.

Comum aos três fluxos

Ambientes

O Marco oferece dois ambientes, com os mesmos caminhos em ambos os hosts.

Ambiente Host
Homologação (staging) staging.deep-talk.ai
Produção production.deep-talk.ai
text
// Página pública e página privada
Script:              https://<host>/widget/widget.js
API base URL:        https://<host>/widget

// Servidor a servidor
Criação de sessão:   POST https://<host>/launch_token
Iniciar chat:        GET  https://<host>/chat?launch_token=...

Isolamento entre ambientes

Cada ambiente tem as suas próprias credenciais e a sua própria lista de origens autorizadas, e não existem rotas entre ambientes para nenhuma delas.

Fluxo Credencial por ambiente
Página pública Um appId próprio. Um appId de homologação não é válido contra o host de produção.
Página privada Um segredo compartilhado próprio. Uma assinatura calculada com o segredo de homologação é rejeitada em produção.
Servidor a servidor Um client_secret próprio. Um launch_token só é válido no ambiente que o emitiu.

Guarde e rotacione as credenciais de cada ambiente separadamente.

Desempenho

As métricas de desempenho e os limiares fixos, incluindo o tempo até o primeiro token e qualquer outra garantia de latência acordada, são definidos no acordo de SLA, um documento independente deste guia.

Comum aos três fluxos

Antes de ir para produção

Antes de ativar qualquer um dos três fluxos, compartilhe o seguinte com o seu contato no Marco.

O que precisamos Para quê Aplica-se a
Origem(ns) onde o widget é incorporado Verificação de origem. É a lista contra a qual cada carregamento ou chamada é comparado. Os três fluxos
Cores de marca primária e secundária Personalizar o tema da interface para combinar com o seu site. Os três fluxos
Duração da sessão Tempo limite de inatividade e duração máxima, se os valores padrão não servirem. Os três fluxos
Formato do objeto metadata em COMPLETED Acordar a saída estruturada que a sua integração precisa receber ao encerrar a sessão. Servidor a servidor

O Marco entrega em troca as credenciais de cada ambiente: o appId no fluxo de página pública, o segredo compartilhado na página privada, e o client_secret junto com o app_id em servidor a servidor.

Dúvidas sobre qual fluxo é o seu?

Escreva para sales@marco.care com uma descrição de onde a sua aplicação vive e quais dados de contexto você precisa passar. Confirmamos o fluxo e entregamos as credenciais de homologação para que você possa testar antes de se comprometer.

Update cookies preferences