Introdução ao Onboarding
O processo de onboarding no ConnectVets Notes é projetado para colocar sua integração funcionando rapidamente, seguindo as melhores práticas de segurança e performance para aplicações veterinárias.
Tempo estimado : 15-30 minutos para uma integração básica funcionando
Pré-requisitos
Antes de começar, certifique-se de ter:
Ambiente de Desenvolvimento
✅ Node.js 16+ ou Python 3.8+
✅ Editor de código
✅ Cliente HTTP (Postman, curl, etc.)
✅ Acesso à internet
Fluxo de Onboarding
Passo 1: Criar API Key
Ir para Configurações
No menu lateral, clique em Configurações → API Keys
Criar Nova Chave
Clique em “Nova API Key” e escolha:
Nome : Ex: “Integração Sistema Veterinário”
Tipo : write (recomendado para integração completa)
Ambiente : test para desenvolvimento, live para produção
Copiar Chave
⚠️ IMPORTANTE : A chave é exibida apenas uma vez! Copie e armazene com segurança.
# Estrutura da chave
cvn_live_1234567890abcdef1234567890abcdef
# Onde:
cvn = Prefixo ConnectVets Notes
live = Ambiente (live/test)
1234... = Token único
Passo 2: Configurar Ambiente
# .env (NUNCA commitar este arquivo!)
CONNECTVETS_API_KEY = cvn_test_sua_chave_aqui
CONNECTVETS_BASE_URL = https://api.connectvets.com
CONNECTVETS_ENVIRONMENT = development
# .env.example (pode commitar)
CONNECTVETS_API_KEY = your_api_key_here
CONNECTVETS_BASE_URL = https://api.connectvets.com
CONNECTVETS_ENVIRONMENT = development
Passo 3: Primeiro Teste
JavaScript/Node.js
Python
cURL
Go
// Testar conectividade com a API
const CONNECTVETS_API_KEY = process . env . CONNECTVETS_API_KEY ;
const BASE_URL = 'https://api.connectvets.com' ;
async function testConnection () {
try {
const response = await fetch ( ` ${ BASE_URL } /notes` , {
method: 'GET' ,
headers: {
'X-API-KEY' : CONNECTVETS_API_KEY ,
'Content-Type' : 'application/json'
}
});
if ( response . ok ) {
const data = await response . json ();
console . log ( '✅ Conexão estabelecida!' );
console . log ( `📋 Encontradas ${ data . data . length } notas` );
return data ;
} else {
console . error ( '❌ Erro na conexão:' , response . status );
}
} catch ( error ) {
console . error ( '❌ Erro de rede:' , error . message );
}
}
testConnection ();
Integração Básica
Enviar Primeira Nota
async function createNote ( audioFile , metadata = {}) {
const formData = new FormData ();
// Arquivo de áudio
formData . append ( 'audio' , audioFile );
// Metadados da consulta
formData . append ( 'metadata' , JSON . stringify ({
patient_name: metadata . patientName || 'Teste' ,
doctor_name: metadata . doctorName || 'Dr. Teste' ,
consultation_date: metadata . date || new Date (). toISOString (),
species: metadata . species || 'Canino' ,
... metadata
}));
try {
const response = await fetch ( ` ${ BASE_URL } /notes` , {
method: 'POST' ,
headers: {
'X-API-KEY' : CONNECTVETS_API_KEY
// NÃO definir Content-Type para FormData
},
body: formData
});
if ( response . ok ) {
const note = await response . json ();
console . log ( '✅ Nota criada:' , note . id );
console . log ( '🔄 Status:' , note . status );
return note ;
} else {
const error = await response . json ();
console . error ( '❌ Erro ao criar nota:' , error );
}
} catch ( error ) {
console . error ( '❌ Erro de rede:' , error );
}
}
// Exemplo de uso
const audioInput = document . getElementById ( 'audio-input' );
audioInput . addEventListener ( 'change' , ( event ) => {
const file = event . target . files [ 0 ];
if ( file ) {
createNote ( file , {
patientName: 'Rex' ,
doctorName: 'Dr. Silva' ,
species: 'Canino'
});
}
});
Acompanhar Processamento
async function pollNoteStatus ( noteId , maxAttempts = 30 ) {
for ( let attempt = 1 ; attempt <= maxAttempts ; attempt ++ ) {
try {
const response = await fetch ( ` ${ BASE_URL } /notes/ ${ noteId } ` , {
headers: {
'X-API-KEY' : CONNECTVETS_API_KEY ,
'Content-Type' : 'application/json'
}
});
if ( response . ok ) {
const note = await response . json ();
console . log ( `📊 Tentativa ${ attempt } : Status ${ note . status } ` );
switch ( note . status ) {
case 'completed' :
console . log ( '✅ Processamento concluído!' );
console . log ( '📝 Conteúdo:' , note . sections );
return note ;
case 'failed' :
console . log ( '❌ Processamento falhou' );
console . log ( '💬 Erro:' , note . error_message );
return note ;
case 'processing' :
case 'transcribing' :
case 'analyzing' :
console . log ( '⏳ Ainda processando...' );
await new Promise ( resolve => setTimeout ( resolve , 2000 )); // Aguardar 2s
break ;
default :
console . log ( `⏳ Status: ${ note . status } ` );
await new Promise ( resolve => setTimeout ( resolve , 2000 ));
}
}
} catch ( error ) {
console . error ( `❌ Erro na tentativa ${ attempt } :` , error );
}
}
console . log ( '⚠️ Timeout: Processamento demorou mais que esperado' );
return null ;
}
// Usar após criar nota
createNote ( audioFile ). then ( note => {
if ( note ) {
pollNoteStatus ( note . id );
}
});
Configuração de Webhooks
Para receber notificações automáticas quando as notas ficarem prontas:
1. Configurar Endpoint
// Endpoint para receber webhooks
app . post ( '/webhooks/connectvets' , express . raw ({ type: 'application/json' }), ( req , res ) => {
const event = req . body ;
console . log ( '🔔 Webhook recebido:' , event . type );
switch ( event . type ) {
case 'note.completed' :
handleNoteCompleted ( event . data );
break ;
case 'note.failed' :
handleNoteFailed ( event . data );
break ;
default :
console . log ( `❓ Evento desconhecido: ${ event . type } ` );
}
res . status ( 200 ). send ( 'OK' );
});
function handleNoteCompleted ( noteData ) {
console . log ( '✅ Nota processada:' , noteData . id );
console . log ( '📝 Seções:' , noteData . sections . length );
// Integrar com seu sistema
updatePatientRecord ( noteData );
notifyVeterinarian ( noteData );
}
function handleNoteFailed ( noteData ) {
console . log ( '❌ Falha no processamento:' , noteData . id );
console . log ( '💬 Erro:' , noteData . error_message );
// Notificar erro
alertAdministrator ( noteData );
}
2. Registrar Webhook
async function registerWebhook ( url , events = [ 'note.completed' , 'note.failed' ]) {
try {
const response = await fetch ( ` ${ BASE_URL } /webhooks` , {
method: 'POST' ,
headers: {
'X-API-KEY' : CONNECTVETS_API_KEY ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
url: url ,
events: events ,
active: true
})
});
if ( response . ok ) {
const webhook = await response . json ();
console . log ( '✅ Webhook registrado:' , webhook . id );
return webhook ;
}
} catch ( error ) {
console . error ( '❌ Erro ao registrar webhook:' , error );
}
}
// Registrar webhook
registerWebhook ( 'https://meuapp.com/webhooks/connectvets' );
Exemplo de Aplicação Completa
Setup Inicial
// config/connectvets.js
class ConnectVetsClient {
constructor ( apiKey , baseUrl = 'https://api.connectvets.com' ) {
this . apiKey = apiKey ;
this . baseUrl = baseUrl ;
}
async request ( endpoint , options = {}) {
const url = ` ${ this . baseUrl }${ endpoint } ` ;
const config = {
... options ,
headers: {
'X-API-KEY' : this . apiKey ,
... options . headers
}
};
const response = await fetch ( url , config );
if ( ! response . ok ) {
const error = await response . json (). catch (() => ({ message: 'Erro desconhecido' }));
throw new Error ( `API Error: ${ response . status } - ${ error . message } ` );
}
return response . json ();
}
async createNote ( audioFile , metadata = {}) {
const formData = new FormData ();
formData . append ( 'audio' , audioFile );
formData . append ( 'metadata' , JSON . stringify ( metadata ));
return this . request ( '/notes' , {
method: 'POST' ,
body: formData ,
headers: {} // Deixar browser definir Content-Type para FormData
});
}
async getNote ( id ) {
return this . request ( `/notes/ ${ id } ` );
}
async listNotes ( filters = {}) {
const params = new URLSearchParams ( filters );
return this . request ( `/notes? ${ params } ` );
}
}
// Instanciar cliente
const connectvets = new ConnectVetsClient ( process . env . CONNECTVETS_API_KEY );
module . exports = { connectvets };
// services/consultationService.js
const { connectvets } = require ( '../config/connectvets' );
class ConsultationService {
async processConsultation ( consultation ) {
try {
// 1. Preparar dados
const metadata = {
patient_name: consultation . patient . name ,
patient_id: consultation . patient . id ,
doctor_name: consultation . veterinarian . name ,
doctor_id: consultation . veterinarian . id ,
consultation_date: consultation . date ,
species: consultation . patient . species ,
breed: consultation . patient . breed ,
consultation_type: consultation . type
};
// 2. Enviar áudio para processamento
console . log ( '📤 Enviando áudio para ConnectVets...' );
const note = await connectvets . createNote ( consultation . audioFile , metadata );
// 3. Salvar referência no banco
await this . saveNoteReference ( consultation . id , note . id );
// 4. Iniciar monitoramento
this . startNoteMonitoring ( note . id , consultation . id );
return note ;
} catch ( error ) {
console . error ( '❌ Erro ao processar consulta:' , error );
throw error ;
}
}
async startNoteMonitoring ( noteId , consultationId ) {
const checkStatus = async () => {
try {
const note = await connectvets . getNote ( noteId );
if ( note . status === 'completed' ) {
await this . handleCompletedNote ( note , consultationId );
} else if ( note . status === 'failed' ) {
await this . handleFailedNote ( note , consultationId );
} else {
// Ainda processando, verificar novamente em 30s
setTimeout ( checkStatus , 30000 );
}
} catch ( error ) {
console . error ( '❌ Erro ao verificar status:' , error );
}
};
checkStatus ();
}
async handleCompletedNote ( note , consultationId ) {
console . log ( '✅ Nota processada para consulta:' , consultationId );
// Extrair informações das seções
const sections = note . sections ;
const summary = sections . find ( s => s . type === 'summary' )?. content ;
const diagnosis = sections . find ( s => s . type === 'diagnosis' )?. content ;
const treatment = sections . find ( s => s . type === 'treatment' )?. content ;
// Atualizar prontuário
await this . updateMedicalRecord ( consultationId , {
summary ,
diagnosis ,
treatment ,
full_transcript: note . transcript ,
connectvets_note_id: note . id
});
// Notificar veterinário
await this . notifyVeterinarian ( consultationId , note );
}
async handleFailedNote ( note , consultationId ) {
console . log ( '❌ Falha no processamento para consulta:' , consultationId );
// Registrar erro
await this . logProcessingError ( consultationId , note . error_message );
// Notificar administrador
await this . notifyAdmin ( consultationId , note . error_message );
}
}
module . exports = { ConsultationService };
Checklist de Onboarding
✅ Funcionalidades Avançadas
Próximos Passos
Suporte
Precisa de ajuda durante o onboarding?
📧 Email : [email protected]
💬 Chat : Disponível no dashboard
📖 Documentação : Sempre atualizada
🐛 Bugs : Reporte via GitHub Issues