Skip to main content

Tratamento de Erros

Este guia explica como a Wapizap API reporta erros e como tratá-los corretamente em sua aplicação.

Formato de Resposta de Erro

Todas as respostas de erro seguem este formato:
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Descrição legível do erro",
    "details": {}
  }
}
CampoTipoDescrição
successbooleanSempre false para erros
error.codestringCódigo único do erro (use para lógica)
error.messagestringMensagem legível (use para logs/debug)
error.detailsobjectInformações adicionais (opcional)

Códigos HTTP

CódigoSignificadoQuando Ocorre
400Bad RequestDados inválidos ou faltando
401UnauthorizedToken ausente ou inválido
403ForbiddenSem permissão para a ação
404Not FoundRecurso não existe
409ConflictConflito (ex: nome duplicado)
422UnprocessableDados válidos mas não processáveis
429Too Many RequestsRate limit excedido
500Internal ErrorErro interno do servidor
503Service UnavailableServiço temporariamente indisponível

Erros Comuns

Autenticação (401)

{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key provided"
  }
}
Solução: Verifique se o header Authorization: Bearer SEU_TOKEN está correto.

Instância Não Encontrada (404)

{
  "success": false,
  "error": {
    "code": "INSTANCE_NOT_FOUND",
    "message": "Instance 'minha-instancia' not found"
  }
}
Solução: Verifique se o instanceId está correto e se a instância existe.

Instância Desconectada (422)

{
  "success": false,
  "error": {
    "code": "INSTANCE_NOT_CONNECTED",
    "message": "Instance is not connected to WhatsApp"
  }
}
Solução: Reconecte a instância usando o endpoint de conexão.

Número Inválido (400)

{
  "success": false,
  "error": {
    "code": "INVALID_NUMBER",
    "message": "The phone number is not registered on WhatsApp",
    "details": {
      "number": "5511999999999"
    }
  }
}
Solução: Use /contacts/check para validar números antes de enviar.

Rate Limit (429)

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please retry after 60 seconds.",
    "details": {
      "retryAfter": 60,
      "limit": 30,
      "remaining": 0
    }
  }
}
Solução: Aguarde o tempo indicado em retryAfter e implemente exponential backoff.

Mídia Muito Grande (400)

{
  "success": false,
  "error": {
    "code": "MEDIA_TOO_LARGE",
    "message": "Media file exceeds maximum size",
    "details": {
      "maxSize": "16MB",
      "receivedSize": "25MB"
    }
  }
}
Solução: Reduza o tamanho do arquivo antes de enviar.

Tratamento em Código

JavaScript/TypeScript

async function sendMessage(instanceId, to, text) {
  try {
    const response = await fetch('https://api.wapizap.com/api/v2/messages', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${API_KEY}`
      },
      body: JSON.stringify({ instanceId, to, type: 'text', text })
    });

    const data = await response.json();

    if (!data.success) {
      // Tratar erro baseado no código
      switch (data.error.code) {
        case 'INSTANCE_NOT_CONNECTED':
          await reconnectInstance(instanceId);
          return sendMessage(instanceId, to, text); // Retry

        case 'INVALID_NUMBER':
          console.error(`Número inválido: ${to}`);
          return null;

        case 'RATE_LIMIT_EXCEEDED':
          const retryAfter = data.error.details?.retryAfter || 60;
          await sleep(retryAfter * 1000);
          return sendMessage(instanceId, to, text); // Retry

        default:
          throw new Error(data.error.message);
      }
    }

    return data.data;

  } catch (error) {
    console.error('Erro ao enviar mensagem:', error);
    throw error;
  }
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Python

import requests
import time

def send_message(instance_id, to, text):
    try:
        response = requests.post(
            'https://api.wapizap.com/api/v2/messages',
            headers={
                'Content-Type': 'application/json',
                'Authorization': f'Bearer {API_KEY}'
            },
            json={
                'instanceId': instance_id,
                'to': to,
                'type': 'text',
                'text': text
            }
        )

        data = response.json()

        if not data.get('success'):
            error_code = data.get('error', {}).get('code')

            if error_code == 'INSTANCE_NOT_CONNECTED':
                reconnect_instance(instance_id)
                return send_message(instance_id, to, text)  # Retry

            elif error_code == 'INVALID_NUMBER':
                print(f'Número inválido: {to}')
                return None

            elif error_code == 'RATE_LIMIT_EXCEEDED':
                retry_after = data.get('error', {}).get('details', {}).get('retryAfter', 60)
                time.sleep(retry_after)
                return send_message(instance_id, to, text)  # Retry

            else:
                raise Exception(data.get('error', {}).get('message'))

        return data.get('data')

    except Exception as e:
        print(f'Erro ao enviar mensagem: {e}')
        raise

Exponential Backoff

Para erros temporários (429, 500, 503), implemente exponential backoff:
async function fetchWithRetry(url, options, maxRetries = 3) {
  let lastError;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      const data = await response.json();

      if (data.success) {
        return data;
      }

      // Erros que não devem ser retentados
      const nonRetryable = ['UNAUTHORIZED', 'INVALID_NUMBER', 'NOT_FOUND'];
      if (nonRetryable.includes(data.error?.code)) {
        throw new Error(data.error.message);
      }

      // Rate limit - usar tempo específico
      if (data.error?.code === 'RATE_LIMIT_EXCEEDED') {
        const waitTime = data.error.details?.retryAfter || 60;
        await sleep(waitTime * 1000);
        continue;
      }

      lastError = new Error(data.error?.message);

    } catch (error) {
      lastError = error;
    }

    // Exponential backoff: 1s, 2s, 4s, 8s...
    const waitTime = Math.pow(2, attempt) * 1000;
    console.log(`Tentativa ${attempt + 1} falhou. Aguardando ${waitTime}ms...`);
    await sleep(waitTime);
  }

  throw lastError;
}

Códigos de Erro por Categoria

Autenticação

CódigoDescrição
UNAUTHORIZEDToken inválido ou ausente
TOKEN_EXPIREDToken expirado
INSUFFICIENT_PERMISSIONSSem permissão para a ação

Instâncias

CódigoDescrição
INSTANCE_NOT_FOUNDInstância não existe
INSTANCE_NOT_CONNECTEDInstância desconectada
INSTANCE_ALREADY_EXISTSNome já em uso
INSTANCE_LIMIT_EXCEEDEDLimite do plano atingido
QR_CODE_EXPIREDQR code expirou

Mensagens

CódigoDescrição
INVALID_NUMBERNúmero não está no WhatsApp
MESSAGE_NOT_FOUNDMensagem não encontrada
MEDIA_TOO_LARGEArquivo excede limite
INVALID_MEDIA_TYPETipo de mídia não suportado
MESSAGE_FAILEDFalha ao enviar mensagem

Grupos

CódigoDescrição
GROUP_NOT_FOUNDGrupo não encontrado
NOT_GROUP_ADMINAção requer ser admin
PARTICIPANT_NOT_FOUNDParticipante não está no grupo
ALREADY_GROUP_MEMBERJá é membro do grupo

Rate Limiting

CódigoDescrição
RATE_LIMIT_EXCEEDEDMuitas requisições
DAILY_LIMIT_EXCEEDEDLimite diário atingido

Logs e Monitoramento

Estrutura de Log Recomendada

function logApiError(error, context) {
  console.error(JSON.stringify({
    timestamp: new Date().toISOString(),
    level: 'error',
    code: error.code,
    message: error.message,
    context: {
      endpoint: context.endpoint,
      instanceId: context.instanceId,
      requestId: context.requestId
    },
    details: error.details
  }));
}

Alertas Recomendados

Configure alertas para:
  • Taxa de erros > 5% em 5 minutos
  • Erros INSTANCE_NOT_CONNECTED (reconectar automaticamente)
  • Rate limits frequentes (ajustar throttling)
  • Erros 500 (problema no servidor)

Melhores Práticas

Use Códigos de Erro

Base sua lógica no error.code, não na mensagem (que pode mudar).

Implemente Retry

Use exponential backoff para erros temporários (429, 500, 503).

Valide Antes

Valide números com /contacts/check antes de enviar mensagens.

Monitore Erros

Registre e monitore erros para identificar padrões.

Próximos Passos