Bem-vindo à documentação completa da API SoulScribe! Esta API permite transcrever consultas médicas, gerar relatórios SOAP estruturados e integrar inteligência artificial ao seu sistema de saúde.
https://soulscribe.soulclinic.com.br/api/v1
Todas as requisições para a API devem incluir dois headers de autenticação:
X-API-Key: Sua chave pública de APIX-API-Secret: Sua chave secreta de APIPOST /api/v1/consultas
Host: soulscribe.soulclinic.com.br
X-API-Key: sua_chave_publica_aqui
X-API-Secret: sua_chave_secreta_aqui
Content-Type: multipart/form-data
Para começar a usar a API, primeiro você precisa criar uma conta no painel administrativo.
Entre em contato com a SoulClinic para criar sua organização. Você receberá credenciais de acesso ao dashboard.
https://soulscribe.soulclinic.com.br/dashboard
Após o login, você verá seu Tenant ID no canto superior direito do dashboard. Anote-o, pois você precisará dele.
A SoulScribe oferece planos flexíveis baseados em uso:
Com sua conta criada, agora você pode gerar chaves de API para autenticar suas requisições.
No dashboard, vá até o menu Configurações → Chaves de API
Clique em "Nova Chave de API" e preencha:
Faça um teste rápido com curl:
curl -X GET "https://soulscribe.soulclinic.com.br/api/v1/test/ping-auth" \
-H "X-API-Key: sua_chave_publica_aqui" \
-H "X-API-Secret: sua_chave_secreta_aqui"
/api/v1/test/ping-auth para testar sua autenticação sem consumir cota.
Visão geral de todos os endpoints da API:
| Método | Endpoint | Descrição |
|---|---|---|
| POST | /api/v1/consultas |
Envia áudio para processamento |
| GET | /api/v1/consultas/:id |
Consulta status de processamento |
| GET | /api/v1/consultas |
Lista todas as consultas |
| GET | /api/v1/consultas/:id/resultado |
Obtém resultado completo |
Envia um arquivo de áudio para transcrição e geração de relatório SOAP.
https://soulscribe.soulclinic.com.br/api/v1/consultas
| Header | Tipo | Descrição |
|---|---|---|
X-API-Key OBRIGATÓRIO |
string | Sua chave pública de API |
X-API-Secret OBRIGATÓRIO |
string | Sua chave secreta de API |
Content-Type |
string | multipart/form-data |
| Parâmetro | Tipo | Descrição |
|---|---|---|
audio OBRIGATÓRIO |
file | Arquivo de áudio (MP3, WAV, M4A, WebM, OGG) Máximo: 500MB |
webhook_url OPCIONAL |
string | URL para receber notificação quando concluir |
metadata OPCIONAL |
json | Metadados customizados (ex: ID do paciente, médico, etc) |
curl -X POST "https://soulscribe.soulclinic.com.br/api/v1/consultas" \
-H "X-API-Key: sua_chave_publica_aqui" \
-H "X-API-Secret: sua_chave_secreta_aqui" \
-F "audio=@/caminho/para/consulta.mp3" \
-F "webhook_url=https://seu-site.com/webhook" \
-F 'metadata={"paciente_id": "12345", "medico": "Dr. Silva"}'
const formData = new FormData();
formData.append('audio', audioFile);
formData.append('webhook_url', 'https://seu-site.com/webhook');
formData.append('metadata', JSON.stringify({
paciente_id: '12345',
medico: 'Dr. Silva'
}));
const response = await fetch('https://soulscribe.soulclinic.com.br/api/v1/consultas', {
method: 'POST',
headers: {
'X-API-Key': 'sua_chave_publica_aqui',
'X-API-Secret': 'sua_chave_secreta_aqui'
},
body: formData
});
const data = await response.json();
console.log(data);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://soulscribe.soulclinic.com.br/api/v1/consultas',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: sua_chave_publica_aqui',
'X-API-Secret: sua_chave_secreta_aqui'
],
CURLOPT_POSTFIELDS => [
'audio' => new CURLFile('/caminho/para/consulta.mp3'),
'webhook_url' => 'https://seu-site.com/webhook',
'metadata' => json_encode([
'paciente_id' => '12345',
'medico' => 'Dr. Silva'
])
]
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);
import requests
url = 'https://soulscribe.soulclinic.com.br/api/v1/consultas'
headers = {
'X-API-Key': 'sua_chave_publica_aqui',
'X-API-Secret': 'sua_chave_secreta_aqui'
}
files = {'audio': open('consulta.mp3', 'rb')}
data = {
'webhook_url': 'https://seu-site.com/webhook',
'metadata': '{"paciente_id": "12345", "medico": "Dr. Silva"}'
}
response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())
{
"success": true,
"message": "Áudio recebido e em processamento",
"consulta_id": 42,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "pendente",
"status_url": "https://soulscribe.soulclinic.com.br/api/v1/consultas/42"
}
status_url para consultar o progresso ou configure um webhook para ser notificado automaticamente.
Consulta o status e progresso do processamento de uma consulta.
https://soulscribe.soulclinic.com.br/api/v1/consultas/:id
| Parâmetro | Tipo | Descrição |
|---|---|---|
id OBRIGATÓRIO |
integer | ID da consulta retornado no POST |
curl -X GET "https://soulscribe.soulclinic.com.br/api/v1/consultas/42" \
-H "X-API-Key: sua_chave_publica_aqui" \
-H "X-API-Secret: sua_chave_secreta_aqui"
{
"success": true,
"consulta_id": 42,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "processando",
"status_processamento": "processando",
"progresso": 60,
"tempo_decorrido": "2m 15s"
}
{
"success": true,
"consulta_id": 42,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "concluida",
"status_processamento": "concluido",
"progresso": 100,
"tempo_decorrido": "3m 42s",
"transcricao": "Paciente relata dor de cabeça há 3 dias...",
"relatorio_soap": {
"SOAP": {
"S": {
"Queixa_principal": "Dor de cabeça",
"Historia_da_doenca_atual": "Paciente refere cefaleia há 3 dias..."
},
"O": {
"Sinais_vitais": "PA: 120/80 mmHg, FC: 72 bpm",
"Achados_do_exame_fisico": "Paciente alerta e orientado..."
},
"A": {
"Diagnostico_principal": "Cefaleia tensional",
"Diagnosticos_diferenciais": ["Enxaqueca", "Hipertensão"]
},
"P": {
"Medicacoes_prescritas": ["Dipirona 500mg"],
"Orientacoes_dadas": ["Repouso", "Hidratação"]
}
}
}
}
status_processamento não for "concluido" ou "falhou".
Lista todas as consultas da sua conta com paginação.
https://soulscribe.soulclinic.com.br/api/v1/consultas
| Parâmetro | Tipo | Descrição |
|---|---|---|
page OPCIONAL |
integer | Número da página (padrão: 1) |
per_page OPCIONAL |
integer | Itens por página (padrão: 20, máx: 100) |
status OPCIONAL |
string | Filtrar por status: "pendente", "processando", "concluida", "falhou" |
curl -X GET "https://soulscribe.soulclinic.com.br/api/v1/consultas?page=1&per_page=10&status=concluida" \
-H "X-API-Key: sua_chave_publica_aqui" \
-H "X-API-Secret: sua_chave_secreta_aqui"
{
"success": true,
"data": [
{
"id": 42,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "concluida",
"created_at": "2025-10-02 14:30:00",
"tempo_processamento": "3m 42s"
}
],
"pagination": {
"total": 150,
"per_page": 10,
"current_page": 1,
"last_page": 15,
"next_page_url": "https://soulscribe.soulclinic.com.br/api/v1/consultas?page=2",
"prev_page_url": null
}
}
Receba notificações automáticas quando o processamento de uma consulta for concluído.
webhook_urlQuando o processamento termina, enviamos este JSON para sua webhook_url:
{
"event": "consulta.concluida",
"timestamp": "2025-10-02T14:35:22Z",
"data": {
"consulta_id": 42,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "concluida",
"transcricao": "Texto completo da transcrição...",
"relatorio_soap": {
"SOAP": {
"S": {...},
"O": {...},
"A": {...},
"P": {...}
}
},
"custos": {
"total_usd": 0.0234,
"total_brl": 0.117,
"minutos_audio": 3.5
},
"metadata": {
"paciente_id": "12345",
"medico": "Dr. Silva"
}
},
"signature": "sha256=abc123..."
}
Para garantir que o webhook veio realmente da SoulClinic, verificamos cada requisição com HMAC-SHA256:
// webhook-receiver.php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$secret = 'sua_chave_api_aqui';
$expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expectedSignature, $signature)) {
http_response_code(401);
die('Assinatura inválida');
}
$data = json_decode($payload, true);
if ($data['event'] === 'consulta.concluida') {
// Processar consulta concluída
$consultaId = $data['data']['consulta_id'];
$transcricao = $data['data']['transcricao'];
$soap = $data['data']['relatorio_soap'];
// Salvar no banco, enviar email, etc.
}
http_response_code(200);
echo json_encode(['success' => true]);
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const secret = 'sua_chave_api_aqui';
const expectedSignature = 'sha256=' +
crypto.createHmac('sha256', secret)
.update(req.body)
.digest('hex');
if (signature !== expectedSignature) {
return res.status(401).json({error: 'Assinatura inválida'});
}
const data = JSON.parse(req.body);
if (data.event === 'consulta.concluida') {
console.log('Consulta concluída:', data.data.consulta_id);
// Processar dados...
}
res.json({success: true});
});
from flask import Flask, request, jsonify
import hmac
import hashlib
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-Webhook-Signature', '')
secret = 'sua_chave_api_aqui'
payload = request.data
expected_signature = 'sha256=' + hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected_signature):
return jsonify({'error': 'Assinatura inválida'}), 401
data = request.get_json()
if data['event'] == 'consulta.concluida':
consulta_id = data['data']['consulta_id']
# Processar dados...
return jsonify({'success': True})
Integre facilmente gravação de áudio e processamento em tempo real no seu sistema com nosso widget pronto.
Adicione 2 linhas de código e está pronto!
Interface bonita e responsiva com Bootstrap 5.3
Posicione no canto da tela sem interferir no layout
Ondas sonoras animadas durante a gravação
Adicione no final do seu HTML, antes do </body>:
<script src="https://soulscribe.soulclinic.com.br/widget/soulclinic-recorder.js"></script>
Adicione uma div onde o widget será renderizado:
<div id="soulclinic-recorder"></div>
Configure e inicie o widget:
<script>
const recorder = new SoulClinicRecorder({
// Container onde o widget será renderizado
containerId: 'soulclinic-recorder',
// Sua chave de API
apiKey: 'sua_chave_api_aqui',
// URL da API
apiUrl: 'https://soulscribe.soulclinic.com.br/api/v1/consultas',
// Posição do widget (opcional)
position: 'bottom-right', // 'bottom-left', 'bottom-center', 'bottom-right'
// Widget flutuante? (opcional)
floating: true,
// Callbacks (opcional)
onSuccess: (resultado) => {
console.log('Sucesso!', resultado);
alert('Transcrição: ' + resultado.transcricao);
},
onError: (erro) => {
console.error('Erro:', erro);
alert('Erro: ' + erro.message);
}
});
</script>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Minha Clínica</title>
</head>
<body>
<h1>Sistema da Minha Clínica</h1>
<!-- Container do Widget -->
<div id="soulclinic-recorder"></div>
<!-- Script do Widget -->
<script src="https://soulscribe.soulclinic.com.br/widget/soulclinic-recorder.js"></script>
<!-- Inicialização -->
<script>
const recorder = new SoulClinicRecorder({
containerId: 'soulclinic-recorder',
apiKey: 'sua_chave_api_aqui',
apiUrl: 'https://soulscribe.soulclinic.com.br/api/v1/consultas',
position: 'bottom-right',
floating: true,
onSuccess: (resultado) => {
// Exibir transcrição
document.getElementById('transcricao').textContent = resultado.transcricao;
// Salvar no seu banco de dados
fetch('/sua-api/salvar-consulta', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
paciente_id: 12345,
transcricao: resultado.transcricao,
soap: resultado.relatorio_soap
})
});
},
onError: (erro) => {
alert('Erro ao processar áudio: ' + erro.message);
}
});
</script>
</body>
</html>
| Opção | Tipo | Padrão | Descrição |
|---|---|---|---|
containerId |
string | - | OBRIGATÓRIO ID do elemento HTML |
apiKey |
string | - | OBRIGATÓRIO Sua chave de API |
apiUrl |
string | - | OBRIGATÓRIO URL da API |
position |
string | 'bottom-right' | 'bottom-left', 'bottom-center', 'bottom-right' |
floating |
boolean | false | Widget flutuante sobre a página |
onSuccess |
function | null | Callback quando processamento terminar |
onError |
function | null | Callback em caso de erro |
Casos de uso reais para ajudar você a começar rapidamente.
// Durante videochamada, gravar consulta
const mediaRecorder = new MediaRecorder(stream);
const chunks = [];
mediaRecorder.ondataavailable = (e) => chunks.push(e.data);
mediaRecorder.onstop = async () => {
const blob = new Blob(chunks, {type: 'audio/webm'});
const formData = new FormData();
formData.append('audio', blob, 'consulta.webm');
formData.append('metadata', JSON.stringify({
paciente_id: pacienteAtual.id,
medico_id: medicoAtual.id,
especialidade: 'cardiologia'
}));
const response = await fetch('https://soulscribe.soulclinic.com.br/api/v1/consultas', {
method: 'POST',
headers: {
'X-API-Key': API_KEY_PUBLIC,
'X-API-Secret': API_KEY_SECRET
},
body: formData
});
const data = await response.json();
// Fazer polling do resultado
const checkStatus = setInterval(async () => {
const status = await fetch(data.status_url, {
headers: {
'X-API-Key': API_KEY_PUBLIC,
'X-API-Secret': API_KEY_SECRET
}
}).then(r => r.json());
if (status.status_processamento === 'concluido') {
clearInterval(checkStatus);
salvarProntuario(status.transcricao, status.relatorio_soap);
}
}, 3000);
};
// prontuario.php
class ProntuarioService {
private $apiKey = 'sua_chave_aqui';
private $apiUrl = 'https://soulscribe.soulclinic.com.br/api/v1/consultas';
public function processarConsulta($audioPath, $pacienteId) {
$ch = curl_init($this->apiUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . $this->apiKeyPublic,
'X-API-Secret: ' . $this->apiKeySecret
],
CURLOPT_POSTFIELDS => [
'audio' => new CURLFile($audioPath),
'webhook_url' => 'https://meu-sistema.com/webhook/consulta',
'metadata' => json_encode([
'paciente_id' => $pacienteId,
'timestamp' => date('c')
])
]
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
// Salvar ID da consulta no banco
DB::table('consultas_processando')->insert([
'paciente_id' => $pacienteId,
'soulclinic_id' => $response['consulta_id'],
'uuid' => $response['uuid'],
'status' => 'aguardando'
]);
return $response;
}
public function receberWebhook($payload) {
// Validar assinatura...
if ($payload['event'] === 'consulta.concluida') {
DB::table('prontuarios')->insert([
'paciente_id' => $payload['data']['metadata']['paciente_id'],
'transcricao' => $payload['data']['transcricao'],
'soap_subjetivo' => json_encode($payload['data']['relatorio_soap']['SOAP']['S']),
'soap_objetivo' => json_encode($payload['data']['relatorio_soap']['SOAP']['O']),
'soap_avaliacao' => json_encode($payload['data']['relatorio_soap']['SOAP']['A']),
'soap_plano' => json_encode($payload['data']['relatorio_soap']['SOAP']['P']),
'created_at' => now()
]);
}
}
}
import AudioRecorderPlayer from 'react-native-audio-recorder-player';
const ConsultaScreen = () => {
const [recording, setRecording] = useState(false);
const audioRecorderPlayer = new AudioRecorderPlayer();
const startRecording = async () => {
const uri = await audioRecorderPlayer.startRecorder();
setRecording(true);
};
const stopRecording = async () => {
const uri = await audioRecorderPlayer.stopRecorder();
setRecording(false);
// Enviar para API
const formData = new FormData();
formData.append('audio', {
uri: uri,
type: 'audio/m4a',
name: 'consulta.m4a'
});
const response = await fetch('https://soulscribe.soulclinic.com.br/api/v1/consultas', {
method: 'POST',
headers: {
'X-API-Key': 'sua_chave_publica_aqui',
'X-API-Secret': 'sua_chave_secreta_aqui'
},
body: formData
});
const data = await response.json();
navigation.navigate('Resultado', {consultaId: data.consulta_id});
};
return (
<View>
<Button
title={recording ? 'Parar' : 'Gravar'}
onPress={recording ? stopRecording : startRecording}
/>
</View>
);
};
Referência completa de erros e como resolvê-los.
| Código HTTP | Erro | Descrição | Solução |
|---|---|---|---|
| 400 | Bad Request | Parâmetros inválidos ou arquivo ausente | Verifique se enviou o arquivo de áudio corretamente |
| 401 | Unauthorized | Chaves de API inválidas ou ausentes | Verifique se incluiu ambos os headers X-API-Key e X-API-Secret corretamente |
| 403 | Forbidden | Cota excedida ou conta suspensa | Verifique seu plano no dashboard ou entre em contato |
| 404 | Not Found | Consulta não encontrada | Verifique se o ID da consulta está correto |
| 413 | Payload Too Large | Arquivo maior que 500MB | Reduza o tamanho do arquivo ou divida em partes |
| 415 | Unsupported Media Type | Formato de áudio não suportado | Use MP3, WAV, M4A, WebM ou OGG |
| 429 | Too Many Requests | Rate limit excedido | Aguarde alguns segundos antes de tentar novamente |
| 500 | Internal Server Error | Erro interno no servidor | Entre em contato com o suporte |
| 503 | Service Unavailable | Serviço temporariamente indisponível | Tente novamente em alguns minutos |
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Chave de API inválida ou expirada",
"details": "Verifique se sua chave está correta e ativa no dashboard"
}
}
Entenda os limites da API e como são calculados os custos.
Os custos são calculados baseados em:
Todas as respostas incluem headers informativos:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1696347600
Nossa equipe está pronta para ajudar você!