Pular para conteúdo

Referência de Erros HTTP

Esta página documenta os códigos de erro HTTP que você pode encontrar ao interagir com a API da Videochamada.com.br, com os cenários reais que os produzem e como resolvê-los.

Estrutura de resposta de erro

Todas as respostas de erro seguem o formato JSON:

{
  "statusCode": 400,
  "timestamp": "2026-08-30T14:22:01.000Z",
  "path": "/api/calls",
  "message": "Descrição legível do erro"
}

Códigos de erro por categoria

400 — Bad Request

Parâmetros inválidos ou operação que não faz sentido no estado atual do recurso.

Mensagem Cenário Solução
startDate and endDate are required GET /api/calls sem os parâmetros de período Informe startDate e endDate na listagem de chamadas
Call is already ended POST /api/calls/{id}/end em uma chamada já encerrada Consulte GET /api/calls/{id}/status antes de encerrar
Failed to end call: ... Falha durante o encerramento da chamada Verifique a mensagem detalhada e tente novamente
Expected exactly one participant role POST /api/calls/{id}/access com corpo diferente de {"role": "..."} Envie exatamente um campo role no corpo
Invalid participant role role fora dos valores aceitos Use customer, attendant ou supervisor
Idempotency-Key must contain 1 to 200 printable characters Header Idempotency-Key vazio, longo demais ou com caracteres de controle Use uma chave de 1 a 200 caracteres imprimíveis

Exemplo de resposta:

{
  "statusCode": 400,
  "timestamp": "2026-08-30T14:22:01.000Z",
  "path": "/api/calls/9f3b2a1c-7d4e-4c8a-b5f6-2e1d0c9b8a7f/end",
  "message": "Call is already ended"
}

401 — Unauthorized

Credencial ausente, inválida ou não autorizada para a operação.

Mensagem Cenário Solução
API key is missing Header Authorization não foi enviado Adicione Authorization: Bearer {API_TOKEN} à requisição
Invalid API key API key inexistente, revogada — ou requisição vinda de um IP fora da lista de IPs permitidos da chave (a resposta não distingue os dois casos) Verifique a chave no painel e, se a chave tem restrição de IP, confirme que o IP de origem está na lista
Organization subscription is suspended. Please update your payment information. Assinatura da organização suspensa Atualize os dados de pagamento no painel
Expiration date must be in the future POST /api/calls com expiresAt no passado ou inválido Envie uma data futura em formato ISO 8601. Observação: hoje este cenário retorna 401, embora seja um erro de validação — trate-o como um dado inválido
Call does not belong to this project POST /api/calls/{id}/end, GET /api/calls/{id}/status, GET /api/calls/{id}/events ou GET /api/calls/{id}/participants com uma chamada de outro projeto Use a API key do projeto ao qual a chamada pertence

Exemplo de resposta:

{
  "statusCode": 401,
  "timestamp": "2026-08-30T14:22:01.000Z",
  "path": "/api/calls",
  "message": "API key is missing"
}

403 — Forbidden

Você está autenticado, mas a operação não é permitida.

Mensagem Cenário Solução
Maximum spending limit reached for this month Limite de gastos mensal da assinatura atingido ao criar uma chamada Aumente o limite de gastos no painel ou aguarde o próximo ciclo
Call does not belong to this project POST/DELETE /api/calls/{id}/recordings ou POST /api/calls/{id}/access com uma chamada de outro projeto Use a API key do projeto correto
Recording does not belong to this project GET /api/calls/{id}/recordings, GET /api/calls/{id}/transcriptions ou GET /recordings/files/{fileId}/download-url com recurso de outro projeto Use a API key do projeto correto
Recording is not enabled for this call Tentativa de gravação em chamada sem gravação habilitada Habilite a gravação da chamada antes

O mesmo cenário pode retornar 401 ou 403

O cenário "recurso de outro projeto" pode retornar 401 ou 403 dependendo do endpoint (por exemplo, POST /api/calls/{id}/end responde 401 e POST /api/calls/{id}/recordings responde 403, ambos com mensagens equivalentes). Na sua integração, trate os dois códigos da mesma forma: a credencial usada não está autorizada para este recurso — quase sempre é uma API key do projeto errado.

Exemplo de resposta:

{
  "statusCode": 403,
  "timestamp": "2026-08-30T14:22:01.000Z",
  "path": "/api/calls",
  "message": "Maximum spending limit reached for this month"
}

404 — Not Found

O recurso solicitado não foi encontrado.

Mensagem Cenário Solução
Call not found ID de chamada inexistente Verifique o ID da chamada
Recording file not found ID de arquivo de gravação inexistente em GET /recordings/files/{fileId}/download-url Verifique o ID do arquivo retornado na listagem de gravações
Call does not have recording enabled GET /api/calls/{id}/transcriptions em chamada sem gravação habilitada Habilite a gravação antes de consultar transcrições
Organization not found / Subscription not found Conta com configuração incompleta ao criar uma chamada Entre em contato com o suporte

Exemplo de resposta:

{
  "statusCode": 404,
  "timestamp": "2026-08-30T14:22:01.000Z",
  "path": "/api/calls/9f3b2a1c-7d4e-4c8a-b5f6-2e1d0c9b8a7f/status",
  "message": "Call not found"
}

409 — Conflict

Mensagem Cenário Solução
Idempotency-Key was already used with a different request A mesma Idempotency-Key foi reutilizada em POST /api/calls com um corpo diferente do original Gere uma chave nova para cada requisição distinta; reutilize a chave apenas para reenviar exatamente a mesma requisição

Exemplo de resposta:

{
  "statusCode": 409,
  "timestamp": "2026-08-30T14:22:01.000Z",
  "path": "/api/calls",
  "message": "Idempotency-Key was already used with a different request"
}

410 — Gone

O recurso existiu, mas não está mais disponível. Diferente do 404, o 410 é definitivo — não adianta repetir a requisição.

Mensagem Cenário Solução
Recording expired on {data}. Retention period: {N} days Download de gravação após o fim do período de retenção Baixe e armazene as gravações dentro do período de retenção do seu plano
Call access has expired POST /api/calls/{id}/access para uma chamada cujo expiresAt já passou Crie uma nova chamada; tokens de acesso não podem ser emitidos para chamadas expiradas

Exemplo de resposta:

{
  "statusCode": 410,
  "timestamp": "2026-08-30T14:22:01.000Z",
  "path": "/api/calls/9f3b2a1c-7d4e-4c8a-b5f6-2e1d0c9b8a7f/access",
  "message": "Call access has expired"
}

5xx — Erros do servidor

Erros 500/503 indicam uma falha temporária do lado da plataforma. Eles são monitorados internamente; na sua integração, trate-os com nova tentativa e backoff exponencial (veja abaixo). Em erros 500, o campo message retorna sempre o texto genérico "Internal server error" — os detalhes ficam apenas nos logs internos.

Uso responsável

Não há limites rígidos de requisições (rate limiting) publicados hoje — a API não retorna 429. Ainda assim:

  • Prefira webhooks a polling constante para acompanhar chamadas.
  • Aplique backoff exponencial ao repetir requisições que falharam com erros 5xx.
  • Use cache no seu lado para dados que mudam pouco.

Boas práticas de tratamento de erros

1. Sempre verifique o status HTTP

const response = await fetch(
  'https://api.videochamada.com.br/api/calls?startDate=2025-10-01&endDate=2025-10-31',
  { headers: { Authorization: 'Bearer ' + apiToken } },
);

if (!response.ok) {
  const error = await response.json();
  console.error(`Erro ${error.statusCode}: ${error.message}`);
  // Trate o erro apropriadamente
}

2. Implemente retry com backoff exponencial para 5xx

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);

    if (response.ok) {
      return response;
    }

    // Repita apenas erros de servidor; erros 4xx não mudam ao repetir
    if (response.status >= 500) {
      await new Promise((resolve) => setTimeout(resolve, Math.pow(2, i) * 1000));
      continue;
    }

    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }
}

3. Registre erros para análise

import logging
import requests

try:
    response = requests.get(url, headers=headers)
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    logging.error(f"HTTP Error: {e.response.status_code} - {e.response.text}")
    # Trate o erro apropriadamente

4. Use webhooks em vez de polling

// ❌ Evite: polling a cada 5 segundos
setInterval(async () => {
  const status = await getCallStatus(callId);
}, 5000);

// ✅ Prefira: configure um webhook para call.ended
// Você receberá a notificação automaticamente quando a chamada encerrar

Suporte

Se você continuar enfrentando erros após seguir este guia:

Ao entrar em contato, inclua:

  • Endpoint acessado
  • Código de status HTTP recebido
  • Mensagem de erro completa
  • Data e hora aproximada da requisição