top of page

Exemplos de Códigos

Nesta seção, forneceremos exemplos práticos de código para orientar os desenvolvedores em sua integração inicial com nossas APIs, oferecendo implementações claras e concisas para acelerar o processo de integração e simplificar a adoção da API.

Introdução

Bem-vindo à documentação de integração com a API WaveLight.

Nossa documentação fornece um exemplo simples de código em JavaScript (JS), projetado para facilitar a integração com a API WaveLight. Fornecemos implementações detalhadas para atender às diversas necessidades dos desenvolvedores.

 

Nosso objetivo é simplificar a implementação de APIs em diferentes ambientes, garantindo flexibilidade e compatibilidade. Nosso guia fornece instruções claras e exemplos práticos para uma integração eficiente.

Aqui você aprenderá como:

 

  1. Criar um Service Request (pedido de análise)

  2. Fazer o Upload de um vídeo para análise

  3. Obter os Resultados em tempo real via SSE (Server-Sent Events)

Visão Geral

O fluxo de integração segue 3 passos principais:

[1] Service Request  ---> retorna requestId + uploadUrl
          |
          v
[2] Upload do Vídeo ---> envia o vídeo para uploadUrl
          |
          v
[3] SSE Results -----> conecta usando requestId e recebe os resultados em tempo real

1. Service Request Response

A Solicitação de Serviço é o ponto de partida.

Aqui você informa à API quais serviços deseja executar:

 

  • Pulso → wc_pr-avg_sk_beta

  • Saturação de oxigênio → wc_o2-avg_sk_beta

  • Pressão Arterial → wc_bp-neural_sk_beta

 

Notas importantes:

 

  • Se você solicitar aferição de pressão arterial, deverá fornecer dados do paciente (idade, sexo, altura, peso).

  • Para outros serviços, esses valores podem ser omitidos.

Exemplo de Requisição

POST https://api.wavelighthealth.com/gateway/service-request
Headers:
  Content-Type: application/json
  x-api-key: SUA_CHAVE_API

Body:
{
  "serviceList": ["wc_pr-avg_sk_beta", "wc_o2-avg_sk_beta"],
  "WPG_Object": {
    "header": { "content-type": "", "version": "", "hash": "", "secure": true },
    "study": { "created": "2025-09-16T13:36:28.872Z" },
    "patient": {
      "anonymous": [
        { "label": "age", "unit": "years" },
        { "label": "sex", "unit": "enum", "value": "UNDEFINED" },
        { "label": "height", "unit": "cm" },
        { "label": "weight", "unit": "kg" }
      ]
    }
  }
}

Exemplo de Resposta

{
  "requestId": "12345-abcde",
  "uploadVideoUrl": "https://upload-url-gerada-pela-api.com/xyz",
  "status": "PENDING"
}

2. Video Upload Status

Após o Service Request, você deve enviar o vídeo para a URL retornada  (uploadVideoUrl). 

Exemplo de Upload (JavaScript)

await fetch(uploadUrl, {
  method: "PUT",
  headers: { "Content-Type": "application/octet-stream" },
  body: selectedVideoFile
});

Resposta Esperada

{
  "status": 200,
  "statusText": "OK",
  "videoSize": "12.5 MB",
  "uploadUrl": "https://upload-url-gerada-pela-api.com/xyz",
  "timestamp": "2025-09-16T14:00:00.000Z"
}

3. Real-time Results (SSE)

A API envia os resultados em tempo real via SSE (Server-Sent Events).

Como funciona:

  • Você conecta ao endpoint:  /gateway/sse-request-track/{requestId} 

  • A API envia eventos até o processamento ser concluído.

Tipos de Eventos

  •  PARTIAL_PROGRESS  → resultados parciais

  •  SUCCESS  → resultados finais

Exemplo de Resultado Final

{
  "event": "status",
  "data": "SUCCESS",
  "results": [
    { "name": "HEART BEATS", "return": "[{\"label\": \"PR-AVG\", \"value\": [72]}]" },
    { "name": "OXIMETRY", "return": "[{\"label\": \"Oximetry\", \"value\": [98]}]" }
  ]
}

Exemplo Completo (Dados Fixos)

Este exemplo inclui Pulso, Saturação e Pressão Arterial.

Usamos dados fictícios de paciente fixos no código apenas para demonstração:

  • Idade = 45

  • Sexo = Masculino

  • Altura = 172 cm

  • Peso = 85 kg

Atenção: Em produção, esses valores devem ser coletados do usuário real ou de um prontuário eletrônico.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>WaveLight API Test</title>
  <script src="https://unpkg.com/event-source-polyfill@1.0.31/src/eventsource.min.js"></script>
</head>
<body>
  <h1>WaveLight API Demo</h1>

  <!-- Botões de controle -->
  <input type="file" id="videoInput" accept="video/*" style="display: none;" />
  <button onclick="document.getElementById('videoInput').click()">Selecionar Vídeo</button>
  <button id="startButton" onclick="runFullProcess()">Iniciar</button>

  <!-- Áreas de resultado -->
  <h3>1. Service Request Response</h3>
  <pre id="serviceResponse">Waiting...</pre>

  <h3>2. Video Upload Status</h3>
  <pre id="uploadStatus">Waiting...</pre>

  <h3>3. Real-time Results (SSE)</h3>
  <pre id="sseResults">Waiting...</pre>

  <script>
    // Configuração da API
    const API_URL = "https://api.wavelighthealth.com";
    const API_KEY = "SUA_CHAVE_API_AQUI="; // substitua pela sua chave real

    let eventSource = null;
    let selectedVideoFile = null;

    // Seleção de arquivo
    document.getElementById("videoInput").addEventListener("change", (e) => {
      selectedVideoFile = e.target.files[0];
      if (selectedVideoFile) {
        const sizeInMB = (selectedVideoFile.size / 1024 / 1024).toFixed(2);
        document.getElementById("uploadStatus").textContent =
          `Vídeo selecionado: ${selectedVideoFile.name} (${sizeInMB} MB)`;
      }
    });

    // Função principal: roda o processo completo
    async function runFullProcess() {
      if (!selectedVideoFile) {
        alert("Selecione um vídeo antes de iniciar!");
        return;
      }

      const button = document.getElementById("startButton");
      button.disabled = true;

      // Limpa resultados anteriores
      document.getElementById("serviceResponse").textContent = "Processando...";
      document.getElementById("uploadStatus").textContent = "Aguardando upload...";
      document.getElementById("sseResults").textContent = "Aguardando resultados...";

      try {
        // 1. Criar Service Request
        const serviceResponse = await makeServiceRequest();
        document.getElementById("serviceResponse").textContent =
          JSON.stringify(serviceResponse, null, 2);

        // 2. Fazer upload do vídeo
        await uploadVideo(serviceResponse);

        // 3. Escutar resultados em tempo real (SSE)
        listenToSSE(serviceResponse);

      } catch (error) {
        console.error("Erro no processo:", error);
        document.getElementById("uploadStatus").textContent = `Erro: ${error.message}`;
        button.disabled = false;
      }
    }

    // === 1. Service Request ===
    async function makeServiceRequest() {
      const createdDate = new Date().toISOString();

      const requestBody = {
        serviceList: [
          "wc_pr-avg_sk_beta",     // Pulso
          "wc_o2-avg_sk_beta",     // Saturação
          "wc_bp-neural_sk_beta"   // Pressão Arterial
        ],
        WPG_Object: {
          header: { "content-type": "", version: "", hash: "", secure: true },
          study: {
            created: createdDate,
            source: {
              device: { model: navigator.userAgent, features: [] },
              institution: "Wavelight",
              application: "WaveLight API Demo"
            }
          },
          // ⚠️ IMPORTANTE:
          // Neste exemplo os dados do paciente estão FIXOS para demonstração.
          // Em uma aplicação real, esses valores devem vir de um formulário
          // ou integração com prontuário eletrônico.
          patient: {
            anonymous: [
              { label: "age", unit: "years", value: 45 },
              { label: "sex", unit: "enum", value: "MALE" },
              { label: "height", unit: "cm", value: 172 },
              { label: "weight", unit: "kg", value: 85 }
            ]
          }
        }
      };

      const response = await fetch(`${API_URL}/gateway/service-request`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-api-key": API_KEY
        },
        body: JSON.stringify(requestBody)
      });

      if (!response.ok) {
        throw new Error(`Erro Service Request: HTTP ${response.status}`);
      }
      return await response.json();
    }

    // === 2. Upload do Vídeo ===
    async function uploadVideo(serviceResponse) {
      const uploadUrl = serviceResponse.uploadVideoUrl;
      if (!uploadUrl) throw new Error("Upload URL não fornecida");

      const videoSize = (selectedVideoFile.size / 1024 / 1024).toFixed(2);
      document.getElementById("uploadStatus").textContent =
        `Enviando vídeo (${videoSize} MB)...`;

      const uploadResponse = await fetch(uploadUrl, {
        method: "PUT",
        headers: { "Content-Type": "application/octet-stream" },
        body: selectedVideoFile
      });

      if (!uploadResponse.ok) {
        throw new Error(`Falha no upload: HTTP ${uploadResponse.status}`);
      }

      document.getElementById("uploadStatus").textContent =
        `Upload concluído (${videoSize} MB)`;
    }

    // === 3. Escutar SSE ===
    function listenToSSE(serviceResponse) {
      const requestId = serviceResponse.requestId;
      if (!requestId) throw new Error("Request ID não fornecido");

      const sseUrl = `${API_URL}/gateway/sse-request-track/${requestId}`;
      const sseResultsEl = document.getElementById("sseResults");

      if (eventSource) eventSource.close(); // fecha conexão antiga

      eventSource = new EventSourcePolyfill(sseUrl, {
        headers: { "x-api-key": API_KEY }
      });

      eventSource.onopen = () => {
        sseResultsEl.textContent = "Conexão SSE estabelecida...\n";
      };

      eventSource.onmessage = (event) => {
        const data = JSON.parse(event.data);
        sseResultsEl.textContent += JSON.stringify(data, null, 2) + "\n\n";

        if (data.event === "status" && data.data === "SUCCESS") {
          sseResultsEl.textContent += "\n✅ Resultados finais recebidos.\n";
          eventSource.close();
          document.getElementById("startButton").disabled = false;
        }
      };

      eventSource.onerror = (err) => {
        sseResultsEl.textContent += "\n❌ Erro na conexão SSE\n";
        console.error("SSE error:", err);
        eventSource.close();
        document.getElementById("startButton").disabled = false;
      };
    }

    // Fecha SSE quando a página for fechada
    window.addEventListener("beforeunload", () => {
      if (eventSource) eventSource.close();
    });
  </script>
</body>
</html>

 

Exemplo Alternativo (Com Formulário)

Neste exemplo, os dados do paciente são coletados por um formulário simples em HTML.

Se o dev selecionar pressão arterial, o formulário aparece e exige os valores para idade, sexo, peso e altura.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>WaveLight API - Exemplo com Formulário</title>
  <script src="https://unpkg.com/event-source-polyfill@1.0.31/src/eventsource.min.js"></script>
</head>
<body>
  <h1>WaveLight API Demo (com formulário)</h1>

  <!-- Seleção de serviços -->
  <h3>Selecione os serviços</h3>
  <label><input type="checkbox" class="serviceOption" value="wc_pr-avg_sk_beta"> Pulso</label><br>
  <label><input type="checkbox" class="serviceOption" value="wc_o2-avg_sk_beta"> Saturação</label><br>
  <label><input type="checkbox" id="bpCheckbox" class="serviceOption" value="wc_bp-neural_sk_beta"> Pressão Arterial</label>

  <!-- Formulário do paciente (aparece apenas se pressão for selecionada) -->
  <div id="bpForm" style="display:none; margin-top:10px;">
    <label>Idade: <input type="number" id="age"></label><br>
    <label>Sexo:
      <select id="sex">
        <option value="MALE">Masculino</option>
        <option value="FEMALE">Feminino</option>
      </select>
    </label><br>
    <label>Altura (cm): <input type="number" id="height"></label><br>
    <label>Peso (kg): <input type="number" id="weight"></label>
  </div>

  <!-- Controles -->
  <br>
  <input type="file" id="videoInput" accept="video/*" style="display: none;" />
  <button onclick="document.getElementById('videoInput').click()">Selecionar Vídeo</button>
  <button id="startButton" onclick="runFullProcess()">Iniciar</button>

  <!-- Resultados -->
  <h3>Service Request Response</h3>
  <pre id="serviceResponse">Waiting...</pre>

  <h3>Upload Status</h3>
  <pre id="uploadStatus">Waiting...</pre>

  <h3>Resultados em Tempo Real (SSE)</h3>
  <pre id="sseResults">Waiting...</pre>

  <script>
    const API_URL = "https://api.wavelighthealth.com";
    const API_KEY = "SUA_CHAVE_API_AQUI"; // insira sua chave real

    let eventSource = null;
    let selectedVideoFile = null;

    // Mostra/esconde o formulário de paciente se Pressão for marcada
    document.getElementById("bpCheckbox").addEventListener("change", function() {
      document.getElementById("bpForm").style.display = this.checked ? "block" : "none";
    });

    // Seleção de arquivo
    document.getElementById("videoInput").addEventListener("change", (e) => {
      selectedVideoFile = e.target.files[0];
      if (selectedVideoFile) {
        document.getElementById("uploadStatus").textContent =
          `Vídeo selecionado: ${selectedVideoFile.name}`;
      }
    });

    // Fluxo principal
    async function runFullProcess() {
      if (!selectedVideoFile) {
        alert("Selecione um vídeo antes de iniciar!");
        return;
      }

      document.getElementById("serviceResponse").textContent = "Processando...";
      document.getElementById("uploadStatus").textContent = "Aguardando upload...";
      document.getElementById("sseResults").textContent = "Aguardando resultados...";

      try {
        const serviceResponse = await makeServiceRequest();
        document.getElementById("serviceResponse").textContent =
          JSON.stringify(serviceResponse, null, 2);

        await uploadVideo(serviceResponse);
        listenToSSE(serviceResponse);

      } catch (error) {
        document.getElementById("uploadStatus").textContent = `Erro: ${error.message}`;
      }
    }

    // 1. Service Request
    async function makeServiceRequest() {
      const createdDate = new Date().toISOString();
      const selectedServices = Array.from(document.querySelectorAll(".serviceOption:checked"))
                                   .map(el => el.value);

      if (selectedServices.length === 0) {
        throw new Error("Selecione ao menos um serviço.");
      }

      // Prepara dados do paciente
      let patientData;
      if (selectedServices.includes("wc_bp-neural_sk_beta")) {
        const age = document.getElementById("age").value;
        const sex = document.getElementById("sex").value;
        const height = document.getElementById("height").value;
        const weight = document.getElementById("weight").value;

        if (!age || !height || !weight) {
          throw new Error("Preencha todos os dados do paciente para pressão arterial.");
        }

        patientData = {
          anonymous: [
            { label: "age", unit: "years", value: parseInt(age) },
            { label: "sex", unit: "enum", value: sex },
            { label: "height", unit: "cm", value: parseInt(height) },
            { label: "weight", unit: "kg", value: parseInt(weight) }
          ]
        };
      } else {
        patientData = {
          anonymous: [
            { label: "age", unit: "years" },
            { label: "sex", unit: "enum", value: "UNDEFINED" },
            { label: "height", unit: "cm" },
            { label: "weight", unit: "kg" }
          ]
        };
      }

      const requestBody = {
        serviceList: selectedServices,
        WPG_Object: {
          header: { "content-type": "", version: "", hash: "", secure: true },
          study: { created: createdDate, source: { device: { model: navigator.userAgent } } },
          patient: patientData
        }
      };

      const response = await fetch(`${API_URL}/gateway/service-request`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-api-key": API_KEY
        },
        body: JSON.stringify(requestBody)
      });

      if (!response.ok) {
        throw new Error(`Erro Service Request: HTTP ${response.status}`);
      }
      return await response.json();
    }

    // 2. Upload do Vídeo
    async function uploadVideo(serviceResponse) {
      const uploadUrl = serviceResponse.uploadVideoUrl;
      if (!uploadUrl) throw new Error("Upload URL não fornecida");

      document.getElementById("uploadStatus").textContent = "Enviando vídeo...";
      const uploadResponse = await fetch(uploadUrl, {
        method: "PUT",
        headers: { "Content-Type": "application/octet-stream" },
        body: selectedVideoFile
      });

      if (!uploadResponse.ok) {
        throw new Error(`Falha no upload: HTTP ${uploadResponse.status}`);
      }
      document.getElementById("uploadStatus").textContent = "Upload concluído!";
    }

    // 3. Escutar SSE
    function listenToSSE(serviceResponse) {
      const requestId = serviceResponse.requestId;
      if (!requestId) throw new Error("Request ID não fornecido");

      const sseUrl = `${API_URL}/gateway/sse-request-track/${requestId}`;
      const sseResultsEl = document.getElementById("sseResults");

      if (eventSource) eventSource.close();

      eventSource = new EventSourcePolyfill(sseUrl, { headers: { "x-api-key": API_KEY } });

      eventSource.onopen = () => {
        sseResultsEl.textContent = "Conexão SSE aberta...\n";
      };

      eventSource.onmessage = (event) => {
        const data = JSON.parse(event.data);
        sseResultsEl.textContent += JSON.stringify(data, null, 2) + "\n\n";

        if (data.event === "status" && data.data === "SUCCESS") {
          sseResultsEl.textContent += "\n✅ Resultados finais recebidos.\n";
          eventSource.close();
        }
      };

      eventSource.onerror = () => {
        sseResultsEl.textContent += "\n❌ Erro SSE\n";
        eventSource.close();
      };
    }
  </script>
</body>
</html>

 

Solução de Problemas

  •  HTTP 403 (Forbidden)  → verifique se a chave API está correta.

  •  Upload URL not provided  → o service request não retornou a URL, verifique a requisição inicial.

  •  SSE connection error  → pode ser problema de rede ou chave inválida.

  •  Please fill all Blood Pressure parameters  → pressione arterial exige idade, sexo, altura e peso.

Recursos Extras

1. Arquivo de Mídia de Exemplo​

Para simplificar o entendimento de nossas APIs, fornecemos um arquivo de mídia MP4 como exemplo. Este arquivo serve como um recurso prático para que os desenvolvedores testem o processo de upload e integrem com nossa API de upload de vídeos.

Como usar

  • Clique aqui para fazer o download do arquivo e utilizá-lo em suas requisições de upload.

  • Utilize o endpoint apropriado para uploads de mídia conforme descrito na documentação da API..
  • Certifique-se de estar em conformidade com o formato e as especificações de tamanho suportados.

Este exemplo ajuda a validar a integração correta antes de utilizar arquivos reais em produção.​

2. EventSource Polyfill

EventSource Polyfill (para suporte a SSE nos navegadores): https://www.npmjs.com/package/event-source-polyfill

bottom of page