Erros
O formato único de erro da API, o que cada status significa e o que fazer com cada código.
Quando algo dá errado, a API responde com um status HTTP de erro e sempre o mesmo JSON. Este é o mapa para tratar cada caso.
O formato
Todo erro, de qualquer rota, vem assim:
{
"error": {
"code": "whatsapp_window_closed",
"message": "The 24-hour customer service window is closed. Send an approved template instead."
}
}| Campo | O que é |
|---|---|
error.code | Código estável, para o seu programa decidir o que fazer. Não muda |
error.message | Texto para pessoas, em inglês. Pode mudar: não compare com ele |
| Outros campos | Detalhes de alguns erros, ao lado de code e message. Por exemplo available em out_of_stock, issues em validation_error, retryAfterSec em rate_limited |
Um jeito simples de ler:
const res = await fetch(url, options);
if (!res.ok) {
const { error } = await res.json().catch(() => ({ error: {} }));
const retryAfter = res.headers.get("Retry-After"); // no 429 e no 409 idempotency_key_in_progress
throw Object.assign(new Error(error.message), { status: res.status, code: error.code, details: error, retryAfter });
}Status HTTP
| Status | Significa |
|---|---|
400 | O pedido está errado: JSON inválido, campo que falta ou com valor inválido, regra do modelo não cumprida |
401 | Chave ausente, inválida, revogada ou expirada (veja Autenticação) |
402 | Envio recusado por cobrança |
403 | A chave não pode fazer isso: publicável fora de lojas e modelos, ou chave somente leitura tentando escrever |
404 | Não existe, é de outra organização, ou o ID não é um UUID (as respostas são iguais de propósito) |
409 | Conflito com o estado atual: estoque, etapa do pedido, contato repetido, WhatsApp desconectado, envio em andamento |
422 | A regra do WhatsApp não permite (janela de 24 horas, número sem WhatsApp, opt-out de marketing), ou um Idempotency-Key reaproveitado com outro pedido |
429 | Limite de requisições da sua chave, ou o WhatsApp pediu para esperar. Respeite Retry-After |
500 | Erro do Vamo (internal_error). Tente de novo mais tarde |
502 | O WhatsApp não processou o envio |
Códigos gerais
Valem para todas as rotas.
| Código | Status | O que aconteceu | O que fazer |
|---|---|---|---|
missing_api_key, invalid_api_key, api_key_revoked, api_key_expired | 401 | Problema com a chave | Veja Autenticação |
publishable_key_read_only, publishable_key_forbidden, read_only_key | 403 | A chave não tem esse acesso | Use uma chave secreta com Leitura e escrita |
invalid_json | 400 | O corpo não é um JSON válido | Confira o corpo e o Content-Type: application/json |
validation_error | 400 | Um campo falta ou tem valor inválido, no corpo ou na query string (page=abc, status fora da lista) | message diz o campo (phone: …) e issues traz todos: [{ "path": "phone", "message": "…" }] |
not_found | 404 | O recurso não existe na sua organização | Confira o ID |
rate_limited | 429 | A sua chave passou do limite por minuto | Espere os segundos de Retry-After (veja Limites de requisição) |
invalid_idempotency_key | 400 | Idempotency-Key com mais de 200 caracteres | Use uma chave menor |
idempotency_key_reused | 422 | A mesma Idempotency-Key com outro pedido | Use uma chave nova para cada operação |
idempotency_key_in_progress | 409 | A primeira requisição com essa chave ainda está rodando | Tente de novo em 1 segundo |
internal_error | 500 | Erro do Vamo | Tente de novo com espera crescente |
Erros de envio pelo WhatsApp
Vêm de POST /messages/send e POST /templates/send, e aparecem por item no envio em massa.
| Código | Status | O que aconteceu | O que fazer |
|---|---|---|---|
whatsapp_window_closed | 422 | O cliente não escreveu nas últimas 24 horas | Envie um modelo aprovado |
whatsapp_recipient_unavailable | 422 | O número não recebe WhatsApp, ou o contato não tem número | Confira o telefone do contato |
whatsapp_marketing_opt_out | 422 | O cliente pediu para não receber marketing | Não envie modelos de marketing para ele; utilidade continua valendo |
whatsapp_template_error | 422 | O WhatsApp recusou o modelo: pausado, desativado, ou variáveis que não batem | Confira o status do modelo e envie um valor para cada variável |
whatsapp_busy | 409 | Outra mensagem para o mesmo contato está saindo agora | Tente de novo em alguns segundos |
whatsapp_not_connected | 409 | O WhatsApp da loja não está conectado | Conecte o número no Vamo |
trial_marketing_blocked | 409 | Modelo de marketing durante o período de teste | Envie depois do teste, ou use um modelo de utilidade |
whatsapp_rate_limited | 429 | A Meta segurou os envios do número | Espere os segundos de Retry-After (60, se não vier) e tente de novo |
whatsapp_billing | 402 | O WhatsApp recusou por cobrança | Fale com o suporte do Vamo |
billing_marketing_restricted | 402 | Há uma fatura do Vamo vencida: marketing pausado. Respostas e utilidade continuam | Regularize em Configurações → Faturamento |
whatsapp_upstream_error | 502 | O WhatsApp não processou | Tente mais tarde |
Quando o WhatsApp chegou a receber a tentativa, ela fica gravada na conversa como failed. Em GET /messages/:id, errorCode traz então o código da própria Meta (por exemplo 131047 para janela fechada, 131026 para número sem WhatsApp).
Códigos de outras rotas
| Rota | Códigos |
|---|---|
| Contatos | contact_exists (com contactId), contact_has_orders |
| Modelos | invalid_phone, template_not_approved, template_not_sendable, template_header_variable_too_long, no_active_store |
| Pedidos | product_not_found, inactive_product, variant_required, variant_not_found, mixed_currency, total_too_large, out_of_stock, invalid_transition, order_managed_by_store, order_in_review |
| Envio em massa | Por item: os códigos de envio acima, not_found e internal_error |
| Webhooks | webhook_disabled_test_first |
Quando tentar de novo
| Resposta | Tentar de novo? |
|---|---|
429 | Sim, depois de Retry-After |
409 whatsapp_busy, 409 idempotency_key_in_progress, 502, 500 | Sim, com espera crescente |
Um POST sem resposta (a rede caiu) | Sim, com o mesmo Idempotency-Key: o Vamo não envia nem cria de novo (veja Idempotência) |
400, 401, 403, 404, 422 | Não: corrija o pedido antes |