# Erros

> Formato dos erros da API do FORSI Chat, o que cada status HTTP quer dizer e a tabela com todos os códigos, como janela_fechada e conta_restrita.

Todo erro da API tem o mesmo formato JSON, com um `codigo` fixo que o seu código pode testar. Use o `codigo` (ele não muda); a `mensagem` é só ajuda e pode mudar. `detalhe` diz o campo inválido, o escopo que faltou etc. Mande o `requisicao_id` (também no cabeçalho `X-Request-Id`) ao suporte.

## Como tratar

- **4xx (menos 429)**: o pedido está errado. Corrija antes de repetir; a mesma chamada vai falhar igual.
- **429**: espere os segundos de `Retry-After` e repita (veja [Limites de uso](https://docs.forsi.com.br/limites)).
- **5xx**: repita com espera crescente. No envio de mensagem, com a mesma `Idempotency-Key`.

```json title="resposta 422"
{
  "erro": {
    "codigo": "janela_fechada",
    "mensagem": "A janela de 24 horas desta conversa está fechada. Na API oficial do WhatsApp, só um modelo aprovado reabre a conversa.",
    "requisicao_id": "5d2f0c3e-8b1a-4c6e-9f7d-1a2b3c4d5e6f"
  }
}
```

## Conta restrita pela Meta (`conta_restrita`)

Enquanto a Meta restringe o número por spam e a trava de spam da organização está ligada (Configurações > API), o envio barrado volta `422 conta_restrita` na hora, sem enviar nada. O `erro` traz os campos do objeto `RestricaoMeta` (os mesmos de `caixas[].conexoes[].restricao_meta` no [`GET /me`](https://docs.forsi.com.br/api/conta/me)): `ate` e `desde` (ISO-8601 UTC), `ate_fonte` (`meta` ou `padrao`), `escopo` (`iniciadas` = só modelos; `tudo` = nada sai), `motivo` (`meta_131031`, `meta_368`, `meta_131048`, `account_restriction`, `account_disabled`, `outro`), `motivo_texto`, `caixa_id` e `retry_after_s`. O cabeçalho `Retry-After` repete `retry_after_s`: mostre `ate` ao usuário e tente de novo depois desse tempo. Com a trava desligada, nada é barrado e a restrição só aparece no `GET /me`.

```json title="resposta 422 conta_restrita"
{
  "erro": {
    "codigo": "conta_restrita",
    "mensagem": "A Meta restringiu esta conta por spam até 25/10/2026 às 11:00 (horário de Brasília): mensagens que abrem conversa (modelos) estão barradas; respostas dentro da janela de 24 h saem.",
    "ate": "2026-10-25T14:00:00Z",
    "desde": "2026-10-24T14:00:00Z",
    "ate_fonte": "padrao",
    "escopo": "iniciadas",
    "motivo": "meta_131031",
    "motivo_texto": "A Meta travou a conta do WhatsApp (131031).",
    "caixa_id": "0b6f5a52-3c1d-4e8f-9a7b-2c4d6e8f0a1b",
    "retry_after_s": 86400,
    "api_recusa": true,
    "requisicao_id": "5d2f0c3e-8b1a-4c6e-9f7d-1a2b3c4d5e6f"
  }
}
```

## Status HTTP

| Status | Quando |
| --- | --- |
| 400 | JSON inválido ou cabeçalho mal formado. |
| 401 | Chave ausente, inválida, revogada, vencida ou fora dos IPs permitidos. A resposta é sempre a mesma, de propósito. |
| 403 | Sem permissão: escopo que falta, plano sem API (ou sem o módulo), assinatura suspensa, chamada pelo navegador ou sem https. |
| 404 | Não existe, ou é de outra organização (para a API, é a mesma coisa). |
| 409 | Conflito: registro repetido, horário ocupado, `Idempotency-Key` reaproveitada com outro corpo. |
| 413 | Corpo acima de 64 KB. |
| 415 | Corpo que não é JSON. |
| 422 | Dados inválidos ou regra de negócio (ex.: janela de 24 h fechada). Veja `codigo` e `detalhe`. |
| 429 | Passou do limite. Espere os segundos de `Retry-After`. |
| 500 / 503 | Erro do nosso lado ou relatório que demorou demais. Pode tentar de novo (no envio, com a mesma `Idempotency-Key`). |

## Perguntas frequentes

### O que mando ao suporte?

O `requisicao_id` da resposta (também no cabeçalho `X-Request-Id`), a hora e a rota chamada. Nunca mande a chave.

### Por que recebo 404 num id que existe?

Porque ele é de outra organização ou foi apagado. A chave enxerga só a organização dela e, para a API, as duas coisas são iguais.

### A mensagem do erro pode mudar?

Pode. A `mensagem` é para pessoas e pode mudar de texto. O `codigo` não muda: é ele que o seu código deve testar.

## Todos os códigos

| codigo | O que significa |
| --- | --- |
| `nao_autorizado` | Chave de API ausente, inválida, revogada, vencida ou fora dos IPs permitidos. Mande "Authorization: Bearer fcv2_live_...". |
| `modulo_fora_do_plano` | A API não está liberada para esta organização: o plano não inclui a API ou a assinatura não está ativa (teste vencido, conta em modo leitura). Fale com um dono. |
| `escopo_insuficiente` | Esta chave não tem permissão para esta operação. |
| `limite_excedido` | Muitas requisições. Espere o tempo de Retry-After e tente de novo. |
| `muitas_falhas` | Muitas tentativas com chave errada deste endereço. Espere o tempo de Retry-After. |
| `operacao_invalida` | Rota não encontrada. |
| `recurso_inexistente` | Não encontrado. |
| `metodo_nao_permitido` | Método não permitido nesta rota. |
| `https_obrigatorio` | Use https. |
| `origem_nao_permitida` | A chave de API é secreta: chame a API do seu servidor, nunca do navegador. |
| `corpo_grande` | Corpo grande demais (máximo de 64 KB). |
| `tipo_de_conteudo` | Mande o corpo como JSON (Content-Type: application/json). |
| `json_invalido` | O corpo não é um JSON válido. |
| `dados_invalidos` | Dados inválidos. Confira o campo indicado em "detalhe". |
| `idempotencia_invalida` | Idempotency-Key deve ter de 1 a 200 caracteres visíveis, sem espaço. |
| `idempotencia_obrigatoria` | Envie Idempotency-Key ou id_cliente para identificar a mensagem. |
| `idempotencia_em_andamento` | Este envio ainda está em andamento. Repita a consulta em instantes. |
| `idempotencia_conflito` | Esta Idempotency-Key já foi usada com outro corpo. Use uma chave nova para um pedido novo. |
| `conflito` | Conflito com um registro que já existe. |
| `erro_interno` | Erro do nosso lado. Já ficou registrado; tente de novo em instantes. |
| `indisponivel` | Serviço indisponível no momento. Tente de novo em instantes. |
| `cursor_invalido` | Cursor inválido. Use o valor de "proximo" da página anterior. |
| `tipo_invalido` | tipo deve ser texto, imagem, video, audio, documento ou modelo. |
| `texto_vazio` | Mensagem de texto precisa de texto. |
| `texto_longo` | Texto longo demais (máximo de 4096 caracteres). |
| `midia_invalida` | Link de mídia inválido: use https com um endereço público. |
| `midia_indisponivel` | O arquivo desta mídia está indisponível. |
| `midia_baixando` | O download desta mídia está na fila. Tente novamente após Retry-After. |
| `janela_fechada` | A janela de 24 horas desta conversa está fechada. Na API oficial do WhatsApp, só um modelo aprovado reabre a conversa. |
| `conta_restrita` | A Meta restringiu esta conta do WhatsApp por spam. Nada foi enviado: erro.ate diz até quando (erro.retry_after_s e o cabeçalho Retry-After, em segundos), erro.escopo o que está barrado e erro.motivo o código. Quem administra pode desligar a trava em Configurações > API. |
| `caixa_obrigatoria` | A organização tem mais de um WhatsApp conectado: informe caixa_id (veja GET /me). |
| `caixa_sem_conexao` | Nenhum WhatsApp conectado nesta caixa. |
| `canal_sem_iniciar` | Este canal não permite começar conversa por telefone. Use uma caixa de WhatsApp. |
| `modelo_sem_api_oficial` | Modelos só saem pela API oficial do WhatsApp. Conecte a API oficial nesta caixa. |
| `modelo_inexistente` | Modelo não encontrado nesta caixa (veja GET /modelos). |
| `canal_invalido` | canal deve ser "auto", "oficial" ou "qr". |
| `canal_so_whatsapp` | canal "oficial"/"qr" só vale em caixa de WhatsApp. Omita o campo (ou use "auto"). |
| `canal_oficial_indisponivel` | canal "oficial": a API oficial do WhatsApp não está conectada nesta caixa. Nada foi enviado pelo QR. |
| `canal_oficial_sem_grupo` | canal "oficial": a API oficial do WhatsApp não envia para grupo. Use "qr" ou omita o campo. |
| `canal_oficial_tipo` | canal "oficial": a API oficial do WhatsApp não envia este tipo de mensagem. Nada foi enviado pelo QR. |
| `canal_qr_indisponivel` | canal "qr": o WhatsApp por QR não está conectado nesta caixa. Nada foi enviado pela API oficial. |
| `canal_qr_sem_modelo` | canal "qr": modelos só saem pela API oficial do WhatsApp. Use "oficial" ou omita o campo. |
| `canal_qr_tipo` | canal "qr": este tipo de mensagem só sai pela API oficial do WhatsApp. Nada foi enviado pela API oficial. |
| `mensagem_inexistente` | Mensagem não encontrada. |
| `conversa_inexistente` | Conversa não encontrada. |
| `contato_inexistente` | Contato não encontrado. |
| `caixa_inexistente` | Caixa não encontrada (veja GET /me). |
| `webhook_inexistente` | Webhook não encontrado. |
| `entrega_inexistente` | Entrega não encontrada. |
| `webhook_desativado` | Este webhook está desativado. Reative com PATCH {"ativo": true}. |
| `entrega_em_andamento` | Esta entrega ainda está em andamento. |
| `entrega_ja_despachada` | Esta entrega já saiu uma vez e não é repetida (entrega única, sem duplicar). Só entregas que nunca saíram podem ser reenviadas. |
| `url_invalida` | URL inválida: use https://, porta 443 e um nome de domínio público. |
| `destino_bloqueado` | Esse endereço aponta para uma rede interna ou reservada. Use um endereço público. |
| `dns_falhou` | Não conseguimos resolver esse domínio. Confira o endereço. |
| `eventos_invalidos` | Algum evento não existe. Veja a lista na documentação. |
| `limite_de_webhooks` | Limite de 10 webhooks por organização. |
| `nome_invalido` | Nome deve ter de 1 a 60 caracteres. |
| `telefone_invalido` | Telefone inválido. Mande com DDI e DDD. |
| `telefone_repetido` | Já existe um contato com esse telefone (com ou sem o 9). |
| `graca_invalida` | horas deve ser de 0 a 168. |
| `negocio_inexistente` | Negócio não encontrado. |
| `etapa_inexistente` | Etapa não encontrada (veja GET /funis). |
| `funil_inexistente` | Funil não encontrado. |
| `nota_inexistente` | Nota não encontrada. |
| `etapa_fora_do_funil` | Essa etapa não pertence ao funil informado. |
| `etapa_ganha_e_perdida` | Uma etapa não pode ser de ganho e de perda ao mesmo tempo. |
| `estado_invalido` | estado deve ser aberto, ganho ou perdido. |
| `valor_invalido` | O valor não pode ser negativo. |
| `limite_de_funis` | Limite de 20 funis por organização. |
| `limite_de_etapas` | Limite de 30 etapas por funil. |
| `limite_de_notas` | Limite de 500 notas por negócio. |
| `periodo_longo` | Escolha um período de até 366 dias. |
| `periodo_invalido` | Período inválido: `de` precisa ser antes de `ate` (AAAA-MM-DD). |
| `granularidade_invalida` | granularidade deve ser dia, semana ou mes. |
| `caixa_invalida` | Caixa não encontrada nesta organização (veja GET /me). |
| `limite_relatorios` | Relatórios têm limite próprio, mais baixo. Espere o tempo de Retry-After. |
| `relatorio_demorou` | O relatório demorou demais. Escolha um período menor ou uma granularidade maior (semana ou mes). |
| `assinatura_bloqueada` | A assinatura da organização está suspensa. Fale com um dono. |
| `horario_invalido` | Data e hora inválidas. Use o formato 2026-10-12T14:00:00-03:00 (sempre com o fuso), com o fim depois do início. |
| `janela_grande` | A janela de consulta passa do máximo (62 dias). |
| `duracao_invalida` | Duração inválida: de 5 a 720 minutos (compromisso de até 12 horas). |
| `campo_longo` | Um dos textos passa do tamanho máximo. O campo vem em "detalhe". |
| `campo_invalido` | Campo obrigatório ou inválido. O campo vem em "detalhe". |
| `link_invalido` | O link precisa começar com https://. |
| `contato_ambiguo` | Informe só um entre contato_id, conversa_id e telefone. |
| `conversa_de_outro_contato` | A conversa informada é de outro contato. |
| `evento_cancelado` | O compromisso está cancelado e não pode ser alterado. Marque um novo. |
| `evento_finalizado` | O compromisso já foi encerrado (concluído ou faltou) e não pode ser alterado. |
| `horario_ocupado` | Esse horário já está ocupado nessa agenda. |
| `horario_bloqueado` | Esse horário está bloqueado (folga, almoço ou feriado). |
| `fora_do_horario` | Esse horário está fora do horário de trabalho da agenda. |
| `antecedencia` | Esse horário está mais perto do que a antecedência mínima da agenda. |
| `compromisso_estado_invalido` | estado só pode ser concluido ou faltou. Para confirmar ou cancelar, use as rotas próprias. |
| `nada_para_atualizar` | Mande ao menos um campo para atualizar. |
| `fuso_invalido` | Fuso inválido. Use um nome IANA, como America/Sao_Paulo. |
| `cor_invalida` | Cor inválida. Use slate, blue, violet, amber, emerald, green, rose, cyan ou orange. |
| `lembretes_invalidos` | Lembretes inválidos: até 5 itens, cada um só com antes_min (1 a 43200). |
| `usuario_inexistente` | usuario_id não é de uma pessoa desta equipe. |
| `agenda_inexistente` | Agenda não encontrada (ou inativa, para marcar compromisso). |
| `evento_inexistente` | Compromisso não encontrado. |
| `bloqueio_inexistente` | Bloqueio não encontrado. |
| `agenda_repetida` | Essa pessoa já tem uma agenda. |
| `limite_agendas` | Limite de 100 agendas por organização. |
| `limite_bloqueios` | Limite de 500 bloqueios por organização. |
| `bloqueio_tipo_invalido` | tipo deve ser folga, almoco, feriado ou outro. |
| `repeticao_invalida` | repetir deve ser nunca, diario, semanal ou anual; repetir_ate só vale com repetição. |
| `sem_permissao` | A chave de API não pode fazer isso. Veja o motivo em "detalhe". |
| `ja_e_membro` | Esse e-mail já é de alguém da equipe. |
| `limite_de_acessos` | O plano chegou ao limite de acessos (pessoas + convites abertos). Remova alguém ou cancele um convite. |
| `limite_de_convites` | Limite de convites: 20 por dia por organização e 3 por dia para o mesmo e-mail. Tente amanhã. |
| `membro_inexistente` | Pessoa não encontrada nesta organização (veja GET /equipe/membros). |
| `convite_inexistente` | Convite não encontrado, já aceito ou vencido (veja GET /equipe/convites). |
| `equipe_inexistente` | Equipe não encontrada (veja GET /equipe/equipes). |
| `equipe_repetida` | Já existe uma equipe com esse nome. |
| `papel_inexistente` | Papel de acesso não encontrado nesta organização. |
| `modulos_do_papel` | Com papel de acesso, os módulos e a agenda vêm do papel. Mande papel_de_acesso_id: null para escolher à mão. |
| `regra_inexistente` | Regra de comentário não encontrada (veja GET /regras-comentario). |
| `regra_conexao_invalida` | conexao_id precisa ser uma conta do Instagram conectada por login (veja GET /instagram/contas). |
| `regra_sem_palavras` | Informe de 1 a 30 palavras, ou use qualquer_comentario: true. |
| `regra_modo_invalido` | modo deve ser contem ou igual. |
| `regra_sem_acao` | A regra precisa de uma resposta pública ou de uma resposta privada. |
| `regra_texto_longo` | Texto longo demais: resposta pública até 2200 caracteres e resposta privada até 1000. |
| `regra_variantes_demais` | No máximo 5 respostas_publicas. |
| `regra_extra_sem_publico` | respostas_publicas e ocultar_apos só valem com responder_publico preenchido. |
| `regra_automacao_invalida` | automacao_id não é uma automação desta organização (veja GET /automacoes?gatilho=comentario). |
| `regra_automacao_sem_privada` | Para ligar uma automação, preencha resposta_privada. |
| `regra_botao_longo` | Cada botão tem no máximo 20 caracteres. |
| `regra_botao_repetido` | Botões repetidos. Cada botão deve ser diferente. |
| `regra_botoes_demais` | No máximo 3 botões. |
| `regra_botoes_invalidos` | botoes deve ser uma lista de textos ou de objetos { titulo, url }. |
| `regra_botao_url_invalida` | A url do botão deve ser um link https:// válido, com até 2000 caracteres. |
| `regra_botoes_sem_privada` | Para ter botões, preencha resposta_privada. |
| `recurso_desligado` | Este recurso não está liberado para a sua organização. |
| `seguir_invalido` | Algum campo de `seguir` é inválido. A mensagem diz qual: textos de 1 a 640 caracteres (os de "já segue" e "seguiu depois" podem ser vazios), botões de 1 a 20 e sem `{` (botão não troca variáveis), cada texto até 900 bytes (emoji e acento contam mais), sem caractere de controle ou invisível, `max_tentativas` de 1 a 50 e link do conteúdo em https. |
| `limite_de_regras` | Limite de 200 regras de comentário por organização. Apague alguma para criar outra. |
| `modulo_invalido` | Módulo inválido. Use conversas, contatos, automacoes, agentes, funil, agenda, followup ou relatorios. |

---

Página: https://docs.forsi.com.br/erros · Índice: https://docs.forsi.com.br/llms.txt · Tudo num arquivo: https://docs.forsi.com.br/llms-full.txt
