# POST /regras-comentario — Criar regra de comentário

- URL: `POST https://chat.forsi.com.br/api/v1/regras-comentario`
- Acesso: escopo `automacoes:escrever` · módulos do plano: API + Automações · aceita `Idempotency-Key`
- Sucesso: `201`, `{"dados": ...}` com `RegraComentario`
- Página: https://docs.forsi.com.br/api/automacoes/criar-regra-comentario (Markdown: https://docs.forsi.com.br/api/automacoes/criar-regra-comentario.md)

Nasce desligada, a menos que mande `ativo: true`. Informe `post_id`: sem ele a regra vale para todas as publicações. A primeira regra que combinar com o comentário vale. Até 200 regras por organização (422 `limite_de_regras`). Com `tipo: "seguir"` ("Seguir para receber") a pessoa precisa seguir a conta para receber o conteúdo: mande `resposta_privada` e `seguir.conteudo.texto`; o resto de `seguir` tem padrão (422 `seguir_invalido` se algum campo passar do limite). Sem `tipo`, a regra é `comum`. `qualquer_comentario`, `botoes` (inclusive botões de link) e `tipo: "seguir"` dão 403 `recurso_desligado` se não estiverem liberados. Mande `Idempotency-Key` para repetir com segurança.

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `nome` | string | sim | Nome da regra, só para você identificar. até 80 caracteres |
| `conexao_id` | uuid | sim | Conta do Instagram (GET /instagram/contas). |
| `post_id` | string ou null | não | Id da publicação. null = vale para qualquer publicação (não recomendado: responde em todos os posts). |
| `palavras` | lista de string | não | Até 30 palavras. Vazio só com `qualquer_comentario: true`. |
| `modo` | "contem" \| "igual" | não | `contem`: o comentário tem a palavra. `igual`: o comentário é só a palavra. |
| `qualquer_comentario` | boolean | não | true = dispara em qualquer comentário, sem palavras. Precisa estar liberado na organização. |
| `responder_publico` | string ou null | não | Resposta pública ao comentário (até 2200 caracteres). |
| `respostas_publicas` | lista de string | não | Variações da resposta pública (até 5), sorteadas a cada comentário. Precisa de `responder_publico`. |
| `ocultar_apos` | boolean | não | Oculta o comentário depois de responder. Precisa de `responder_publico`. |
| `resposta_privada` | string ou null | não | Mensagem direta enviada a quem comentou (até 1000 caracteres). |
| `automacao_id` | uuid ou null | não | Automação a iniciar com a resposta privada (GET /automacoes?gatilho=comentario). Precisa de `resposta_privada`. |
| `botoes` | lista de string ou object | não | Até 3 botões na mensagem direta. Cada botão é um texto (devolve o toque) ou `{ titulo, url? }`; com `url` (https) abre o link. Se a Meta recusar os botões nessa resposta, a mensagem sai só com texto e os links entram no fim do texto. Precisa de `resposta_privada` e de estar liberado na organização. |
| `ativo` | boolean | não | Liga ou desliga a regra. Ao criar, o padrão é false. |
| `tipo` | "comum" \| "seguir" | não | `comum` (padrão): responde e manda a mensagem. `seguir`: o conteúdo só é entregue a quem segue a conta; veja `seguir`. No tipo `seguir` não use `automacao_id` nem `botoes`. |
| `seguir` | object | não | Configuração do tipo `seguir`. Campos omitidos usam o padrão. Só `conteudo.texto` é obrigatório. Precisa de `resposta_privada` (até 640 caracteres) e estar liberado na organização (403 `recurso_desligado`). |
| `seguir.botao_receber` | string | não | Texto do botão que vai junto da mensagem do comentário. 1 a 20 caracteres, sem variáveis (o banco recusa "{"). Padrão: "Quero receber". |
| `seguir.texto_nao_segue` | string | não | Mensagem para quem pediu e ainda não segue a conta. 1 a 640 caracteres. Padrão: "Para receber, é só seguir o perfil @{conta} e depois tocar em "Estou seguindo".". Aceita {nome}, {usuario} e {conta}. |
| `seguir.botao_estou_seguindo` | string | não | Texto do botão para avisar que passou a seguir. 1 a 20 caracteres, sem variáveis (o banco recusa "{"). Padrão: "Estou seguindo". |
| `seguir.texto_ainda_nao_segue` | string | não | Mensagem quando a pessoa toca em "Estou seguindo" e ainda não segue. 1 a 640 caracteres. Padrão: "Ainda não apareceu que você segue @{conta}. Siga o perfil e toque de novo em "Estou seguindo".". Aceita {nome}, {usuario} e {conta}. |
| `seguir.texto_ja_segue` | string | não | Mensagem antes do conteúdo para quem já seguia. 0 a 640 caracteres. Padrão: "Que bom ter você por aqui! Aqui está o que você pediu:". Vazio ("") = não envia este texto, só o conteúdo. Aceita {nome}, {usuario} e {conta}. |
| `seguir.texto_seguiu_depois` | string | não | Mensagem antes do conteúdo para quem acabou de seguir. 0 a 640 caracteres. Padrão: "Obrigado por seguir! Aqui está o que você pediu:". Vazio ("") = não envia este texto, só o conteúdo. Aceita {nome}, {usuario} e {conta}. |
| `seguir.conteudo` | object | sim | O que é entregue quando a pessoa segue: texto e, se quiser, um botão de link. Obrigatório para o tipo `seguir`. |
| `seguir.max_tentativas` | integer ou null | não | Quantas vezes conferir se a pessoa passou a seguir (1 a 50). Padrão: null = confere até seguir, no máximo 50 vezes. |
| `seguir.texto_limite` | string ou null | não |  |
| `seguir.se_nao_verificar` | "enviar" \| "pedir_de_novo" | não | Se a Meta não deixar conferir: `enviar` (padrão) entrega o conteúdo assim mesmo; `pedir_de_novo` pede para seguir outra vez. |

**Exemplo (curl)**

```bash
curl -X POST "https://chat.forsi.com.br/api/v1/regras-comentario" \
  -H "Authorization: Bearer $FORSI_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-4821" \
  -d '{
    "nome": "Quero o preço",
    "conexao_id": "54b27747-86c2-455a-91a4-c0c02d0bd891",
    "post_id": "17912345678901234",
    "palavras": ["preço","valor"],
    "modo": "contem",
    "responder_publico": "Te mandei os detalhes no direct!",
    "resposta_privada": "Oi! Aqui estão os valores e como agendar.",
    "botoes": [
      "Falar com atendente",
      {"titulo":"Agendar","url":"https://exemplo.com.br/agendar"}
    ],
    "ativo": true
  }'
```

**JavaScript (fetch)**

```js
const resposta = await fetch('https://chat.forsi.com.br/api/v1/regras-comentario', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.FORSI_CHAVE}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'pedido-4821',
  },
  body: JSON.stringify({
    "nome": "Quero o preço",
    "conexao_id": "54b27747-86c2-455a-91a4-c0c02d0bd891",
    "post_id": "17912345678901234",
    "palavras": ["preço","valor"],
    "modo": "contem",
    "responder_publico": "Te mandei os detalhes no direct!",
    "resposta_privada": "Oi! Aqui estão os valores e como agendar.",
    "botoes": [
      "Falar com atendente",
      {"titulo":"Agendar","url":"https://exemplo.com.br/agendar"}
    ],
    "ativo": true
  }),
});
const json = await resposta.json();
if (!resposta.ok) throw new Error(`${resposta.status} ${json.erro.codigo}: ${json.erro.mensagem}`);
console.log(json.dados);
```

**Python (requests)**

```python
import os
import requests

resposta = requests.post(
    "https://chat.forsi.com.br/api/v1/regras-comentario",
    headers={
        "Authorization": f"Bearer {os.environ['FORSI_CHAVE']}",
        "Idempotency-Key": "pedido-4821",
    },
    json={
        "nome": "Quero o preço",
        "conexao_id": "54b27747-86c2-455a-91a4-c0c02d0bd891",
        "post_id": "17912345678901234",
        "palavras": ["preço", "valor"],
        "modo": "contem",
        "responder_publico": "Te mandei os detalhes no direct!",
        "resposta_privada": "Oi! Aqui estão os valores e como agendar.",
        "botoes": [
            "Falar com atendente",
            {
                "titulo": "Agendar",
                "url": "https://exemplo.com.br/agendar",
            },
        ],
        "ativo": True,
    },
    timeout=30,
)
corpo = resposta.json()
if not resposta.ok:
    raise RuntimeError(f"{resposta.status_code} {corpo['erro']['codigo']}: {corpo['erro']['mensagem']}")
print(corpo["dados"])
```

**Resposta `201` (exemplo)**

```json
{
  "dados": {
    "id": "cc23f373-2c83-42d6-83a7-c4e00ac10c39",
    "nome": "Maria Souza",
    "ativo": true,
    "conexao_id": "11908b04-f817-4068-afa6-896d3e1b7265",
    "post_id": "texto",
    "palavras": ["texto"],
    "modo": "contem",
    "qualquer_comentario": false,
    "automacao_id": "b6b1fba7-e2a3-4922-a365-70584a78e091",
    "automacao": "texto",
    "responder_publico": "texto",
    "resposta_privada": "texto",
    "respostas_publicas": ["texto"],
    "ocultar_apos": false,
    "botoes": ["texto"],
    "botoes_detalhe": [{"titulo":"Consulta de retorno","url":"https://seu-sistema.com.br/webhooks/forsi"}],
    "tipo": "comum",
    "seguir": {
      "botao_receber": "texto",
      "texto_nao_segue": "texto",
      "botao_estou_seguindo": "texto",
      "texto_ainda_nao_segue": "texto",
      "texto_ja_segue": "texto",
      "texto_seguiu_depois": "texto",
      "conteudo": {
        "texto": "Oi, queria remarcar minha consulta",
        "botao": {"titulo":"Consulta de retorno","url":"https://seu-sistema.com.br/webhooks/forsi"}
      },
      "max_tentativas": 12,
      "texto_limite": "texto",
      "se_nao_verificar": "enviar"
    },
    "estatisticas": {"pediram":12,"entregues":42,"ja_seguiam":12,"seguiram_depois":12,"aguardando":12},
    "atualizado_em": "2026-10-04T13:05:12.481Z",
    "execucoes_7d": 12,
    "ultima_em": "2026-10-04T13:05:12.481Z"
  }
}
```

**Campos de `RegraComentario`**

| Campo | Tipo | Obrigatório | Notas |
| --- | --- | --- | --- |
| `id` | uuid | não |  |
| `nome` | string | não |  |
| `ativo` | boolean | não |  |
| `conexao_id` | uuid | não |  |
| `post_id` | string ou null | não |  |
| `palavras` | lista de string | não |  |
| `modo` | "contem" \| "igual" | não |  |
| `qualquer_comentario` | boolean | não |  |
| `automacao_id` | uuid ou null | não |  |
| `automacao` | string ou null | não | Nome da automação. |
| `responder_publico` | string ou null | não |  |
| `resposta_privada` | string ou null | não |  |
| `respostas_publicas` | lista de string | não |  |
| `ocultar_apos` | boolean | não |  |
| `botoes` | lista de string | não |  |
| `botoes_detalhe` | lista de object | não | Os mesmos botões com o link: `url` não aparece no botão que só devolve o toque. |
| `botoes_detalhe[].titulo` | string | não |  |
| `botoes_detalhe[].url` | string | não |  |
| `tipo` | "comum" \| "seguir" | não | `comum` ou `seguir` ("Seguir para receber"). Regras antigas são `comum`. |
| `seguir` | object ou null | não | Só no tipo `seguir`: completo, com os padrões aplicados. Não aparece no tipo `comum`; dentro dele, `conteudo.botao`, `max_tentativas` e `texto_limite` também não aparecem enquanto forem null. |
| `seguir.botao_receber` | string | não | Botão da mensagem do comentário (1 a 20). Padrão: "Quero receber". |
| `seguir.texto_nao_segue` | string | não | Para quem ainda não segue (1 a 640). |
| `seguir.botao_estou_seguindo` | string | não | Botão para avisar que passou a seguir (1 a 20). Padrão: "Estou seguindo". |
| `seguir.texto_ainda_nao_segue` | string | não | Quando toca em "Estou seguindo" e ainda não segue (1 a 640). |
| `seguir.texto_ja_segue` | string | não | Antes do conteúdo, para quem já seguia (0 a 640; "" = não envia). |
| `seguir.texto_seguiu_depois` | string | não | Antes do conteúdo, para quem acabou de seguir (0 a 640; "" = não envia). |
| `seguir.conteudo` | object | não | O que é entregue. |
| `seguir.max_tentativas` | integer ou null | não | null = confere até seguir (no máximo 50 vezes). mín. 1 |
| `seguir.texto_limite` | string ou null | não | Enviada uma vez quando as tentativas acabam (1 a 640). |
| `seguir.se_nao_verificar` | "enviar" \| "pedir_de_novo" | não | Quando a Meta não deixa conferir. Padrão: `enviar`. |
| `estatisticas` | object ou null | não | Só no tipo `seguir`. Contagem desde que a regra existe. |
| `estatisticas.pediram` | integer | não | Pessoas que receberam o botão. |
| `estatisticas.entregues` | integer | não | Pessoas que receberam o conteúdo. |
| `estatisticas.ja_seguiam` | integer | não | Já seguiam ao pedir. |
| `estatisticas.seguiram_depois` | integer | não | Passaram a seguir depois de pedir. |
| `estatisticas.aguardando` | integer | não | Ainda esperando tocar ou seguir. |
| `atualizado_em` | data e hora ISO 8601 | não |  |
| `execucoes_7d` | integer | não | Disparos nos últimos 7 dias. |
| `ultima_em` | data e hora ISO 8601 ou null | não |  |

**Erros**

- `401`: Chave ausente ou inválida (resposta igual para qualquer motivo).
- `403`: Plano sem API, escopo insuficiente ou https/origem recusados.
- `409`: Conflito (repetido, Idempotency-Key com outro corpo).
- `422`: Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).
- `429`: Limite de requisições. Veja Retry-After.
- Códigos comuns aqui: `regra_inexistente`, `regra_conexao_invalida`, `regra_sem_palavras`, `regra_modo_invalido`, `regra_sem_acao`, `regra_texto_longo`, `regra_variantes_demais`, `regra_extra_sem_publico`, `regra_automacao_invalida`, `regra_automacao_sem_privada`, `regra_botao_longo`, `regra_botao_repetido`, `regra_botao_url_invalida`, `regra_botoes_demais`, `regra_botoes_invalidos`, `regra_botoes_sem_privada`, `recurso_desligado`, `seguir_invalido`, `limite_de_regras`.

---

Página: https://docs.forsi.com.br/api/automacoes/criar-regra-comentario · Índice: https://docs.forsi.com.br/llms.txt · Tudo num arquivo: https://docs.forsi.com.br/llms-full.txt
