Descrição
Inicia uma nova tentativa de processamento para uma nota que falhou na transcrição ou que você deseja reprocessar. Útil para casos onde:
- A transcrição falhou devido a problemas temporários
- Você deseja reprocessar uma nota com melhorias na IA
- Houve problemas na qualidade da primeira transcrição
Compatibilidade: Este endpoint permite retry para notas com status failed, completed ou pending. Não é possível fazer retry de uma nota que já está com status processing.
Parâmetros da Requisição
| Header | Obrigatório | Valor |
X-API-KEY | ✅ Sim | Sua chave de API |
Content-Type | ✅ Sim | application/json |
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
note_id | UUID | ✅ Sim | ID da nota que será reprocessada |
Exemplos de Requisição
cURL
curl -X POST https://api.connectvets.com/transcripts/retry \
-H "X-API-KEY: cvn_live_abc123def456..." \
-H "Content-Type: application/json" \
-d '{
"note_id": "6a4fe1de-52c4-4b2b-a30f-4b3fa9d7d8b3"
}'
JavaScript/TypeScript
async function retryTranscription(noteId) {
const response = await fetch('https://api.connectvets.com/transcripts/retry', {
method: 'POST',
headers: {
'X-API-KEY': 'cvn_live_abc123def456...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
note_id: noteId
})
});
if (!response.ok) {
throw new Error(`Erro no retry: ${response.status}`);
}
const result = await response.json();
return result;
}
// Uso
try {
const result = await retryTranscription('6a4fe1de-52c4-4b2b-a30f-4b3fa9d7d8b3');
console.log('Retry iniciado:', result.status);
console.log('URL da transcrição:', result.transcription);
} catch (error) {
console.error('Erro:', error.message);
}
Python
import requests
import json
def retry_transcription(api_key, note_id):
url = "https://api.connectvets.com/transcripts/retry"
headers = {
"X-API-KEY": api_key,
"Content-Type": "application/json"
}
data = {
"note_id": note_id
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
result = response.json()
print(f"Retry iniciado para nota {note_id}")
print(f"Status: {result['status']}")
print(f"Transcrição: {result['transcription']}")
return result
else:
print(f"Erro: {response.status_code}")
print(response.text)
return None
# Uso
api_key = "cvn_live_abc123def456..."
note_id = "6a4fe1de-52c4-4b2b-a30f-4b3fa9d7d8b3"
result = retry_transcription(api_key, note_id)
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
type RetryRequest struct {
NoteID string `json:"note_id"`
}
type RetryResponse struct {
NoteID string `json:"note_id"`
Status string `json:"status"`
Message string `json:"message"`
Transcription string `json:"transcription"`
}
func retryTranscription(apiKey, noteID string) (*RetryResponse, error) {
url := "https://api.connectvets.com/transcripts/retry"
requestBody := RetryRequest{
NoteID: noteID,
}
jsonData, err := json.Marshal(requestBody)
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, 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 nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("erro %d: %s", resp.StatusCode, resp.Status)
}
var result RetryResponse
err = json.NewDecoder(resp.Body).Decode(&result)
return &result, err
}
// Uso
result, err := retryTranscription("cvn_live_abc123def456...", "6a4fe1de-52c4-4b2b-a30f-4b3fa9d7d8b3")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Status: %s\n", result.Status)
fmt.Printf("Mensagem: %s\n", result.Message)
Resposta de Sucesso (200 OK)
{
"note_id": "6a4fe1de-52c4-4b2b-a30f-4b3fa9d7d8b3",
"status": "processing",
"message": "Transcription retry initiated successfully",
"transcription": "https://cdn.connectvets.com/notes/6a4fe1de.txt"
}
| Campo | Tipo | Descrição |
note_id | UUID | ID da nota que está sendo reprocessada |
status | String | Novo status da nota (sempre “processing”) |
message | String | Mensagem de confirmação |
transcription | String | URL onde a nova transcrição ficará disponível |
Tratamento de Erros
400 Bad Request
{
"error": "bad_request",
"message": "Invalid note_id format",
"code": "INVALID_NOTE_ID"
}
Causas:
note_id ausente no corpo da requisição
note_id com formato inválido (não é UUID)
- Corpo da requisição malformado
400 Bad Request - Já em Processamento
{
"error": "bad_request",
"message": "transcription is already being processed",
"code": "TRANSCRIPTION_IN_PROGRESS"
}
Causa: A nota já está com status processing e não pode ser reprocessada novamente até a conclusão.
403 Forbidden
{
"error": "forbidden",
"message": "Note does not belong to current tenant",
"code": "NOTE_ACCESS_DENIED"
}
Causa: A nota não pertence ao tenant/clínica associado à API Key utilizada.
404 Not Found
{
"error": "not_found",
"message": "Note not found",
"code": "NOTE_NOT_FOUND"
}
Causa: Nota com o ID fornecido não existe.
Casos de Uso
Retry Automático para Notas Falhadas
async function retryFailedNotes() {
// Buscar notas com status failed
const failedNotes = await listNotes({
transcription_status: 'failed'
});
console.log(`Encontradas ${failedNotes.notes.length} notas falhadas`);
const retryResults = [];
for (const note of failedNotes.notes) {
try {
const result = await retryTranscription(note.id);
retryResults.push({
noteId: note.id,
status: 'success',
newStatus: result.status
});
console.log(`✅ Retry iniciado para nota ${note.id}`);
// Aguardar um pouco entre retries
await new Promise(resolve => setTimeout(resolve, 1000));
} catch (error) {
retryResults.push({
noteId: note.id,
status: 'error',
error: error.message
});
console.error(`❌ Erro no retry da nota ${note.id}:`, error.message);
}
}
return retryResults;
}
async function retryAndMonitor(noteId) {
try {
// Iniciar retry
const retryResult = await retryTranscription(noteId);
console.log(`🔄 Retry iniciado para nota ${noteId}`);
// Monitorar progresso
let status = 'processing';
let attempts = 0;
const maxAttempts = 60; // 5 minutos máximo
while (status === 'processing' && attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 5000)); // 5s
const statusResult = await getNoteStatus(noteId);
status = statusResult.status;
attempts++;
console.log(`📊 Tentativa ${attempts}: Status ${status}`);
if (status === 'completed') {
console.log('✅ Retry concluído com sucesso!');
return { success: true, status };
} else if (status === 'failed') {
console.log('❌ Retry falhou novamente');
return { success: false, status };
}
}
if (attempts >= maxAttempts) {
console.log('⏰ Timeout: Retry demorou muito');
return { success: false, status: 'timeout' };
}
} catch (error) {
console.error('❌ Erro no retry:', error.message);
return { success: false, error: error.message };
}
}
async function intelligentRetry(noteId, maxRetries = 3) {
let attempt = 0;
while (attempt < maxRetries) {
try {
// Verificar status atual
const status = await getNoteStatus(noteId);
if (status.status === 'processing') {
console.log('⏳ Nota ainda em processamento, aguardando...');
await new Promise(resolve => setTimeout(resolve, 30000));
continue;
}
if (status.status === 'completed') {
console.log('✅ Nota já processada com sucesso');
return { success: true, alreadyCompleted: true };
}
// Iniciar retry
await retryTranscription(noteId);
console.log(`🔄 Retry ${attempt + 1}/${maxRetries} iniciado`);
// Aguardar processamento
const result = await waitForCompletion(noteId);
if (result.status === 'completed') {
console.log('✅ Retry bem-sucedido!');
return { success: true, attempt: attempt + 1 };
}
attempt++;
if (attempt < maxRetries) {
// Backoff exponencial: 2^attempt minutos
const delayMinutes = Math.pow(2, attempt);
console.log(`⏰ Aguardando ${delayMinutes} minutos antes do próximo retry...`);
await new Promise(resolve => setTimeout(resolve, delayMinutes * 60 * 1000));
}
} catch (error) {
console.error(`❌ Erro no retry ${attempt + 1}:`, error.message);
attempt++;
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, 60000)); // 1 minuto
}
}
}
console.log(`❌ Falha após ${maxRetries} tentativas`);
return { success: false, attempts: maxRetries };
}
Monitoramento após Retry
Verificação de Status
Após iniciar um retry, use o endpoint /notes/{id}/status para monitorar o progresso:
async function monitorRetry(noteId) {
console.log('📊 Monitorando retry...');
let status = 'processing';
let checkCount = 0;
while (status === 'processing') {
await new Promise(resolve => setTimeout(resolve, 10000)); // 10s
const result = await getNoteStatus(noteId);
status = result.status;
checkCount++;
console.log(`Verificação ${checkCount}: ${status}`);
if (status === 'completed') {
console.log('🎉 Retry concluído!');
break;
} else if (status === 'failed') {
console.log('💥 Retry falhou');
break;
}
// Timeout após 10 minutos
if (checkCount > 60) {
console.log('⏰ Timeout do monitoramento');
break;
}
}
return status;
}
Boas Práticas
🔄 Gestão de Retries
- Limite tentativas: Não faça retry infinitamente
- Use backoff: Aguarde entre tentativas com delay crescente
- Monitore status: Verifique se a nota já está em processamento
- Log adequadamente: Registre tentativas e resultados
⏰ Timing
- Aguarde falhas: Não faça retry imediatamente após falha
- Respeite processamento: Não tente retry em notas
processing
- Use polling inteligente: Interval de 5-10s para verificar status
🚨 Tratamento de Erros
function shouldRetry(error) {
// Não retry em casos irrecuperáveis
const nonRetryableErrors = [
'NOTE_NOT_FOUND',
'NOTE_ACCESS_DENIED',
'INVALID_NOTE_ID'
];
return !nonRetryableErrors.includes(error.code);
}
async function safeRetry(noteId) {
try {
return await retryTranscription(noteId);
} catch (error) {
if (shouldRetry(error)) {
console.log('Erro temporário, pode tentar novamente');
} else {
console.log('Erro permanente, não tentar novamente');
}
throw error;
}
}
📈 Métricas
Monitore métricas importantes:
- Taxa de sucesso dos retries
- Tempo médio de processamento
- Notas que falharam múltiplas vezes
- Patterns de falhas para feedback à equipe
API Key para autenticação
ID único da nota para reprocessar
Body
application/json · object
Body vazio para reprocessamento
Reprocessamento iniciado com sucesso
Example:"Note reprocessing started successfully"