# Erros da API

Gerado do catálogo de erros da própria API (`npm run skills:gerar`). Todo erro vem como
`{ "error": "<código>", "message": "<frase>" }`, às vezes com campos a mais (`missing` no 402, `nextOpenAt` no 409
da janela, `Retry-After` no 429). Mostre a `message` ao usuário e diga o próximo passo.

| HTTP | Código | Quando |
| --- | --- | --- |
| 400 | `invalid_request` | Campo obrigatório ausente ou com valor fora do aceito. |
| 400 | `invalid_json` | O corpo não é um JSON válido. |
| 400 | `invalid_idempotency_key` | Idempotency-Key com mais de 200 caracteres ou com espaço. |
| 400 | `invalid_contact` | O contato não é um e-mail válido nem um telefone com DDD (opt-in e envio para um contato), ou o canal não atende esse número (ligação só para o Brasil). |
| 400 | `invalid_collected_at` | Opt-in: "collectedAt" não é data ISO 8601 ou está no futuro. |
| 400 | `LGPD_CONSENT_HEADER_MISSING` | Disparo sem o cabeçalho X-LGPD-Consent-Logged: true. |
| 400 | `INVALID_CHANNELS` | Disparo sem canal ou com canal desconhecido. |
| 400 | `MESSAGE_REQUIRED` | Disparo sem "message". |
| 400 | `MESSAGE_TOO_LONG` | Mensagem acima de 1.000 caracteres. |
| 400 | `CONTACTS_REQUIRED` | Disparo sem contatos. |
| 400 | `TOO_MANY_CONTACTS` | Mais de 30 mil contatos numa chamada. |
| 400 | `PHONE_REQUIRED` | Canal de telefone escolhido e nenhum contato com "phone". |
| 400 | `EMAIL_REQUIRED` | Canal de e-mail escolhido e nenhum contato com "email". |
| 400 | `EMAIL_LEGITIMATE_INTEREST_REQUIRED` | Canal de e-mail sem "emailLegitimateInterestAck" igual à versão em vigor da declaração do legítimo interesse ("provisorio-2026-10-13"): a sua empresa declara que envia por legítimo interesse (LGPD, art. 7º, IX), com assunto ligado à atividade profissional do contato e o link para sair da lista. |
| 400 | `SMS_TOO_LONG` | A mensagem passaria de 1 SMS: 160 caracteres, já sem os acentos (a plataforma os tira) e com o "P/ SAIR digite SAIR". "units" diz quantos ela ocupa. |
| 401 | `unauthorized` | Chave ausente, inválida ou revogada. |
| 402 | `CREDITOS_INSUFICIENTES` | Saldo insuficiente; "missing" diz quanto falta por carteira. |
| 403 | `account_suspended` | A conta da chave está suspensa. |
| 403 | `signup_confirmation_required` | A conta da chave, criada pelo login da empresa (SSO), ainda não aceitou os Termos de Uso e a Política de Privacidade nem confirmou ter 18 anos ou mais. O titular confirma ao entrar no painel; depois a chave volta a funcionar. |
| 403 | `insufficient_scope` | A chave não tem o método desta rota ("method" diz qual). Edite a chave em Minha Conta › Integrações e marque o método. |
| 403 | `key_suspended` | A chave foi suspensa pela equipe OneClick Sales. |
| 403 | `plan_feature_api` | O plano da conta não inclui a API (Minha Conta › Plano). A chave continua salva e volta a funcionar num plano com API e webhooks. |
| 403 | `plan_expired` | O plano da conta venceu: a API não faz consultas, extrações nem envios, e o webhook de eventos só avisa o pagamento confirmado. Só respondem POST /v1/billing/renew-plan e GET /v1/billing/payments/{paymentId} (renovar pela API); a chave continua salva e volta a funcionar com o plano em vigor. |
| 403 | `plan_required` | A conta não tem plano em vigor (sem validade gravada). A API só funciona com um plano pago em vigor que inclua a API. |
| 403 | `api_disabled` | A API foi desligada para a conta pela equipe OneClick Sales (o motivo vem na mensagem). |
| 403 | `ip_not_allowed` | A chave tem lista de IPs e a chamada veio de outro ("ip" diz qual). |
| 403 | `email_unverified` | O e-mail de login da conta ainda não foi confirmado (link enviado no cadastro). Nada é enviado nem cobrado. |
| 403 | `CADASTRO_INCOMPLETO` | O cadastro da empresa (CNPJ, endereço) está incompleto; "missing" lista o que falta. |
| 403 | `test_key_not_allowed` | Chave de teste numa operação que cobra ou conecta número. |
| 403 | `contact_blocked` | Envio para um contato: o contato está na lista de bloqueio (pediu para sair); "suppressionLevel" diz qual lista. Nada é cobrado. |
| 403 | `contact_opt_out` | Lista de bloqueio: o próprio contato pediu para sair (SAIR por WhatsApp ou SMS, link de descadastro, "não receber mais" da Meta no WhatsApp, pedido na ligação ou na sala com avatar ao vivo) — o bloqueio só sai se ele voltar a autorizar. |
| 403 | `platform_block` | Lista de bloqueio: o bloqueio foi aplicado pela equipe OneClick Sales e só sai pelo suporte. |
| 403 | `plan_inactive` | Envio para um contato: o plano da conta não está ativo. |
| 403 | `biometric_consent_revoked` | Vídeo: o titular da conta retirou o consentimento para dado biométrico (LGPD, Art. 11); os avatares criados no painel não geram vídeo até um novo aceite em Minha Conta › Ligações e vídeo. Nada é enviado nem cobrado. |
| 404 | `not_found` | O disparo, envio ou pagamento não existe nesta conta. |
| 404 | `not_implemented` | O endpoint não existe na API. |
| 405 | `method_not_allowed` | MCP (/v1/mcp): o servidor MCP responde só por POST (Streamable HTTP, sem sessão). |
| 409 | `outside_send_window` | Fora da janela de envio (WhatsApp e voz: 08:00–12:00 e 13:30–22:00, todos os dias; SMS: segunda a sábado, 09:00–12:00 e 13:30–22:00; Brasília); "nextOpen" diz a hora e "nextOpenAt" a data e a hora da abertura; no SMS, "reasonCode": "outside_sms_window". |
| 409 | `idempotency_in_progress` | Outra chamada com a mesma Idempotency-Key ainda está em andamento. |
| 409 | `daily_outreach_limit` | Envio para um contato: ele já foi abordado hoje neste canal (uma abordagem por dia). |
| 409 | `channel_not_configured` | Envio para um contato: o canal não tem provedor configurado nesta conta. |
| 409 | `whatsapp_not_connected` | Envio de WhatsApp: nenhum número da conta está conectado (veja GET /v1/channels). |
| 409 | `template_required` | WhatsApp Oficial: passou de 24 h desde a última mensagem do contato; só modelo aprovado ("template"). |
| 409 | `human_mode` | Ligação ou vídeo: a conta está no modo atendente humano (Minha Conta › Ligações e vídeo). |
| 409 | `dispatch_in_progress` | Um envio para este contato ainda está em andamento; tente depois do Retry-After. |
| 409 | `conflict` | Envio para um contato: o envio não pôde ser feito agora (o motivo vem em "message"). |
| 422 | `content_blocked` | O texto tem termo proibido pela política de conteúdo (apostas, jogos de azar, ameaças, ofensas, golpes, drogas, armas, conteúdo adulto, propaganda eleitoral); "categories" e "terms" dizem o quê. Link encurtado (bit.ly, tinyurl...) também é recusado (categoria "link_encurtado"): use o link completo. Nada é enviado nem cobrado. |
| 422 | `recipient_rejected` | Envio de e-mail: o servidor do destinatário recusou o endereço (não existe, caixa cheia ou desativada). "hardBounce": true = o endereço não existe e foi bloqueado para novos envios (o próximo responde "contact_blocked"). Nada é cobrado; não repita o mesmo envio. |
| 413 | `payload_too_large` | Corpo acima do limite da rota: 16 MB no disparo em massa (POST /v1/dispatches/mass) e 2 MB nas demais rotas. |
| 429 | `too_many_active_dispatches` | Já há 3 disparos em andamento nesta conta. |
| 429 | `rate_limited` | Requisições demais: o limite por minuto da chave no tipo da chamada ("kind": leitura, alteração ou envio; padrão 60, 60 e 120 — veja GET /v1/account/limits), 600/min por IP, ou o limite anti-bloqueio do número de WhatsApp. Respeite o Retry-After e os cabeçalhos X-RateLimit-*. |
| 429 | `account_send_daily_limit` | Envio para um contato: a conta chegou ao limite diário de envios do canal que ela mesma definiu em Segurança (WhatsApp ou SMS); "resumeAt" diz quando volta. Nada é enviado nem cobrado. O ritmo por hora da conta responde como "rate_limited". |
| 429 | `daily_quota_exceeded` | A conta chegou ao limite de chamadas do dia (todas as chaves do mesmo ambiente somadas). Volta à meia-noite de Brasília (Retry-After). |
| 500 | `internal_error` | Erro inesperado do servidor (a equipe é avisada). |
| 502 | `charge_failed` | O gateway não gerou a cobrança. |
| 502 | `status_failed` | O gateway não respondeu o status do pagamento. |
| 502 | `pairing_failed` | Não foi possível iniciar o pareamento do número. |
| 502 | `provider_failed` | Envio para um contato: o provedor do canal recusou ou falhou. Nada foi cobrado. |
| 503 | `unavailable` | Banco de dados indisponível no momento; tente de novo (Retry-After). |
| 503 | `feature_unavailable` | A função pedida (canal, servidor ou ferramenta) está em manutenção na plataforma; "feature" diz qual. Nada é enviado nem cobrado; tente de novo depois do Retry-After. No disparo em massa, os contatos dela esperam e saem quando ela voltar. |
| 503 | `charge_mark_failed` | Envio para um contato: não foi possível registrar a cobrança do envio (banco de dados instável). Nada foi enviado e o crédito foi devolvido; tente de novo (Retry-After). |
| 503 | `sending_paused` | Envio para um contato: os envios da plataforma estão pausados pela equipe OneClick Sales (freio geral). Nada foi enviado nem cobrado; tente de novo depois do Retry-After. O disparo em massa espera sozinho (status "waiting") e continua do mesmo contato. |
