Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.connectvets.com.br/llms.txt

Use this file to discover all available pages before exploring further.

Os Webhooks permitem que você receba notificações automáticas quando eventos importantes acontecem no ConnectVets Notes, como quando uma transcrição é concluída ou falha.

Como Funcionam

1

Configuração

Nossa equipe configura os webhooks no seu sistema conforme suas necessidades
2

Eventos

Quando um evento ocorre (ex: transcrição concluída), enviamos uma requisição POST
3

Recebimento

Sua aplicação recebe a notificação e pode processar o evento imediatamente
4

Confirmação

Responda com status 200 para confirmar o recebimento

Eventos Disponíveis

note.transcription.completed

Disparado quando uma transcrição é finalizada com sucesso:
{
  "event": "note.transcription.completed",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Rex",
    "transcription_status": "completed",
    "external_id": "CLIENTE_123",
    "created_at": "2024-02-14T18:25:43Z",
    "completed_at": "2024-02-14T18:30:23Z"
  },
  "timestamp": "2024-02-14T18:30:24Z",
  "webhook_id": "wh_abc123def456"
}

note.transcription.failed

Disparado quando uma transcrição falha:
{
  "event": "note.transcription.failed",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Rex",
    "transcription_status": "failed",
    "error": {
      "code": "AUDIO_QUALITY_LOW",
      "message": "Áudio com qualidade insuficiente para transcrição"
    },
    "external_id": "CLIENTE_123",
    "created_at": "2024-02-14T18:25:43Z",
    "failed_at": "2024-02-14T18:28:15Z"
  },
  "timestamp": "2024-02-14T18:28:16Z",
  "webhook_id": "wh_abc123def456"
}

Implementação

Endpoint do Webhook

Sua aplicação deve ter um endpoint que aceite requisições POST:
app.post('/webhooks/connectvets', (req, res) => {
  const { event, data, timestamp } = req.body;
  
  console.log(`Evento recebido: ${event} em ${timestamp}`);
  
  switch (event) {
    case 'note.transcription.completed':
      handleTranscriptionCompleted(data);
      break;
      
    case 'note.transcription.failed':
      handleTranscriptionFailed(data);
      break;
      
    default:
      console.log(`Evento não tratado: ${event}`);
  }
  
  // Resposta de confirmação
  res.status(200).json({ received: true });
});

function handleTranscriptionCompleted(noteData) {
  // Lógica para processar transcrição concluída
  console.log(`Nota ${noteData.id} foi transcrita com sucesso`);
  
  // Exemplo: notificar o usuário
  notifyUser(noteData.external_id, 'Sua consulta foi transcrita!');
  
  // Exemplo: atualizar banco local
  updateLocalNote(noteData.id, { status: 'completed' });
}

function handleTranscriptionFailed(noteData) {
  // Lógica para processar falha na transcrição
  console.log(`Falha na transcrição da nota ${noteData.id}: ${noteData.error.message}`);
  
  // Exemplo: notificar erro
  notifyUser(noteData.external_id, 'Houve um problema na transcrição. Tente novamente.');
}

Segurança

Validação de Origem

Para garantir que o webhook vem do ConnectVets, valide o header de assinatura:
const crypto = require('crypto');

function validateWebhookSignature(payload, signature, secret) {
  const computedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
    
  const expectedSignature = `sha256=${computedSignature}`;
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

app.post('/webhooks/connectvets', (req, res) => {
  const signature = req.headers['x-connectvets-signature'];
  const payload = JSON.stringify(req.body);
  
  if (!validateWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  // Processar webhook...
});

HTTPS Obrigatório

  • Todos os webhooks devem usar HTTPS
  • Certificados SSL válidos são obrigatórios
  • URLs localhost não são aceitas em produção

Retry Logic

Como Funciona

Se seu endpoint não responder com status 2xx, reenviamos automaticamente:
TentativaDelay
Imediato
1 minuto
5 minutos
15 minutos
1 hora

Idempotência

Implemente verificação de duplicatas usando o webhook_id:
const processedWebhooks = new Set();

app.post('/webhooks/connectvets', (req, res) => {
  const webhookId = req.body.webhook_id;
  
  if (processedWebhooks.has(webhookId)) {
    // Já processado, apenas confirme
    return res.status(200).json({ received: true, duplicate: true });
  }
  
  processedWebhooks.add(webhookId);
  
  // Processar webhook...
});

Monitoramento

Logs Importantes

Monitore estes aspectos:
  • Latência de resposta: Tempo para processar webhook
  • Taxa de erro: Percentual de falhas no processamento
  • Timeouts: Requisições que demoram muito
  • Duplicatas: Webhooks reprocessados

Exemplo de Logging

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'webhooks.log' })
  ]
});

app.post('/webhooks/connectvets', (req, res) => {
  const startTime = Date.now();
  const { event, webhook_id } = req.body;
  
  try {
    // Processar webhook...
    
    const duration = Date.now() - startTime;
    logger.info('webhook_processed', {
      event,
      webhook_id,
      duration_ms: duration,
      status: 'success'
    });
    
    res.status(200).json({ received: true });
  } catch (error) {
    const duration = Date.now() - startTime;
    logger.error('webhook_failed', {
      event,
      webhook_id,
      duration_ms: duration,
      error: error.message,
      status: 'error'
    });
    
    res.status(500).json({ error: 'Processing failed' });
  }
});

Configuração

Importante: Webhooks não são gerenciados via API. A configuração é feita através de contato direto com nossa equipe.

Para Configurar Webhooks

  1. Contate nossa equipe via WhatsApp (+55 31 8883-5141)
  2. Forneça informações:
    • URL do seu endpoint (deve ser HTTPS)
    • Eventos que deseja receber
    • Método de autenticação preferido
    • Ambiente (produção/desenvolvimento)

Informações Necessárias

  • URL do Endpoint: https://seuapp.com/webhooks/connectvets
  • Eventos: ["note.transcription.completed", "note.transcription.failed"]
  • Headers Customizados (opcional): Para autenticação adicional
  • Secret para Validação: Para verificar autenticidade

Teste em Desenvolvimento

Nossa equipe pode configurar webhooks para ambiente de desenvolvimento usando:
  • ngrok para túneis locais
  • Webhook.site para testes rápidos
  • RequestBin para debug

Troubleshooting

Webhook Não Recebido

Possíveis causas:
  • Endpoint inacessível (timeout/erro)
  • Certificado SSL inválido
  • Firewall bloqueando nossa IP
Soluções:
  • Verificar se endpoint responde a GET/POST
  • Validar certificado SSL
  • Liberar IPs do ConnectVets no firewall

Erro 401/403

Possíveis causas:
  • Autenticação adicional no endpoint
  • Headers de validação incorretos
Soluções:
  • Revisar lógica de autenticação
  • Verificar headers x-connectvets-signature

Webhooks Duplicados

Possíveis causas:
  • Endpoint demorou para responder (timeout)
  • Resposta não 2xx
Soluções:
  • Implementar verificação de webhook_id
  • Otimizar tempo de processamento
  • Responder rapidamente (mover processamento pesado para background)

Exemplos de Uso

Integração com CRM

async function handleTranscriptionCompleted(noteData) {
  // Buscar informações da consulta no sistema local
  const appointment = await getAppointmentByExternalId(noteData.external_id);
  
  if (appointment) {
    // Atualizar status no CRM
    await updateCRMRecord(appointment.crm_id, {
      transcription_status: 'completed',
      transcription_url: `https://notes.connectvets.com.br/notes/${noteData.id}`,
      last_updated: new Date()
    });
    
    // Notificar veterinário
    await sendNotification(appointment.veterinarian_id, {
      type: 'transcription_ready',
      patient: noteData.name,
      note_id: noteData.id
    });
  }
}

Workflow de Aprovação

async function handleTranscriptionCompleted(noteData) {
  // Verificar se nota precisa de aprovação
  const needsApproval = await checkApprovalRules(noteData);
  
  if (needsApproval) {
    // Enviar para fila de aprovação
    await addToApprovalQueue(noteData.id, {
      priority: noteData.urgent ? 'high' : 'normal',
      assigned_to: await getReviewerForNote(noteData)
    });
    
    // Notificar revisor
    await notifyReviewer(noteData);
  } else {
    // Aprovação automática
    await autoApproveNote(noteData.id);
  }
}

Próximo passo: Veja exemplos práticos de webhooks ou explore os endpoints de Notes.