Download de Gravações
O endpoint GET /recordings/files/{fileId}/download-url gera uma URL assinada e temporária para download de um arquivo de gravação. É a forma recomendada de obter uma URL de download nova a qualquer momento.
Atenção ao caminho
Este endpoint não usa o prefixo /api. O caminho correto é https://api.videochamada.com.br/recordings/files/{fileId}/download-url.
Fluxo de download
- Liste os arquivos da chamada com
GET /api/calls/{id}/recordings. - Pegue o
iddo arquivo desejado (ofileId). - Chame
GET /recordings/files/{fileId}/download-urlpara obter a URL assinada. - Faça o download do arquivo diretamente pela URL retornada (sem autenticação adicional).
Atalho: signed_url já vem na listagem
A listagem de gravações já retorna uma URL assinada pronta (signed_url) e seu instante de expiração (expires_at) em cada item — para a maioria dos casos você pode baixar direto por ela, sem chamada extra. Use o endpoint deste documento quando quiser gerar uma URL nova (por exemplo, quando a da listagem já expirou, ou quando você só tem o fileId).
Requisição
Cabeçalhos:
A autenticação aceita dois esquemas:
- API key do projeto (recomendado para integrações servidor-a-servidor) — autoriza qualquer arquivo cuja chamada pertença ao projeto da chave.
- JWT de sessão do painel — o usuário deve pertencer à organização dona do projeto.
Parâmetros:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
fileId |
string (path) | Sim | ID do arquivo de gravação (campo id retornado na listagem de gravações) |
Exemplos
curl -X GET "https://api.videochamada.com.br/recordings/files/{fileId}/download-url" \
-H "Authorization: Bearer {API_TOKEN}"
import requests
response = requests.get(
f"https://api.videochamada.com.br/recordings/files/{file_id}/download-url",
headers={"Authorization": "Bearer {API_TOKEN}"},
)
data = response.json()
print("URL de download:", data["url"])
print("Expira em:", data["expiresIn"], "segundos")
const response = await fetch(
`https://api.videochamada.com.br/recordings/files/${fileId}/download-url`,
{ headers: { Authorization: 'Bearer {API_TOKEN}' } },
);
const { url, expiresIn } = await response.json();
console.log('URL de download:', url);
console.log('Expira em:', expiresIn, 'segundos');
Resposta
{
"url": "https://s3.sa-east-1.amazonaws.com/.../recordings/abc123.webm?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=604800&X-Amz-Signature=...",
"expiresIn": 604800
}
| Campo | Tipo | Descrição |
|---|---|---|
url |
string | URL assinada para download direto do arquivo |
expiresIn |
number | Validade da URL em segundos: 604800 (7 dias) |
Erros
| Status | Mensagem | Quando |
|---|---|---|
| 401 | Authentication required: provide a valid API key or session JWT |
Sem cabeçalho Authorization, ou credencial malformada/inválida/expirada |
| 403 | Recording does not belong to this project |
A API key é de um projeto diferente do projeto da gravação |
| 404 | Recording file not found |
O fileId não existe |
| 410 | Recording expired on {data}. Retention period: {n} days |
O arquivo ultrapassou o período de retenção. A mensagem inclui a data em que a gravação expirou |
Exemplo completo: download programático
Python — usando signed_url da listagem (1 requisição)
import os
import requests
def download_recordings(call_id, api_token, output_dir="downloads"):
headers = {"Authorization": f"Bearer {api_token}"}
# 1. Listar gravações — signed_url já vem na resposta
response = requests.get(
f"https://api.videochamada.com.br/api/calls/{call_id}/recordings",
headers=headers,
)
files = response.json()["data"]
if not files:
print("Nenhuma gravação encontrada")
return
os.makedirs(output_dir, exist_ok=True)
for file in files:
signed_url = file.get("signed_url")
if not signed_url:
# signed_url = null => gravação fora do período de retenção
print(f"Pulando {file['id']}: signed_url indisponível")
continue
# 2. Download direto
extension = "mp4" if file["fileType"] == "composite" else "webm"
filepath = os.path.join(output_dir, f"{call_id}_{file['id']}.{extension}")
with requests.get(signed_url, stream=True) as file_response:
with open(filepath, "wb") as f:
for chunk in file_response.iter_content(chunk_size=8192):
f.write(chunk)
print(f"Download concluído: {filepath}")
download_recordings("{callId}", "{API_TOKEN}")
Node.js — usando o endpoint /download-url (URL sempre nova)
Útil quando você só tem o fileId ou quando a signed_url da listagem já expirou:
const fs = require('fs');
const path = require('path');
async function downloadRecordings(callId, apiToken, outputDir = 'downloads') {
const headers = { Authorization: `Bearer ${apiToken}` };
// 1. Listar gravações da chamada
const listResponse = await fetch(
`https://api.videochamada.com.br/api/calls/${callId}/recordings`,
{ headers },
);
const files = (await listResponse.json()).data;
if (files.length === 0) {
console.log('Nenhuma gravação encontrada');
return;
}
fs.mkdirSync(outputDir, { recursive: true });
for (const file of files) {
// 2. Gerar URL de download nova para o arquivo
const urlResponse = await fetch(
`https://api.videochamada.com.br/recordings/files/${file.id}/download-url`,
{ headers },
);
if (urlResponse.status === 410) {
console.log(`Pulando ${file.id}: fora do período de retenção`);
continue;
}
const { url } = await urlResponse.json();
// 3. Baixar o arquivo
const extension = file.fileType === 'composite' ? 'mp4' : 'webm';
const filepath = path.join(outputDir, `${callId}_${file.id}.${extension}`);
const fileResponse = await fetch(url);
const buffer = Buffer.from(await fileResponse.arrayBuffer());
fs.writeFileSync(filepath, buffer);
console.log(`Download concluído: ${filepath}`);
}
}
downloadRecordings('{callId}', '{API_TOKEN}');
Informações técnicas
Formato dos arquivos
| Tipo | Container | Codecs |
|---|---|---|
Gravação individual (video) |
WebM (.webm) |
Vídeo VP8/VP9, áudio Opus |
Gravação composta (composite) |
MP4 (.mp4) |
Grade única com todos os participantes |
Validade da URL
As URLs de download expiram em 7 dias (expiresIn: 604800 segundos). Após a expiração, basta chamar o endpoint novamente para gerar uma URL nova — ou reler a signed_url na listagem de gravações.
Política de retenção
As gravações são mantidas por um período configurável por projeto (recordingRetentionDays), com padrão de 30 dias contados a partir da criação da gravação. Após esse período:
- A listagem passa a retornar
signed_url: nullpara os arquivos expirados. - O endpoint de download retorna
410 Gone, com a data de expiração na mensagem.
Faça backup antes da retenção expirar
Se você precisa manter as gravações por mais tempo que o período de retenção do projeto, baixe e armazene os arquivos na sua infraestrutura antes do prazo.
Boas práticas
- Baixe logo, não guarde a URL: gere a URL no momento do download em vez de armazená-la — ela expira em 7 dias.
- Trate o
410: um arquivo listado no seu histórico pode já ter saído da retenção. Trate410(esigned_url: null) como "gravação expirada", não como erro transitório. - Download em streaming: para arquivos grandes, use streaming em vez de carregar o conteúdo inteiro em memória.
- Retry em falhas de rede: implemente novas tentativas para falhas durante o download — a URL continua válida dentro do prazo.