Pular para o conteúdo

Erros

A API usa os status HTTP de sempre: 2xx deu certo, 4xx tem algo a corrigir na requisição e 5xx é problema do nosso lado ou do WhatsApp.

Todo erro tem o mesmo corpo JSON:

{
"error": {
"type": "invalid_request_error",
"code": "missing_field",
"message": "Informe `to` ou `contact_id`.",
"param": "to",
"request_id": "req_6f1d2c3b4a5e"
}
}
Campo Descrição
type Categoria do erro (veja abaixo).
code Código estável e específico. Use este campo no seu código para decidir o que fazer.
message Explicação em português para humanos. Pode mudar de texto; não compare strings com ele.
param Campo que causou o erro, quando houver (ex.: to, send_at).
request_id Identificador da requisição — o mesmo valor do cabeçalho X-Request-Id.

Toda resposta (de sucesso ou de erro) traz o cabeçalho X-Request-Id. Registre-o nos seus logs e envie para o suporte quando precisar de ajuda com uma chamada específica.

type Significado
invalid_request_error A requisição tem algum problema (JSON, campos, parâmetros).
authentication_error Chave ausente, inválida, revogada ou expirada.
permission_error A chave não tem permissão para a ação (ex.: chave somente leitura).
not_found_error O recurso ou a rota não existe.
conflict_error Conflito de estado ou de Idempotency-Key.
channel_error Problema com o canal de envio (ex.: WhatsApp desconectado).
rate_limit_error Limite de requisições por minuto excedido.
api_error Erro inesperado do nosso lado.
HTTP code Quando acontece O que fazer
400 invalid_json O corpo não é um JSON válido. Confira aspas, vírgulas e o cabeçalho Content-Type: application/json.
400 missing_field Faltou um campo obrigatório (param diz qual). Envie o campo. Ex.: to ou contact_id em POST /messages.
400 invalid_field Um campo tem valor ou formato inválido (param diz qual). Corrija o valor: UUID malformado, data no passado, texto longo demais, limit fora de 1–100…
400 invalid_phone O telefone não parece um número válido. Envie com DDI e DDD, ex.: 5511999998888.
401 missing_api_key Nenhuma chave foi enviada. Envie Authorization: Bearer tt_live_....
401 invalid_api_key Chave inexistente ou digitada errada. Copie a chave de novo ou crie outra.
401 revoked_api_key A chave foi revogada. Crie uma chave nova no painel.
401 expired_api_key A validade da chave acabou. Crie uma chave nova no painel.
403 read_only_key Chave somente leitura tentou escrever (POST, PATCH, DELETE). Use uma chave com acesso total.
404 resource_not_found O ID não existe (ou é de outra organização). Confira o ID. Ex.: o contato foi apagado no painel.
404 route_not_found O caminho não existe. Confira a URL: ela começa com /v1/ e usa os nomes em inglês (/contacts, /messages…).
405 method_not_allowed O caminho existe, mas não aceita esse método. Ex.: PUT em vez de PATCH. Veja a referência.
409 idempotency_conflict A mesma Idempotency-Key foi usada com um corpo diferente. Gere uma chave nova para cada operação diferente. Veja Idempotência.
409 invalid_state A ação não é possível no estado atual do recurso. Ex.: cancelar uma mensagem agendada que já foi enviada, gerar QR Code para um WhatsApp já conectado, editar uma mensagem depois de 15 minutos, pausar uma campanha que não está enviando. Busque o recurso e confira o status.
422 channel_unavailable Não há WhatsApp conectado para enviar (ou o canal escolhido está desconectado). Em campanhas: não há número do WhatsApp Oficial conectado. Reconecte o canal com POST /channels/{channel_id}/connect (ou no painel, em Configurações → Conexões). Para campanhas, conecte o WhatsApp Oficial no painel, em Campanhas.
422 limit_reached Um limite da conta foi atingido: o máximo de conexões de WhatsApp do plano (POST /channels) ou 10 webhooks por organização (POST /webhooks). Remova itens que não usa mais (ou reconecte um canal existente em vez de criar outro). Para mais conexões, faça upgrade do plano no painel.
429 rate_limit_exceeded Mais de 120 requisições no mesmo minuto com a mesma chave. Espere os segundos do cabeçalho Retry-After. Veja Limites de uso.
500 ou 502 internal_error Erro inesperado do nosso lado. Tente de novo com espera progressiva. Se persistir, fale com o suporte com o request_id.
502 provider_error O WhatsApp recusou a operação. Num envio, a mensagem fica registrada com status failed. Ao conectar, o WhatsApp não devolveu o QR Code ou o código de pareamento. Leia a message. Confira se o número tem WhatsApp e se a mídia é acessível. Não repita em loop.
503 service_unavailable A API está temporariamente indisponível. Tente de novo com espera progressiva. Use Idempotency-Key em POST.
504 timeout A requisição demorou demais para ser respondida (ex.: o WhatsApp demorou para gerar o QR Code). Tente de novo com a mesma Idempotency-Key: se a primeira tiver dado certo, você recebe a resposta original.

Repare que há dois 422 com type diferentes: limit_reached é invalid_request_error e channel_unavailable é channel_error.

422 limit_reached (conexões do plano)
{
"error": {
"type": "invalid_request_error",
"code": "limit_reached",
"message": "Seu plano permite 3 conexões de WhatsApp. Remova uma ou faça upgrade no painel.",
"request_id": "req_6f1d2c3b4a5e"
}
}
  • Decida pelo code, não pela message.
  • Erros 4xx não melhoram com retentativa (exceto 429): corrija a requisição.
  • 429, 500, 503, 504 e falhas de rede podem ser repetidos com espera progressiva (ex.: 1 s, 2 s, 4 s…). Envie Idempotency-Key em POST para não duplicar nada.
  • 502 provider_error é uma recusa do WhatsApp para aquela mensagem: repetir em sequência raramente ajuda e pode prejudicar o número.
Exemplo (Node.js)
async function toptalking(path, options = {}) {
const res = await fetch(`https://platform.toptalking.com.br/v1${path}`, {
...options,
headers: {
Authorization: `Bearer ${process.env.TOPTALKING_API_KEY}`,
'Content-Type': 'application/json',
...options.headers,
},
});
const body = await res.json();
if (!res.ok) {
const { code, message, request_id } = body.error;
const err = new Error(`[${res.status} ${code}] ${message} (request_id: ${request_id})`);
err.status = res.status;
err.code = code;
err.retryAfter = Number(res.headers.get('Retry-After')) || null;
throw err;
}
return body;
}