> ## 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.

# Onboarding

# Onboarding e Primeiros Passos

> Guia completo para integrar sua aplicação com ConnectVets Notes do zero

## 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.

<Info>
  **Tempo estimado**: 15-30 minutos para uma integração básica funcionando
</Info>

## Pré-requisitos

Antes de começar, certifique-se de ter:

<CardGroup cols={2}>
  <Card title="Conta ConnectVets" icon="user">
    * ✅ Conta criada em [notes.connectvets.com.br](https://notes.connectvets.com.br)
    * ✅ Workspace/clínica configurado
    * ✅ Plano ativo (trial ou pago)
  </Card>

  <Card title="Ambiente de Desenvolvimento" icon="code">
    * ✅ Node.js 16+ ou Python 3.8+
    * ✅ Editor de código
    * ✅ Cliente HTTP (Postman, curl, etc.)
    * ✅ Acesso à internet
  </Card>
</CardGroup>

## Fluxo de Onboarding

### Passo 1: Criar API Key

<Steps>
  <Step title="Acessar Dashboard">
    Faça login em [notes.connectvets.com.br](https://notes.connectvets.com.br)
  </Step>

  <Step title="Ir para Configurações">
    No menu lateral, clique em **Configurações** → **API Keys**
  </Step>

  <Step title="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
  </Step>

  <Step title="Copiar Chave">
    ⚠️ **IMPORTANTE**: A chave é exibida apenas uma vez! Copie e armazene com segurança.
  </Step>
</Steps>

### Formato da API Key

```bash theme={null} theme={null}
# Estrutura da chave
cvn_live_1234567890abcdef1234567890abcdef

# Onde:
cvn      = Prefixo ConnectVets Notes
live     = Ambiente (live/test)  
1234...  = Token único
```

### Passo 2: Configurar Ambiente

```bash theme={null} theme={null}
# .env (NUNCA commitar este arquivo!)
CONNECTVETS_API_KEY=cvn_test_sua_chave_aqui
CONNECTVETS_BASE_URL=https://api.connectvets.com
CONNECTVETS_ENVIRONMENT=development
```

```bash theme={null} theme={null}
# .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

<CodeGroup>
  ```javascript JavaScript/Node.js theme={null} theme={null}
  // 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();
  ```

  ```python Python theme={null} theme={null}
  import os
  import requests

  # Configuração
  API_KEY = os.getenv('CONNECTVETS_API_KEY')
  BASE_URL = 'https://api.connectvets.com'

  def test_connection():
      """Testar conectividade com a API"""
      try:
          headers = {
              'X-API-KEY': API_KEY,
              'Content-Type': 'application/json'
          }
          
          response = requests.get(f'{BASE_URL}/notes', headers=headers)
          
          if response.status_code == 200:
              data = response.json()
              print('✅ Conexão estabelecida!')
              print(f'📋 Encontradas {len(data["data"])} notas')
              return data
          else:
              print(f'❌ Erro na conexão: {response.status_code}')
              print(response.text)
              
      except requests.RequestException as error:
          print(f'❌ Erro de rede: {error}')

  if __name__ == "__main__":
      test_connection()
  ```

  ```bash cURL theme={null} theme={null}
  # Teste básico via curl
  curl -X GET "https://api.connectvets.com/notes" \
    -H "X-API-KEY: cvn_test_sua_chave_aqui" \
    -H "Content-Type: application/json" \
    --verbose

  # Resposta esperada: HTTP 200 com lista de notas
  ```

  ```go Go theme={null} theme={null}
  package main

  import (
      "encoding/json"
      "fmt"
      "io"
      "net/http"
      "os"
  )

  type NotesResponse struct {
      Data []Note `json:"data"`
  }

  type Note struct {
      ID       string `json:"id"`
      Content  string `json:"content"`
      Status   string `json:"status"`
  }

  func testConnection() error {
      apiKey := os.Getenv("CONNECTVETS_API_KEY")
      if apiKey == "" {
          return fmt.Errorf("CONNECTVETS_API_KEY não configurada")
      }
      
      req, err := http.NewRequest("GET", "https://api.connectvets.com/notes", nil)
      if err != nil {
          return err
      }
      
      req.Header.Set("X-API-KEY", apiKey)
      req.Header.Set("Content-Type", "application/json")
      
      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          return err
      }
      defer resp.Body.Close()
      
      if resp.StatusCode == 200 {
          body, _ := io.ReadAll(resp.Body)
          var notesResp NotesResponse
          json.Unmarshal(body, &notesResp)
          
          fmt.Println("✅ Conexão estabelecida!")
          fmt.Printf("📋 Encontradas %d notas\n", len(notesResp.Data))
          return nil
      } else {
          return fmt.Errorf("❌ Erro na conexão: %d", resp.StatusCode)
      }
  }

  func main() {
      if err := testConnection(); err != nil {
          fmt.Println(err)
      }
  }
  ```
</CodeGroup>

## Integração Básica

### Enviar Primeira Nota

<CodeGroup>
  ```javascript JavaScript theme={null} theme={null}
  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'
      });
    }
  });
  ```

  ```python Python theme={null} theme={null}
  import requests
  import json

  def create_note(audio_file_path, metadata=None):
      """Criar uma nova nota com arquivo de áudio"""
      if metadata is None:
          metadata = {}
      
      # Dados padrão
      default_metadata = {
          'patient_name': 'Teste',
          'doctor_name': 'Dr. Teste', 
          'consultation_date': '2024-02-14T10:30:00Z',
          'species': 'Canino'
      }
      default_metadata.update(metadata)
      
      headers = {
          'X-API-KEY': API_KEY
      }
      
      with open(audio_file_path, 'rb') as audio_file:
          files = {
              'audio': audio_file,
              'metadata': (None, json.dumps(default_metadata))
          }
          
          response = requests.post(
              f'{BASE_URL}/notes',
              headers=headers,
              files=files
          )
      
      if response.status_code == 201:
          note = response.json()
          print(f'✅ Nota criada: {note["id"]}')
          print(f'🔄 Status: {note["status"]}')
          return note
      else:
          print(f'❌ Erro ao criar nota: {response.status_code}')
          print(response.text)
          return None

  # Exemplo de uso
  note = create_note(
      'caminho/para/audio.mp3',
      {
          'patient_name': 'Rex',
          'doctor_name': 'Dr. Silva',
          'species': 'Canino'
      }
  )
  ```
</CodeGroup>

### Acompanhar Processamento

```javascript theme={null} theme={null}
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

```javascript theme={null} theme={null}
// 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

```javascript theme={null} theme={null}
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

```javascript theme={null} theme={null}
// 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 };
```

### Integração com Sistema Veterinário

```javascript theme={null} theme={null}
// 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

<AccordionGroup>
  <Accordion title="✅ Configuração Inicial">
    * [ ] Conta ConnectVets criada
    * [ ] Workspace configurado
    * [ ] API Key gerada e armazenada
    * [ ] Variáveis de ambiente configuradas
    * [ ] Primeiro teste de conectividade realizado
  </Accordion>

  <Accordion title="✅ Integração Básica">
    * [ ] Cliente HTTP configurado
    * [ ] Primeira nota enviada com sucesso
    * [ ] Sistema de polling implementado
    * [ ] Tratamento de erros básico funcionando
    * [ ] Logs de debug ativados
  </Accordion>

  <Accordion title="✅ Funcionalidades Avançadas">
    * [ ] Webhooks configurados (opcional)
    * [ ] Filtros e paginação implementados
    * [ ] Retry automático em caso de erro
    * [ ] Monitoramento de performance
    * [ ] Backup de dados críticos
  </Accordion>

  <Accordion title="✅ Produção">
    * [ ] API Key de produção configurada
    * [ ] Logs de produção configurados
    * [ ] Monitoramento ativo
    * [ ] Alertas de erro implementados
    * [ ] Documentação interna criada
  </Accordion>
</AccordionGroup>

## Próximos Passos

<CardGroup cols={2}>
  <Card title="Requisitos de Áudio" icon="microphone" href="/notes/integration/audio-requirements">
    Especificações técnicas para áudio
  </Card>

  <Card title="Tratamento de Erros" icon="alert-triangle" href="/notes/integration/error-handling">
    Como lidar com falhas e erros
  </Card>

  <Card title="API Reference" icon="book" href="/notes/api-reference/overview">
    Documentação completa da API
  </Card>

  <Card title="Exemplos Práticos" icon="code" href="/notes/examples/basic-integration">
    Integrações reais funcionando
  </Card>
</CardGroup>

## Suporte

Precisa de ajuda durante o onboarding?

* 📧 **Email**: [suporte@connectvets.com.br](mailto:suporte@connectvets.com.br)
* 💬 **Chat**: Disponível no dashboard
* 📖 **Documentação**: Sempre atualizada
* 🐛 **Bugs**: Reporte via GitHub Issues
