Skip to content
WhatIsUp.dev

Erros

Todo corpo de resposta 4xx e 5xx usa o mesmo envelope:

{
  "error": {
    "code": "channel_unavailable",
    "message": "Channel is not connected. Re-pair to continue.",
    "details": { "channel_id": "..." }
  },
  "request_id": "req-3f7a1c02"
}

Faça match no code — ele é o contrato estável. message é legível por humanos e pode mudar entre releases. details é opcional e específico de cada código.

O conjunto completo de códigos vem no contrato Zod ERROR_CODES. A tabela abaixo é canônica.

Auth / identidade

CódigoQuando você vai ver
auth_missingNenhum header Authorization enviado.
auth_invalidO token bearer não corresponde a nenhuma chave ativa.
auth_malformedHeader presente mas não Bearer …, ou formato de token errado.
auth_expiredA chave ou o token passou da validade. (Revogação é auth_revoked.)
auth_no_emailO token de sessão do dashboard não tem email verificado.
auth_revokedA chave existia e foi revogada.
auth_backend_unavailable503, não 401. Seu token era válido; nossa busca de usuário falhou. Retente e mantenha a sessão — não deslogue o usuário.

Ciclo de vida do canal

CódigoQuando você vai ver
channel_not_foundO UUID do canal não existe (ou pertence a outro cliente).
channel_access_deniedChave de API escopada por canal sendo usada contra um canal diferente.
insufficient_scope403. Os scopes da chave não cobrem esta rota. details traz required e granted. Um array scopes vazio é irrestrito e nunca dispara isso.
channel_unavailableO canal está em estado terminal (logged_out, stopped_by_user, disabled_by_admin, error, failed).
channel_scoped_keyA chave está escopada a um único canal, mas uma rota multi-canal foi chamada.
invalid_lifecycle_transitionTentou dar connect num canal já conectado, etc.
pair_code_unavailableO estado do canal não permite gerar um código de pareamento agora.
pair_code_failedO upstream rejeitou a requisição do código de pareamento.
no_qrQR ainda não pronto (o canal não inicializou), ou nenhum QR para este estado.
not_disabledTentou reativar um canal que não foi desativado por admin.
concurrent_modificationDuas escritas colidiram na mesma linha; refaça seu read-modify-write.

Plano / cota

CódigoQuando você vai ver
plan_channel_limitLimite de canais do plano atingido. Faça upgrade ou apague um canal existente.
rate_limitedUm token bucket esgotou. X-RateLimit-Scope diz qual (customer, channel ou ip). Os buckets são por conta e por canal, não por chave. Respeite o Retry-After.
worker_at_capacityNenhum worker tem vaga livre agora — extremamente raro; refaça a retentativa.
trial_expired402. Teste acabou sem plano pago. Bloqueia envios, stories, presença e criação de canal; leituras continuam.
payment_overdue402. Conta em atraso. Mesmo bloqueio acima.
sse_connection_limit429. Mais de 10 streams /v1/events simultâneos na conta.

Webhook + mídia

CódigoQuando você vai ver
webhook_endpoint_not_foundO UUID do endpoint não existe.
media_gone410. Token válido, mas os bytes passaram da retenção. Permanente — não adianta retentar.
media_token_expired401. O token de mídia assinado expirou.
media_token_tampered401. A assinatura do token de mídia não confere.
media_token_malformed401. O token de mídia não é parseável.
media_too_large413. A mídia passa do teto de 25 MB.
media_fetch_failed400. Não conseguimos buscar seu source_url (DNS, não-2xx, ou timeout).
media_fetch_blocked400. source_url resolve para endereço privado / loopback / link-local.
message_not_found404. Nenhuma mensagem com esse id nesse canal.
chat_not_found404. Nenhum chat assim nesse canal.
contact_not_found404. Nenhum contato assim nesse canal.

Genéricos

CódigoQuando você vai ver
invalid_requestCorpo ou query falhou na validação Zod. details contém a lista de problemas.
not_found404 genérico.
bad_request400 genérico onde nenhum código mais específico se encaixa.
no_opA mutação não teve efeito (já estava no estado-alvo).
otherCatch-all para erros do provedor upstream.
internal_errorExceção não tratada no servidor. Somos alertados; request_id é a chave de rastreamento.
undeliverable_recipient400. to é um @lid, tem mais de 15 dígitos, não é numérico, tem sufixo desconhecido, ou o WhatsApp diz que o número não está registrado. details.to carrega o valor.
not_implemented501. O endpoint existe mas é um stub declarado (GET /v1/channels/:id/stories, GET /v1/channels/:id/calls).
payload_too_large413. O corpo da requisição passou do limite do servidor.

Esta lista não é fechada. Compare por code sempre com um ramo default — códigos novos entram sem bump de versão maior, e algumas rotas emitem códigos fora do conjunto central documentado aqui.

Boas práticas

  • Sempre registre o request_id. O suporte ao cliente usa ele para achar a requisição exata nos nossos traces.
  • Faça match no code, nunca na message. As mensagens são afinadas para legibilidade humana e mudam com o tempo.
  • Trate códigos desconhecidos como transitórios. Novos códigos são adicionados; assuma que dá pra retentar até a documentação ser atualizada.
  • Para 429, respeite o Retry-After em vez de chutar o backoff.