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
Configuração
Nossa equipe configura os webhooks no seu sistema conforme suas necessidades
Eventos
Quando um evento ocorre (ex: transcrição concluída), enviamos uma requisição POST
Recebimento
Sua aplicação recebe a notificação e pode processar o evento imediatamente
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:
| Tentativa | Delay |
|---|
| 1ª | Imediato |
| 2ª | 1 minuto |
| 3ª | 5 minutos |
| 4ª | 15 minutos |
| 5ª | 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
- Contate nossa equipe via WhatsApp (+55 31 8883-5141)
- 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)
- 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
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);
}
}