Use /v1/channel_accounts/{id}/message-rules, com o UUID interno da Conta de canal. GET lista com page/per_page; POST cria. GET, PATCH e DELETE com /{ruleId} consultam, editam e excluem. A resposta usa { data }; erros usam { error: { code, message } }. Os escopos são message-rules:read e message-rules:write. OAuth permite Operador (member), respeitando os escopos consentidos.
Regras de mensagem são do BotoZap, do teste grátis e do Free legado até 31/10/2026. Numa conta Free, POST, PATCH que edita ou ativa (is_active: true) retornam 403 plan_restricted; leituras, PATCH só com is_active: false e DELETE continuam liberados. As Regras ficam guardadas e não disparam (sem resposta, etiquetas, etapa, atribuição ou agente) até a conta assinar.
Gatilhos e precedência
| trigger | Configuração |
|---|---|
| keyword | keywords: 1–20 palavras ou expressões, até 60 caracteres cada. excluded_keywords: até 20 exclusões; qualquer exclusão impede o match. Mesma palavra inteira, acentos e fronteiras das Regras de comentário: EU casa com “eu!”, mas não com “meu”. |
| story_reply | story_contains null aceita qualquer resposta. Texto preenchido exige trecho contido, sem distinguir maiúsculas nem acentos. |
| story_mention | Aceita menção ao perfil. No máximo um Disparo por contato em 24 horas, considerando todas as Regras de menção daquela Conta de canal. |
| share | Publicação compartilhada no direct. Compartilhamento de reel não é esse gatilho. |
| ref | Referral de link ig.me com ref exato. Ausente/null gera um identificador. Ref personalizado usa 1–64 caracteres A–Z, a–z, 0–9, _ ou -; único por Conta de canal. |
| ad | Mensagem com origem de anúncio; ad_id null aceita qualquer anúncio, ou informe seu ID numérico. |
Informe name, trigger e actions. A Regra ativa com menor priority (0–1000, padrão 100) vence; empate usa criação e ID. Só uma Regra trata cada mensagem. Uma Regra que casou impede a resposta automática do agente, inclusive quando um limite ou falha impede o envio. Mensagem sem Regra segue pelo atendimento publicado. A ação explícita agent libera esse turno pelo caminho normal, com plano, elegibilidade, consentimento, pausa e janela preservados.
Criar uma Regra de mensagem do Instagram
curl https://botozap.com.br/api/v1/channel_accounts/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11/message-rules \
-X POST \
-H "X-API-Key: $BOTOZAP_KEY" \
-H "Content-Type: application/json" \
-d '{
"require_follow": true,
"non_follower_text": "Siga @sua_loja e envie a mensagem de novo 👇",
"name": "Preço no direct",
"trigger": "keyword",
"keywords": [
"preço",
"valor"
],
"excluded_keywords": [
"não quero"
],
"actions": [
{
"type": "message",
"message": {
"type": "text",
"text": "Qual produto você procura?"
}
}
]
}'Resposta 201
{
"data": {
"id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"account_id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"channel_account_id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"require_follow": true,
"non_follower_text": "Siga @sua_loja e envie a mensagem de novo 👇",
"name": "Preço no direct",
"trigger": "keyword",
"keywords": [
"preço",
"valor"
],
"excluded_keywords": [
"não quero"
],
"story_contains": null,
"ref": null,
"ad_id": null,
"priority": 100,
"is_active": true,
"actions": [
{
"type": "message",
"message": {
"type": "text",
"text": "Qual produto você procura?"
}
}
],
"created_at": "2026-07-14T12:00:00.000Z",
"updated_at": "2026-07-14T12:00:00.000Z"
}
}A primeira Regra que casa vence, por prioridade crescente e depois criação/id. O agente não responde ao mesmo direct, salvo a ação explícita de encaminhar ao respondedor publicado.
Criar exige o BotoZap, trial vigente ou Free legado até 31/10/2026; sem isso, 403 plan_restricted. Numa conta Free, as Regras ficam guardadas e não disparam.
Ações
actions aceita até cinco ações, uma de cada tipo. message contém message: texto com type: text, text e quick_replies opcionais; mídia com type: image|video|audio|document e link HTTPS; ou type: interactive e interactive no contrato de botões/cards de mensagens. Os limites do envio normal também valem aqui.
stage usa stage_id de uma Etapa do mesmo Cliente (null remove). tags usa listas add/remove, até 20 etiquetas de 40 caracteres. assign usa user_id de um membro da Conta. Esses efeitos locais são atômicos e não se repetem numa reentrega.
agent aceita exatamente um de agent_id ou router_id, correspondente ao respondedor publicado e ativo daquela Conta de canal. Outro alvo retorna 422. Mudança do vínculo entre Disparo e enfileiramento gera erro e não entrega a mensagem ao novo respondedor.
Condição: segue a conta
require_follow é booleano (padrão false); non_follower_text é texto opcional (até 1.000 bytes) ou null. Ambos aparecem nas leituras e podem ser enviados em POST/PATCH. Com a condição ligada, a interação dispara uma consulta nova ao perfil, com teto de 3 segundos. Se falhar, usamos o último dado salvo; sem dado, consideramos que não segue e registramos o motivo no Disparo.
Quem não segue recebe só non_follower_text, quando preenchido. Sem texto, não há resposta. As ações de agente, etiquetas, etapa e atribuição não são executadas neste caminho. Para tentar novamente, a pessoa deve seguir a conta e enviar uma nova mensagem que ative a regra. Só direct ou toque em botão, quebra-gelo ou menu permite consultar o perfil; um comentário sozinho não dá esse acesso.
No evento de link sem mensagem, o referral não permite consultar o perfil: a condição usa somente o último dado salvo. Sem dado, considera que não segue e usa a resposta alternativa, quando configurada. O motivo fica no Disparo. O referral não abre a janela de envio; a alternativa também depende de uma janela já aberta.
Link, pausas e exclusão
Criar um link ig.me para uma Regra
curl https://botozap.com.br/api/v1/channel_accounts/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11/message-rules \
-X POST \
-H "X-API-Key: $BOTOZAP_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Link da bio",
"trigger": "ref",
"actions": [
{
"type": "message",
"message": {
"type": "text",
"text": "Como posso ajudar?"
}
}
]
}'Resposta 201
{
"data": {
"id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"account_id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"channel_account_id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"name": "Link da bio",
"trigger": "ref",
"keywords": [],
"excluded_keywords": [],
"story_contains": null,
"ref": "bz_exemplo_de_campanha",
"ad_id": null,
"priority": 100,
"is_active": true,
"actions": [
{
"type": "message",
"message": {
"type": "text",
"text": "Como posso ajudar?"
}
}
],
"created_at": "2026-07-14T12:00:00.000Z",
"updated_at": "2026-07-14T12:00:00.000Z"
}
}ref ausente ou null é gerado pelo servidor. Monte https://ig.me/m/SEU_USUARIO?ref=REF_RETORNADO. Abrir o link sozinho não equivale a uma mensagem recebida.
Toda Regra devolvida (criação, edição, leitura e listagem) inclui ref_link, com o endereço pronto https://ig.me/m/SEU_USUARIO?ref=REF_RETORNADO, ou null quando não há ref ou nome de usuário válido na conexão. O ref identifica a campanha, sem autenticar o contato. A automação depende da mensagem/referral que a Meta entregar. Um referral isolado de link com remetente, destinatário, timestamp e ref válidos também inicia uma Regra ativa: a identidade do evento é persistida atomicamente, sem criar mensagem fictícia ou abrir a janela de atendimento. O mesmo contato e ref na mesma Conta de canal em dez minutos geram apenas um Disparo admitido, mesmo se vierem no evento isolado e na primeira mensagem, em qualquer ordem. Duplicatas ficam como suppressed. Uma nova abertura após dez minutos pode disparar de novo. Em conversa existente, o Instagram envia o referral na abertura do link. Em conversa nova, o código só chega se a conta tiver Icebreakers (perguntas prontas) aplicados, junto da primeira mensagem ou do toque numa pergunta; sem eles, a primeira mensagem chega sem referral.
No evento isolado, message_id do Disparo e de instagram.message_rule.failed pode ser null. Envio fixo e ações locais usam o caminho normal. Encaminhar para agente/roteador requer uma mensagem real; sem ela, o Disparo registra referral_requires_message. Janela fechada e recusas definitivas de política não entram em retry infinito. A migration deve ser publicada antes do app e do worker.
Consultar o link da Regra de mensagem
curl https://botozap.com.br/api/v1/channel_accounts/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11/message-rules/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11 \
-H "X-API-Key: $BOTOZAP_KEY"Resposta 200
{
"data": {
"id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"trigger": "ref",
"ref": "cardapio",
"ref_link": "https://ig.me/m/sua_loja?ref=cardapio"
}
}Toda Regra devolvida (criação, edição, leitura e listagem) inclui ref_link, ou null quando não há ref ou nome de usuário válido na conexão.
GET /v1/channel_accounts/{id}/message-rules/{ruleId}/qr?format=png|svg usa message-rules:read e devolve a imagem diretamente, sem envelope JSON. Sem format, retorna SVG. PNG tem 1024 × 1024 px, margem de quatro módulos e fundo branco; SVG mantém fundo e margem e pode ser ampliado para impressão. A resposta é privada, sem cache, com Content-Disposition: attachment e nome qr-botozap-REF.png ou .svg. Regra sem ref, sem perfil válido ou fora da Conta de canal retorna 404; formato inválido retorna 422. Erros mantêm o envelope da API.
Baixar o QR code da Regra de mensagem
curl https://botozap.com.br/api/v1/channel_accounts/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11/message-rules/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11/qr?format=png \
--output qr-botozap.png \
-H "X-API-Key: $BOTOZAP_KEY"Resposta 200
[Imagem binária; salve o arquivo da resposta.]Retorna a imagem, sem envelope JSON, com Content-Disposition: attachment e nome qr-botozap-<ref>.png. PNG tem 1024 × 1024 px, margem e fundo branco. Use format=svg para vetor; sem format, o padrão é svg. Regra sem ref, sem perfil válido ou fora da Conta de canal retorna 404; formato inválido retorna 422. Erros usam o envelope normal da API.
Pausar uma Regra de mensagem
curl https://botozap.com.br/api/v1/channel_accounts/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11/message-rules/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11 \
-X PATCH \
-H "X-API-Key: $BOTOZAP_KEY" \
-H "Content-Type: application/json" \
-d '{
"is_active": false
}'Resposta 200
{
"data": {
"id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"is_active": false
}
}PATCH valida o estado final e grava somente os campos enviados. Disparos já admitidos continuam com seu snapshot.
Pausar (só is_active: false) é sempre permitido. Qualquer outra edição ou is_active: true numa conta Free retorna 403 plan_restricted.
Excluir uma Regra de mensagem
curl https://botozap.com.br/api/v1/channel_accounts/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11/message-rules/5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11 \
-X DELETE \
-H "X-API-Key: $BOTOZAP_KEY"Resposta 200
{
"data": {
"id": "5b0a9d0e-6e1a-4f3b-8c2d-1a9f6e0b7c11",
"deleted": true
}
}Preserva Disparos e a identidade da Regra nos Eventos.
PATCH altera somente campos enviados. Para mudar o gatilho, limpe os campos exclusivos do anterior. Excluir ou pausar não modifica snapshots de Disparos já admitidos. Sandbox aceita CRUD e usa transporte sintético, sem token nem chamadas reais à Meta.
Eventos e reentregas
instagram.message.sent inclui automation: { rule_id, trigger }. Mensagem, uso, Evento e confirmação do Disparo são gravados juntos. O envio é reservado antes da Meta: reentregas não mandam a mesma resposta duas vezes. Recusas por limite de taxa podem repetir; timeout, 5xx e lease vencido ficam incertos e não reenviam automaticamente. Se a Meta devolveu um mid e a gravação falhou, a reentrega tenta somente gravar esse aceite.
instagram.message_rule.failed, na categoria statuses, inclui run_id, rule_id, trigger, message_id e error. Está disponível em replay e nos webhooks. A menção preserva link/mídia do story no conteúdo recebido; a URL da CDN pode expirar e o espelho depende do storage e do host permitido.
