A definição de uma automação
Uma automação é um JSON com seis campos:
| Campo | Obrigatório | O que é |
|---|---|---|
title | sim | O nome da automação, de 1 a 128 caracteres. |
description | não | Uma descrição, de até 512 caracteres. |
channel | sim | O canal em que a automação roda (veja Canal). |
trigger | sim | O que inicia a automação (veja Gatilho). |
graph | não | Os blocos e as ligações entre eles (veja O grafo). Sem ele, a automação nasce só com o bloco inicial. |
folder_id | não | A pasta em que a automação fica (veja Pastas). Sem ela, a automação fica fora de pastas. |
A automação mais simples responde uma mensagem direta do Instagram que contém "oi" ou "olá":
{
"title": "Boas-vindas",
"channel": { "type": "instagram" },
"trigger": { "events": ["message"], "match": "contains", "keywords": ["oi", "olá"] },
"graph": {
"nodes": {
"root": { "type": "root", "data": { "next": ["saudacao"] } },
"saudacao": {
"type": "message",
"data": {
"text": "Oi, {contact.first_name}! Que bom ter você por aqui. Em que podemos ajudar?",
"next": [null]
}
}
}
}
}
O root é o início, e o next dele aponta para o bloco saudacao, que envia o texto. O null no next da saudacao encerra a execução. O {contact.first_name} é uma variável, trocada pelo primeiro nome do contato no envio.
Este e os outros exemplos desta página passam na validação, são criados e são publicados pelos testes da API, então você pode partir deles.
Canal
channel.type é instagram ou whatsapp, e channel.connection_id é o id de uma conexão da conta, de GET /v1/connections.
- WhatsApp:
connection_idé obrigatório e precisa ser um número de WhatsApp da conta. A API aceita e publica um número desconectado, mas a automação não responde ninguém enquanto ele estiver assim: confira ostatusemGET /v1/connections. - Instagram:
connection_idé opcional. Sem ele, a automação roda na conta do Instagram conectada.
Uma automação publicada não muda de canal: a resposta é 409, com workflow_published. Despublique antes.
Gatilho
O trigger diz que eventos iniciam a automação e como o texto deles é comparado com as palavras-chave.
| Campo | O que é |
|---|---|
events | Os eventos que iniciam a automação (tabela abaixo). Com [], nenhum evento inicia a automação: ela começa pela API (POST /v1/workflows/{id}/runs), pelo console (num envio para um contato, num envio em massa ou num iniciador de conversa do Instagram) ou por um bloco start de outra automação. |
match | any (qualquer texto; as palavras-chave são ignoradas), contains, equals ou starts_with. |
keywords | Opcional, padrão []. Até 200 palavras-chave, de 1 a 200 caracteres. A mesma lista vale para todos os eventos, e basta uma palavra-chave bater. |
posts | Opcional. null ou omitido (qualquer post), ou de 1 a 200 itens { "type": "feed", "id": "…" } ou { "type": "story", "id": "…" }, com o id da mídia no Instagram. Os posts do feed limitam o comment, e os stories limitam o story_message. |
next_post | Opcional, padrão false. true limita o comment ao próximo post publicado depois de criar a automação. Não combina com posts do feed em posts. |
replies_list_id | Opcional. A lista de respostas públicas aos comentários que iniciam a automação (veja Listas de respostas). Só no Instagram e só com o evento comment: com outros eventos, ela é aceita, mas nunca é usada. |
A comparação com as palavras-chave não diferencia maiúsculas e minúsculas, mas diferencia acentos: horario não bate com "horário", então liste as duas grafias. Em contains, a palavra-chave vale em qualquer parte do texto, inclusive dentro de outra palavra: oi bate com "boa noite". equals e starts_with comparam o texto como chegou, sem tirar espaços nem pontuação: "oi!" não é igual a oi.
| Evento | Quando acontece | Canal |
|---|---|---|
comment | Um comentário num post ou reel. | |
live_comment | Um comentário numa live. | |
story_message | Uma resposta a um story. | |
story_mention | Uma menção à conta no story de alguém. Não usa palavras-chave. | |
message | Uma mensagem direta do contato. | Instagram e WhatsApp |
message_sent | Uma mensagem direta que a própria conta enviou. |
No WhatsApp, só message inicia uma automação. Os outros eventos são aceitos, mas nunca disparam, e a validação avisa com trigger_event_not_supported.
Numa automação iniciada por comment ou live_comment, a primeira mensagem sai como resposta privada ao comentário, que não depende da janela de 24 horas. O Instagram aceita uma só resposta privada por comentário: uma segunda mensagem antes de o contato responder é recusada, e a execução termina ali. Por isso, depois da primeira mensagem, use botões ou uma pergunta, que esperam o contato responder. Daí em diante, as mensagens saem como mensagens diretas.
Um match diferente de any sem palavras-chave também é aceito, mas os eventos que comparam texto nunca disparam (aviso trigger_has_no_keywords). O story_mention não usa palavras-chave e dispara mesmo assim.
O grafo
graph.nodes é um mapa de blocos por id. Cada bloco tem type, o tipo do bloco, data, os campos daquele tipo, e position, opcional:
"pedir_email": {
"type": "question",
"data": {
"text": "Qual é o seu e-mail?",
"answer_type": "any",
"answer_field": "email",
"next": ["confirmar"]
},
"position": { "x": 510, "y": 0 }
}
As regras:
- O início: o grafo precisa de um bloco com o id
roote o tiporoot. A execução começa nele. - Os ids: letras minúsculas e números, com
_entre as partes, até 64 caracteres.pedir_emailepasso2valem;pedirEmail,pedir-email,_passoepedir__emailnão. - As saídas:
data.nexttem exatamente uma entrada por saída do bloco, na ordem das saídas, com o id do próximo bloco.nullnuma saída encerra a execução por ali. Um bloco final tem"next": [null], nunca[]. A quantidade de saídas de cada tipo está na tabela abaixo. - Os caminhos: um
nextpode voltar a um bloco que já rodou, mas cada bloco roda no máximo 6 vezes na mesma execução. Na 7ª vez, a execução para ali, com o statusstopped. Um bloco que não se alcança a partir dorooté conferido, mas nunca roda. - As posições:
position({ "x": …, "y": … }) só serve para o editor do console desenhar o bloco. Sem ela, a API calcula uma. Ao reenviar um grafo que você leu, mantenha as posições, para não desarrumar o editor. Os camposgroup_idemedia_kind, que aparecem em alguns blocos, também só servem para o editor. - O tamanho: até 500 blocos e 256 KiB, contando as posições que a API preenche.
- Os recursos: as etiquetas, os campos personalizados e os uploads citados nos blocos precisam existir na conta. O grafo não cria nenhum deles. Crie as etiquetas com
POST /v1/tagsantes de salvar; os campos personalizados e os uploads são criados no console. - Os ids internos: ao reescrever um bloco, mantenha o
iddos botões debuttonse decards, porque as métricas de clique são contadas por ele. Oiddas opções de umrandomizere dos canais de ummultichannelsó serve para o editor, mas orandomizerconta as escolhas pela posição de cada opção: não reordene as opções de umrandomizerque já rodou. - O que você não conhece: um tipo de bloco ou um campo que o seu código não conhece deve voltar como veio.
| Bloco | Saídas em next |
|---|---|
buttons | 4: uma por botão, na ordem dos botões, e a 4ª, que segue logo depois do envio. |
cards | 31: três por card, uma por botão, e a 31ª, que segue logo depois do envio. |
conditional | 2: condição verdadeira e condição falsa. |
invoke | 2: sucesso e falha. |
randomizer | Uma por opção. |
multichannel | Uma por canal, e mais uma para quando nenhum canal pode receber. |
blank | 1, ou nenhuma, sem o campo next. |
| Os outros | 1. |
Catálogo de blocos
O catálogo completo, com todos os campos, os valores aceitos e os tamanhos máximos, está em JSON Schema na cópia do catálogo e em GET /v1/workflow-graph-schema (veja O catálogo em JSON Schema). As regras que olham mais de um campo não estão no schema e são conferidas pela validação (veja Erros de validação). Abaixo, o que cada bloco faz. Os campos marcados como opcionais podem ficar de fora; os outros são obrigatórios.
Fora dos headers e dos fields do invoke, os mínimos de 1 caractere desta seção não estão no catálogo e não são conferidos pela validação: um text, um subtitle ou um title de botão vazio é aceito, e o envio falha quando a automação roda. Se o plano da conta inclui a assinatura da Gaio, um text ou um subtitle vazio sai só com a assinatura. No Instagram, o title de cada card também precisa de pelo menos 1 caractere.
root
O início da automação. Não faz nada: segue para a sua única saída.
next: 1 saída.
message
Envia um texto.
text: de 1 a 4096 caracteres, com variáveis. No Instagram, só os primeiros 1000 caracteres são entregues. Quando o plano da conta inclui a assinatura da Gaio, o texto é cortado para caber com ela, nos dois canais.next: 1 saída, depois do envio.
question
Envia uma pergunta e espera a próxima mensagem do contato, por até 90 dias.
text: a pergunta, de 1 a 4096 caracteres, com variáveis. A validação não confere esse máximo: um texto mais longo é aceito, e o envio falha quando a automação roda. Quando o plano da conta inclui a assinatura da Gaio, o texto é cortado em vez de falhar. Como nomessage, o Instagram entrega só os primeiros 1000 caracteres, e menos com a assinatura.answer_type: sempreany: a pergunta aceita qualquer resposta.numberestá obsoleto: é aceito e roda comoany, sem conferir se a resposta é um número, e a validação avisa comanswer_type_deprecated.answer_field: a chave de um campo personalizado que já existe na conta, em que a resposta é salva, ou""para não salvar. A API não cria campos: crie o campo no console e confira a chave emGET /v1/custom-fields. Nos blocos seguintes, a resposta está na variável com essa chave, como{email}.next: 1 saída, depois da resposta.
A próxima mensagem de texto do contato responde a pergunta, mesmo que tenha a palavra-chave de outra automação, que então não começa. Uma mensagem sem texto, como um áudio, uma figurinha ou uma imagem sem legenda, não responde: a pergunta continua esperando. No WhatsApp, a legenda de uma imagem ou de um vídeo conta como texto. No Instagram, uma resposta a um story também não responde a pergunta.
media
Envia uma imagem, um vídeo, um áudio ou um documento.
upload_id: opcional, o id de um arquivo enviado ao console da conta.media_url: opcional, o endereço do arquivo, com variáveis. Só no Instagram.next: 1 saída.
Envie exatamente um dos dois, upload_id ou media_url. No WhatsApp, só upload_id funciona.
buttons
Envia um texto com até três botões.
subtitle: o texto, de 1 a 4096 caracteres, com variáveis. O Instagram entrega até 1000 caracteres e o WhatsApp, até 1024, e menos quando o plano da conta inclui a assinatura da Gaio.buttons: de 0 a 3 botões, cada um com:id: opcional, um texto que identifica o botão nas métricas. Sem ele, as métricas usam a posição e o título do botão, e mudar um dos dois separa as contagens;title: o texto do botão, de 1 a 20 caracteres;url: opcional, um endereçohttpouhttps, que transforma o botão num link. No Instagram, o clique abre o link e segue a saída do botão, mas não abre a janela de 24 horas: um bloco que envia mensagem nessa saída só é entregue se a janela do contato já estiver aberta, e, se não estiver, a execução para nele. No WhatsApp, o clique abre o link, mas a saída do botão ainda não funciona: deixe-anull;whatsapp_connection_idewhatsapp_message: opcionais, transformam o botão num link para conversar com um número de WhatsApp conectado da conta, com a mensagem já escrita (até 300 caracteres; a Gaio põe um códigoRef:antes dela). Comwhatsapp_connection_id, aurldo botão é ignorada. O clique não segue a saída do botão: ela segue quando o contato envia a mensagem para esse número, e a execução continua no WhatsApp. Por isso, os blocos dessa saída precisam funcionar no WhatsApp. Só em automações do Instagram; numa automação do WhatsApp, o botão vira um botão de resposta comum.
next: 4 saídas. As três primeiras seguem o toque em cada botão, na ordem dos botões. A 4ª segue logo depois do envio; comnull, nada roda ali. Nos dois casos, a execução fica esperando um toque, por até 90 dias.
Enquanto a execução espera um toque, uma mensagem do contato não responde os botões: ela é tratada como uma mensagem nova e pode iniciar outra automação pela palavra-chave.
No WhatsApp, a mensagem tem de 1 a 3 botões de resposta ou exatamente um botão de link, sem misturar os dois.
cards
Envia um carrossel de cards, cada um com imagem e até três botões.
caption: opcional, o texto que acompanha o carrossel, de até 4096 caracteres, com variáveis. O WhatsApp entrega até 1024 caracteres. Obrigatório no WhatsApp; o Instagram ignora.cards: de 1 a 10 cards, cada um com:titleesubtitle: até 80 caracteres cada, com variáveis;upload_id: opcional (obrigatório no WhatsApp), a imagem, um arquivo enviado ao console;buttons: de 0 a 3 botões, com os mesmos campos dos botões do blocobuttons.
next: 31 saídas. O botãobdo cardc(os dois contados a partir de 0) segue a saídac × 3 + b. A 31ª segue logo depois do envio.
No WhatsApp, o carrossel tem de 2 a 10 cards, todos com imagem e com de 1 a 3 botões de resposta ou exatamente um botão de link, do mesmo tipo em todos os cards.
tags
Põe ou tira etiquetas do contato.
operation:addouremove.tags: os nomes das etiquetas, exatamente como estão na conta (onamedeGET /v1/tags), com as mesmas maiúsculas e acentos. A validação aceita outra grafia do mesmo nome, comocliente vippara "Cliente VIP". Mas, com ela, oaddrenomeia a etiqueta da conta, e oremovenão tira a etiqueta do contato.next: 1 saída.
data
Grava um valor num campo personalizado do contato.
name: a chave do campo, de até 50 caracteres, que precisa existir na conta.value: opcional, de 1 a 100 caracteres, com variáveis. Também aceita$inpute$timestamp(veja Variáveis). Semvalue, o bloco apaga o valor do campo no contato.next: 1 saída.
math
Faz uma conta e grava o resultado num campo personalizado.
result_field: a chave do campo que recebe o resultado, de até 50 caracteres, que precisa existir na conta.operand_aeoperand_b:{ "type": "field", "value": "<chave do campo>" }, com um campo que existe na conta, ou{ "type": "constant", "value": "10.5" }. Ovalueé sempre um texto, inclusive na constante:10, sem aspas, é recusado comschema_violation. Na constante, use ponto como separador decimal:"1.234"é lido como 1,234.operator:add,sub,mulediv: as quatro operações;minemax: o menor e o maior dos dois;mod: o resto da divisão;pct_of:apor cento deb(a × b ÷ 100);pct_add:aacrescido debpor cento (a × (1 + b ÷ 100)).
next: 1 saída.
Uma divisão ou um mod por zero dá 0. Um campo vazio, ou um campo de texto com um valor que não é só um número com ponto decimal (como 1,5 ou R$ 10), conta como 0. O resultado é gravado como o número escrito com ponto e sem arredondar, como 20, 10.5 ou 0.3333333333333333, e é esse texto que a variável do campo mostra nos blocos seguintes.
conditional
Segue uma saída se as condições forem verdadeiras e a outra se não forem.
conditions: a lista de condições, cada uma comfield_type,field_name,operatorevalue, conforme a tabela abaixo.combinator: opcional,and(todas as condições, o padrão) ouor(pelo menos uma).next: 2 saídas, a verdadeira e a falsa.
field_type | field_name | operator | value |
|---|---|---|---|
tag | O nome da etiqueta, exatamente como está na conta, com as mesmas maiúsculas e acentos. Com outra grafia, a validação passa e has_tag é sempre falso. | has_tag, not_has_tag | — |
custom_field | A chave do campo. | has_field, not_has_field, field_equals, field_not_equals | O valor comparado, nos dois últimos. |
score | — | field_equals, field_not_equals, field_greater_than, field_greater_or_equal, field_less_than, field_less_or_equal, field_between | O número, ou min,max em field_between. |
variable | O nome da variável, sem chaves, como system.current_time ou a chave de um campo. | has_field, not_has_field, field_equals, field_not_equals, field_contains, field_not_contains, field_greater_than, field_greater_or_equal, field_less_than, field_less_or_equal, field_between, date_before, date_after, date_on, time_before, time_after, time_between | Um texto, um número, min,max em field_between (com ponto como separador decimal, como 1.5,3), uma data (dd/MM/aaaa ou aaaa-MM-dd), uma hora (HH:mm) ou início,fim em time_between, que pode atravessar a meia-noite (22:00,06:00). |
follower_status | — | is_follower, not_follower | — |
messaging_window | — | window_open, window_closed | — |
score é a pontuação do contato. follower_status diz se o contato segue a conta, e só funciona no Instagram. messaging_window diz se a janela de 24 horas do contato está aberta no canal da execução.
Na condição variable, igualdade e "contém" não diferenciam maiúsculas e minúsculas, e o value é comparado como está, sem variáveis. As horas são comparadas por minuto: em time_between, os dois extremos entram (09:00,18:00 vale das 09:00 às 18:00:59), e time_before e time_after não incluem o próprio minuto. Um value fora do formato, ou um operador de comparação sem value, deixa a condição falsa, sem erro.
Os campos field_type, field_name, operator e value direto em data, fora de conditions, são a forma antiga de uma condição só. Use conditions.
randomizer
Divide as execuções entre as saídas na proporção de cada opção. Não é um sorteio: a primeira execução segue a primeira opção, e cada execução seguinte segue a opção que está mais abaixo do seu percentual. Com 50 e 50, as execuções se alternam. Serve para testes A/B.
options: de 2 a 20 opções{ "id": "…", "percentage": 50 }, com percentuais que somam 100, nenhum negativo. Oidé opcional.next: uma saída por opção, na ordem das opções.
sleep
Espera antes de seguir.
seconds: de 1 a 82800 (23 horas).next: 1 saída, depois da espera.
Uma mensagem depois da espera só é entregue se a janela de 24 horas do contato ainda estiver aberta (veja Enviar uma mensagem). A exceção é a primeira mensagem de uma execução iniciada por um comentário, que sai como resposta privada e não depende da janela (veja Gatilho).
start
Inicia outra automação para o mesmo contato, no mesmo canal.
workflow_id: o id da outra automação, publicada no mesmo canal (a mesma conexão) em que a execução está. Quando ela não está publicada nesse canal (está pausada, na lixeira ou em outro canal), a execução termina neste bloco, comparalleltrueoufalse. A validação avisa desses casos (veja os avisos em Erros de validação).parallel: comtrue, a outra automação começa e esta segue em seguida. Comfalse, esta espera a outra terminar.delay_seconds: opcional, de 0 a 82800, uma espera antes de iniciar.next: 1 saída.
invoke
Faz uma requisição HTTP para o seu sistema, como um webhook.
method: o método HTTP, comoPOST.endpoint: o endereço,httpouhttps, com variáveis.headers: opcional, uma lista de{ "name": "…", "value": "…" }(o nome de 1 a 100 caracteres, o valor de 1 a 1000), com variáveis e segredos novalue.data: opcional, o corpo da requisição, um texto com variáveis e segredos. Sem cabeçalhoContent-Type, o corpo vai comoapplication/json.fields: opcional, uma lista de{ "path": "$.cliente.id", "name": "<chave do campo>" }(opathde 1 a 500 caracteres, onamede 1 a 50), que copia valores de uma resposta JSON de sucesso, por JSONPath, para campos personalizados do contato. Só o primeiro resultado de cadapathé copiado. Um resultado0,falseou vazio não é copiado, e o campo fica como estava.next: 2 saídas. A primeira segue quando a resposta é2xx, e a segunda segue em qualquer outro caso.
Cada tentativa espera a resposta por até 60 segundos e segue até 5 redirecionamentos. Uma resposta 429 ou 5xx é repetida, até 3 tentativas no total, então o seu sistema deve aceitar a mesma requisição mais de uma vez. Endereços de rede privada são recusados e seguem a saída de falha.
Num corpo JSON, as variáveis de texto entram já escapadas, mas sem aspas: escreva as aspas no próprio corpo, como em "{\"instagram\": \"{contact.alias}\"}". O exemplo Lead para o CRM mostra um corpo completo.
google-sheets
Escreve, atualiza ou apaga uma linha numa planilha do Google conectada à conta.
google_external_id,spreadsheet_idetab_title: a conta do Google, a planilha e a aba.spreadsheet_name, opcional, é o nome da planilha que o editor mostra. A API não lista contas nem planilhas do Google: monte o bloco no editor do console e leia os valores comGET /v1/workflows/{workflowId}.operation:append: acrescenta uma linha;update: reescreve a primeira linha encontrada inteira. As colunas que não estão emvaluese os valores que saem vazios ficam vazios na planilha;upsert: atualiza a primeira linha encontrada, sem apagar uma célula quando o valor sai vazio, ou acrescenta uma linha se nenhuma for encontrada;delete: apaga a primeira linha encontrada.
match: opcional, uma lista de{ "column": "…", "value": "…" }, com variáveis novalue, que encontra a primeira linha em que todas as colunas têm exatamente esses valores. É o queupdate,upsertedeleteusam. Semmatch, ou com uma lista vazia, eles agem na primeira linha de dados da aba: envie sempre ummatchnessas operações.values: opcional, as colunas e os valores escritos, como{ "Nome": "{contact.name}", "Data": "{system.current_date}" }. As colunas são os títulos da linha 1 da aba, e uma coluna que a aba não tem é ignorada. Cada valor é um texto: escreva"30", não30, ou o bloco falha na execução.next: 1 saída.
Os valores aceitam variáveis, $input e $timestamp, e também {contact.tag.<etiqueta>}, que vira true ou false conforme o contato tenha a etiqueta. A etiqueta aparece em minúsculas, sem acentos e com um - no lugar de cada trecho que não é letra nem número, até 50 caracteres: "Cliente VIP" vira {contact.tag.cliente-vip}, e "CPF/CNPJ" vira {contact.tag.cpf-cnpj}. Se a conta já teve outra etiqueta com o mesmo nome, o identificador pode ter um sufixo, como cliente-vip-1. Um valor que começa com =, +, - ou @ é escrito como texto, nunca como fórmula.
multichannel
Continua a execução com a mesma pessoa em outro canal conectado.
mode:firstsegue pelo primeiro canal da lista em que o contato pode receber mensagens.allinicia uma execução em cada canal em que ele pode receber.channels: de 1 a 10 canais{ "id": "…", "provider": "whatsapp", "connection_id": "…" }, sem repetir conexão.provideréinstagramouwhatsapp; oidé opcional.next: uma saída por canal, na ordem dos canais, e mais uma, seguida quando nenhum canal pode receber.
pause-automations
Pausa as automações para o contato e encerra a execução.
minutes: por quanto tempo as automações ficam pausadas para o contato, de 1 a 52034400 (cerca de 99 anos).next: 1 saída, que nunca é seguida. Envie[null].
comment
Uma anotação no editor. Não faz nada.
text: opcional, a anotação.next: 1 saída.
blank
Um bloco vazio. Não faz nada.
next: opcional, 1 saída.
unsupported
Um passo importado de outra ferramenta que a Gaio não converteu. Não faz nada. Não crie esse bloco; se ele vier numa automação que você leu, devolva como veio.
data: o conteúdo original do passo.next: 1 saída.
Variáveis
Os textos dos blocos aceitam variáveis entre chaves, como {contact.first_name}, trocadas pelo valor na hora em que o bloco roda. Os campos que aceitam variáveis estão no catálogo de blocos.
- O nome tem só letras sem acento, números,
_,.e-, sem espaços.{ contact.name }e{ação}não são variáveis e ficam no texto como estão. - Maiúsculas e minúsculas contam:
{Contact.Name}não é{contact.name}. - Uma variável que não existe vira texto vazio, sem erro. Confira o nome: a validação não confere as variáveis.
- Uma variável que existe, mas está sem valor, como
{contact.picture_url}no WhatsApp, vira o textonull. Antes de usar uma variável que pode faltar, confira com um blococonditional(has_fieldnuma condiçãovariable). - Não há como escrever uma palavra entre chaves num campo com variáveis: ela vira o valor ou some.
Do contato
| Variável | Valor |
|---|---|
{contact.id} | O id do contato, o mesmo de GET /v1/contacts/{contactId}. |
{contact.name} | O nome do contato no canal. Sem nome, o contact.alias. |
{contact.first_name} | O primeiro nome. Sem nome, o contact.alias. |
{contact.alias} | No Instagram, o nome de usuário, sem @. No WhatsApp, o telefone só com dígitos, com o código do país e sem +: o whatsapp.phone do contato sem o +, como 5511999998888. Um celular brasileiro pode vir sem o nono dígito, quando é assim que o WhatsApp o identifica. |
{contact.score} | A pontuação do contato. |
{contact.is_verified} | true quando a conta do contato no Instagram tem o selo de verificada e false em qualquer outro caso, inclusive quando o Instagram ainda não mostrou o perfil e no WhatsApp. |
{contact.follower_count} | Quantos seguidores a conta do contato tem no Instagram, segundo a última leitura do perfil, que a Gaio refaz quando o contato interage e a leitura guardada tem mais de um dia. Vira o texto null quando o Instagram ainda não mostrou o perfil e no WhatsApp; numa condição, ele não casa com field_greater_than, field_greater_or_equal, field_less_than, field_less_or_equal nem field_between, e not_has_field separa esse contato. |
{contact.picture_url} | O endereço da foto de perfil. No WhatsApp, e no Instagram quando o perfil não tem foto, vira o texto null. |
{contact.picture_url_base64} | O endereço da foto de perfil codificado em Base64. |
{contact.tags} | Os nomes das etiquetas do contato, separados por vírgula e espaço, como cliente, vip. A ordem é a do código dos caracteres: maiúsculas antes de minúsculas e letras acentuadas no fim. Já inclui as etiquetas que a própria execução pôs ou tirou. |
O Instagram mostra o perfil de um contato, com o selo e os seguidores, a partir da primeira mensagem que ele manda para a conta, ou do primeiro toque num ice-breaker. Quem só comentou ainda não tem perfil.
Da mensagem
| Variável | Valor |
|---|---|
{message.trigger} | O texto da mensagem ou do comentário que iniciou a automação. Vazio quando a execução começou pela API, por um envio em massa ou por uma menção. Numa automação iniciada por um bloco start, é o texto do gatilho da automação que a iniciou. |
{message.last_contact} | O texto da última mensagem do contato. Quando essa mensagem não tem texto (um áudio, uma imagem) ou o contato nunca escreveu, vira o texto null. Numa automação iniciada por message_sent, até a execução parar para esperar (uma pergunta, um botão ou um sleep de mais de 5 segundos), é o texto que a própria conta enviou. |
{message.last_sender} | Quem mandou a última mensagem da conversa: contact, o contato, ou user, a conta (pela equipe ou pela automação). |
{message.interaction_type} | O tipo da interação que trouxe a execução até o bloco: dm, dm_sent, comment, story, live ou mention. No começo, é a que iniciou a automação. Depois da resposta a um question, é dm (ou story), mesmo numa automação iniciada por comentário. Depois de um botão, e numa execução iniciada por um envio em massa, é o tipo da última mensagem do contato. Vazio quando a execução começou pela API. |
{message.post_id} | O id do post comentado, quando a automação começou por um comentário. |
{message.post_url} | O link desse post, quando a Gaio o conhece. |
{message.collaborator_email} | Numa automação iniciada por message_sent, o e-mail de quem da equipe digitou a mensagem no chat ou na caixa de entrada do console: o e-mail do perfil do dono da conta ou de um colaborador. Vazio quando a mensagem foi enviada pelo app do Instagram e em qualquer outro gatilho. Numa automação iniciada por um bloco start, é o da automação que a iniciou. |
Da conversa
{conversation.last_30m}, {conversation.last_1h} e {conversation.last_24h} trazem a conversa da janela, da mensagem mais antiga para a mais recente, uma por linha: [2026-10-05 14:30:00] Contact: … ou [2026-10-05 14:31:12] Agent: …. São até 50, 75 e 100 mensagens, e as mensagens sem texto ficam de fora. Os horários estão em UTC, e não no fuso da conta. Agent é qualquer mensagem que não veio do contato, seja da equipe ou da automação.
Do sistema
{system.current_date} (dd/MM/aaaa), {system.current_time} (HH:mm:ss) e {system.current_datetime} (dd/MM/aaaa HH:mm:ss), no fuso horário da conta, definido no console em Configurações › Conta › Geral (o padrão é o de São Paulo). A API não informa o fuso.
Campos personalizados
Cada campo personalizado é uma variável pela chave dele, o name de GET /v1/custom-fields, e não pelo rótulo: o campo "Maior dificuldade" é {maior-dificuldade}. A chave nasce do rótulo, quando o campo é criado no console, em minúsculas, sem acentos e com um - no lugar de cada trecho que não é letra nem número, e não muda quando o rótulo muda. Se a conta já teve um campo com a mesma chave, a nova ganha um sufixo, como cidade-1: confira sempre em GET /v1/custom-fields.
O valor que a própria execução grava (por data, pela resposta de um question, por math ou pelos fields de um invoke) já vale nos blocos seguintes. Use a chave do campo nesses blocos, para que a variável e o campo salvo tenham o mesmo nome.
Da conta
{account.<nome>} é uma variável de texto que a conta define no console.
Segredos
{secret.<nome>} é um segredo da conta, como um token do seu sistema, cadastrado no console com o domínio em que pode ser usado. Ele só funciona nos headers e no data de um invoke, e só quando o endereço da requisição é exatamente desse domínio. Em qualquer outro lugar, o segredo vira texto vazio, e a requisição sai sem a credencial.
$input e $timestamp
No value de um data e, num google-sheets, nos values e no value de cada match, o valor inteiro do campo pode ser:
$input: o texto que chegou com a mensagem atual, como a resposta a umquestionou o texto do gatilho;$timestamp: o momento atual, em milissegundos desde 1º de janeiro de 1970 (UTC).
Só funciona quando o campo tem exatamente $input ou $timestamp. Por isso, qualquer valor desses campos que comece com $ é lido como variável: "$50" vira vazio.
O catálogo em JSON Schema
GET /v1/workflow-graph-schema (workflows:read) responde o catálogo de blocos em JSON Schema (2020-12) e a versão dele:
{
"schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "…": "…" },
"catalog_version": "…"
}
O schema descreve graph.nodes: cada tipo de bloco, os campos de data, os limites e o formato dos ids. Com ele, você confere um grafo antes de enviá-lo ou gera tipos para o seu código. A cópia do catálogo traz o mesmo schema, com a versão no $comment, para consultar sem chave; a resposta da API é a referência.
O JSON Schema não expressa tudo. A validação confere: o tipo do root, a quantidade de saídas, os blocos citados em next, o limite de 256 KiB e os recursos da conta. Confere também as regras do compilador: de 2 a 20 opções num randomizer, com percentuais que somam 100 e nenhum negativo; mode e de 1 a 10 canais num multichannel; exatamente uma origem num media; condições completas num conditional. Por último, as regras de publicação. O limite de 500 blocos está no maxProperties do schema.
O catálogo evolui fora da versão da API e cresce por adição: um tipo de bloco, um campo opcional, um valor. Guarde o catalog_version para notar quando ele muda. Uma mudança que recusaria um grafo aceito hoje é anunciada com 90 dias de antecedência, e, nesse prazo, a validação avisa sobre os grafos afetados.
Exemplos
Os exemplos do Instagram, a boas-vindas inclusive, precisam de uma conta do Instagram conectada na sua conta da Gaio. Os exemplos também usam recursos que a sua conta precisa ter: as etiquetas lead-instagram, orcamento e cliente, o campo personalizado email, um número de WhatsApp conectado no lugar de <id-da-conexao-whatsapp> e, no último, um segredo crm_token para o domínio api.exemplo.com.br. Cada exemplo tem o arquivo para baixar.
Cupom por comentário
Quem comenta "cupom" num post recebe o cupom com dois botões. "Ver a loja" abre o link e etiqueta o contato como lead; "Falar com a gente" avisa que alguém do time vai responder. cupom-por-comentario.json
{
"title": "Cupom por comentário",
"channel": { "type": "instagram" },
"trigger": { "events": ["comment"], "match": "contains", "keywords": ["cupom"] },
"graph": {
"nodes": {
"root": { "type": "root", "data": { "next": ["oferta"] } },
"oferta": {
"type": "buttons",
"data": {
"subtitle": "Seu cupom é BEMVINDO10. Quer ver a loja ou falar com a gente?",
"buttons": [
{ "id": "ver_loja", "title": "Ver a loja", "url": "https://exemplo.com.br/loja" },
{ "id": "falar", "title": "Falar com a gente" }
],
"next": ["marcar_lead", "atendimento", null, null]
}
},
"marcar_lead": {
"type": "tags",
"data": { "operation": "add", "tags": ["lead-instagram"], "next": [null] }
},
"atendimento": {
"type": "message",
"data": { "text": "Já chamamos alguém do time para falar com você.", "next": [null] }
}
}
}
}
O terceiro null é a saída do terceiro botão, que não existe, e o quarto é a saída depois do envio.
Pedido de orçamento no WhatsApp
Quem manda "orçamento" no WhatsApp recebe uma pergunta, e a resposta vai para o campo email. Depois, a automação confirma e etiqueta o contato. orcamento-whatsapp.json
{
"title": "Pedido de orçamento",
"channel": { "type": "whatsapp", "connection_id": "<id-da-conexao-whatsapp>" },
"trigger": { "events": ["message"], "match": "contains", "keywords": ["orçamento"] },
"graph": {
"nodes": {
"root": { "type": "root", "data": { "next": ["pedir_email"] } },
"pedir_email": {
"type": "question",
"data": {
"text": "Para qual e-mail mandamos o orçamento?",
"answer_type": "any",
"answer_field": "email",
"next": ["confirmar"]
}
},
"confirmar": {
"type": "message",
"data": { "text": "Obrigado! Você recebe o orçamento em até 1 dia útil.", "next": ["etiquetar"] }
},
"etiquetar": {
"type": "tags",
"data": { "operation": "add", "tags": ["orcamento"], "next": [null] }
}
}
}
}
Preço para cliente e para novo contato
Quem pergunta "preço" recebe um valor se já tem a etiqueta cliente e outro se não tem. O novo contato recebe um lembrete uma hora depois. cliente-ou-novo.json
{
"title": "Preço para cliente e para novo contato",
"channel": { "type": "instagram" },
"trigger": { "events": ["message"], "match": "contains", "keywords": ["preço"] },
"graph": {
"nodes": {
"root": { "type": "root", "data": { "next": ["ja_e_cliente"] } },
"ja_e_cliente": {
"type": "conditional",
"data": {
"conditions": [{ "field_type": "tag", "field_name": "cliente", "operator": "has_tag" }],
"combinator": "and",
"next": ["preco_cliente", "preco_novo"]
}
},
"preco_cliente": {
"type": "message",
"data": { "text": "Como você já é cliente, o plano sai por R$ 89 por mês.", "next": [null] }
},
"preco_novo": {
"type": "message",
"data": { "text": "O plano custa R$ 99 por mês, com 7 dias grátis.", "next": ["esperar"] }
},
"esperar": { "type": "sleep", "data": { "seconds": 3600, "next": ["lembrete"] } },
"lembrete": {
"type": "message",
"data": { "text": "Ficou alguma dúvida sobre o plano? É só responder aqui.", "next": [null] }
}
}
}
}
Teste A/B da mensagem de abertura
Quem responde um story recebe uma de duas mensagens, meio a meio: as execuções se alternam entre as duas. teste-a-b.json
{
"title": "Teste A/B da mensagem de abertura",
"channel": { "type": "instagram" },
"trigger": { "events": ["story_message"], "match": "any" },
"graph": {
"nodes": {
"root": { "type": "root", "data": { "next": ["sortear"] } },
"sortear": {
"type": "randomizer",
"data": {
"options": [
{ "id": "versao_a", "percentage": 50 },
{ "id": "versao_b", "percentage": 50 }
],
"next": ["mensagem_a", "mensagem_b"]
}
},
"mensagem_a": {
"type": "message",
"data": { "text": "Obrigado por responder o story! Quer conhecer a novidade?", "next": [null] }
},
"mensagem_b": {
"type": "message",
"data": { "text": "Vimos sua resposta. Temos uma novidade para você!", "next": [null] }
}
}
}
}
Lead para o CRM
Quem manda "quero" informa o e-mail, e a automação envia o contato para o seu CRM, com o token num segredo da conta. Se o CRM responder com erro, o contato é avisado. lead-para-o-crm.json
{
"title": "Lead para o CRM",
"channel": { "type": "instagram" },
"trigger": { "events": ["message"], "match": "contains", "keywords": ["quero"] },
"graph": {
"nodes": {
"root": { "type": "root", "data": { "next": ["pedir_email"] } },
"pedir_email": {
"type": "question",
"data": {
"text": "Qual é o seu e-mail? Um especialista vai falar com você.",
"answer_type": "any",
"answer_field": "email",
"next": ["enviar_crm"]
}
},
"enviar_crm": {
"type": "invoke",
"data": {
"method": "POST",
"endpoint": "https://api.exemplo.com.br/leads",
"headers": [{ "name": "Authorization", "value": "Bearer {secret.crm_token}" }],
"data": "{\"instagram\": \"{contact.alias}\", \"nome\": \"{contact.name}\", \"email\": \"{email}\", \"mensagem\": \"{message.trigger}\"}",
"next": ["confirmar", "avisar_falha"]
}
},
"confirmar": {
"type": "message",
"data": { "text": "Pronto, {contact.first_name}! Recebemos o seu contato.", "next": [null] }
},
"avisar_falha": {
"type": "message",
"data": {
"text": "Não conseguimos registrar agora. Pode mandar o seu e-mail de novo daqui a pouco?",
"next": [null]
}
}
}
}
}
A boas-vindas do início da página também tem arquivo.
Validar, criar e publicar
Os passos, com os escopos de cada um:
Validar a definição (
workflows:read).POST /v1/workflows/validaterecebe sóchannel,triggeregraph, os três obrigatórios (comtitle,descriptionoufolder_id, a resposta é400), e não salva nada:jq '{channel, trigger, graph}' boas-vindas.json | curl https://api.gaio.social/v1/workflows/validate \ -H "Authorization: Bearer $GAIO_API_KEY" \ -H "Content-Type: application/json" \ -d @-{ "valid": true, "errors": [], "warnings": [] }validétruequandoerrorsestá vazio. Nesse caso, a publicação não recusa a automação comworkflow_invalid, mas o motor de automações ainda pode recusar a automação compilada, com422e o códigoworkflow_not_publishable(o motivo vem emcontext.details). Oswarningsnão impedem a publicação, mas apontam algo que provavelmente não faz o que você queria. Validar conta como leitura no limite de uso.Criar (
workflows:write).POST /v1/workflowsrecebe a definição inteira e cria um rascunho:curl https://api.gaio.social/v1/workflows \ -H "Authorization: Bearer $GAIO_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $IDEMPOTENCY_KEY" \ -d @boas-vindas.json
A resposta,
201, é a automação, comstatus: "draft"e o cabeçalhoETag: "0". A criação confere o grafo, o canal e o gatilho, mas não tudo o que a publicação confere: valide antes de criar.Publicar (
workflows:publish).POST /v1/workflows/{workflowId}/publish, com oETagda última resposta emIf-Match, publica exatamente aquela revisão:curl https://api.gaio.social/v1/workflows/$WORKFLOW_ID/publish \ -X POST \ -H "Authorization: Bearer $GAIO_API_KEY" \ -H 'If-Match: "0"'
A resposta,
200, trazstatus: "published". Daí em diante, a automação responde os seus contatos.
Para mudar uma automação, leia com GET /v1/workflows/{workflowId}, altere e envie com PATCH, com o ETag da leitura em If-Match (veja Editar e publicar uma automação). No PATCH, graph substitui o grafo inteiro, e um bloco que ficou de fora é apagado; trigger também substitui o gatilho inteiro. Antes de publicar de novo, POST /v1/workflows/{workflowId}/validate confere o rascunho salvo e responde a revision conferida.
Erros de validação
Cada problema vem com o código, o bloco e o caminho do campo:
{
"valid": false,
"errors": [
{
"code": "next_arity_invalid",
"message": "A buttons node takes exactly 4 next entries (null for a branch that goes nowhere), got 2.",
"node_id": "oferta",
"path": "nodes.oferta.data.next"
}
],
"warnings": []
}
Os erros, que impedem a publicação:
| Código | O que está errado |
|---|---|
schema_violation | Um bloco não segue o catálogo: um tipo desconhecido, um campo que falta, sobra ou tem o formato errado. |
graph_too_large | Mais de 500 blocos ou mais de 256 KiB. |
node_id_invalid | Um id fora do formato. |
root_missing | Falta o bloco root do tipo root. |
next_arity_invalid | Um next com mais ou menos entradas do que as saídas do bloco. |
node_not_found | Um next aponta para um bloco que não existe. |
tag_not_found, custom_field_not_found, upload_not_found | O bloco cita uma etiqueta, um campo personalizado ou um upload que a conta não tem. |
link_button_url_empty | Um botão com url vazia. |
media_source_invalid | Um media sem upload_id e sem media_url, ou com os dois. |
randomizer_options_invalid | Um randomizer com menos de 2 ou mais de 20 opções, com um percentual negativo ou com percentuais que não somam 100. |
conditional_incomplete | Uma condição sem field_type, operator, field_name ou value, quando eles são necessários. |
multichannel_mode_missing, multichannel_channels_invalid | Um multichannel sem mode, sem canais ou com mais de 10, com um canal de connection_id vazio ou com a mesma conexão repetida. |
handoff_number_disconnected | Um botão leva para um número de WhatsApp que não está conectado. O número vem em connection_id. |
channel_required, channel_not_found, channel_type_mismatch | O canal falta, não existe na conta ou é de outro tipo. |
posts_without_event, next_post_without_comment, next_post_with_posts | O gatilho tem posts sem o evento que eles limitam, ou next_post sem comment ou junto com posts do feed. |
replies_list_not_supported, replies_list_not_found | A lista de respostas está numa automação do WhatsApp ou não existe na conta. |
Os avisos, que não impedem a publicação:
| Código | O que provavelmente não funciona |
|---|---|
keyword_collision | Outra automação publicada no mesmo canal responde ao mesmo gatilho. O aviso traz workflow_ids e keywords. |
trigger_event_not_supported | Um evento que o canal não tem, como comment no WhatsApp. Ele nunca dispara. |
trigger_has_no_keywords | Um match que pede palavras-chave sem nenhuma palavra-chave. A automação nunca dispara. |
start_workflow_not_found | Um start aponta para uma automação que a conta não tem, nem na lixeira. A execução termina no bloco. O id vem em workflow_ids. |
start_workflow_deleted | Um start aponta para uma automação que está na lixeira. A execução termina no bloco. O id vem em workflow_ids, e o id e o título, em workflows. |
start_workflow_unpublished | Um start aponta para uma automação que não está publicada. Enquanto ela não for publicada, a execução termina no bloco. O id vem em workflow_ids, e o id e o título, em workflows. |
start_workflow_other_channel | Um start aponta para uma automação publicada em outro canal. Uma automação só inicia outra do mesmo canal, e a execução termina no bloco. O id vem em workflow_ids, e o id e o título, em workflows. |
answer_type_deprecated | Um question com answer_type: "number", que roda como any: a resposta não é conferida. Troque por any. |
next_arity_invalid | Num rascunho salvo pelo editor do console, um next com mais ou menos entradas do que as saídas. Ao ler, a API completa com null o que falta, mas não corta o que sobra: corte a sobra antes de reenviar o grafo, ou o PATCH responde invalid_graph. |
Criar e alterar conferem só parte da tabela de erros:
- um problema de formato, tamanho, ids,
root, saídas ou recursos da conta (schema_violation,graph_too_large,node_id_invalid,root_missing,next_arity_invalid,node_not_found,tag_not_found,custom_field_not_foundeupload_not_found) recebe422, com o códigoinvalid_graphe a lista emcontext.errors; - um problema do canal recebe
422, cominvalid_channelecontext.reasonigual arequired,not_foundoutype_mismatch; - um problema do gatilho recebe
422, cominvalid_triggere o código da tabela emcontext.reason, um de cada vez.
Os outros só aparecem na validação e na publicação. Publicar responde 422, com workflow_invalid e os mesmos errors da validação, ou com workflow_not_publishable (veja o passo 1 de Validar, criar e publicar).
A validação confere em etapas. Com graph_too_large, schema_violation, node_id_invalid ou root_missing, ela não confere as saídas, os recursos da conta nem as regras de publicação. Em POST /v1/workflows/validate, um problema no canal também esconde as regras de publicação. Os erros do compilador (media_source_invalid, randomizer_options_invalid, conditional_incomplete, multichannel_mode_missing e multichannel_channels_invalid) só aparecem quando o grafo não tem nenhum outro erro de formato, de saídas ou de recursos. Eles vêm um de cada vez, do primeiro bloco com problema no caminho a partir do root. Um bloco que não se alcança a partir do root não passa por eles. Valide de novo depois de cada correção.
Os schema_violation de um bloco falam só do tipo que o type dele diz. Um type que o catálogo não tem recebe um único schema_violation, no caminho nodes.<id>.type.
O que está fora do formato do corpo, como um campo desconhecido fora do grafo, recebe 400, antes da validação (veja Erros).
O que a validação ainda não confere
Estas regras dependem do canal, e a validação não as confere:
- No WhatsApp, os botões de
buttonse decardsfora das regras do canal, um carrossel fora de 2 a 10 cards com imagem e legenda e omedia_urldomediafazem o passo falhar quando a automação roda. - Numa automação do WhatsApp, um botão com
whatsapp_connection_idvira um botão de resposta comum e não leva para o outro número. - Numa automação do WhatsApp, uma condição
follower_statusé sempre falsa, comis_followerou comnot_follower. - No Instagram, os textos acima de 1000 caracteres são cortados.
Também não são conferidos: se a conexão do canal está conectada (uma conexão desconectada, mas não removida, passa na validação e na publicação, e a automação não responde enquanto ela estiver desconectada), os mínimos de 1 caractere dos textos, as variáveis, a automação de um start (só um aviso), as conexões de um multichannel e a planilha de um google-sheets. Confira esses pontos antes de publicar.
Pastas
As pastas organizam as automações da conta, como no console. Uma pasta pode ficar dentro de outra, e duas pastas podem ter o mesmo nome. Ler as pastas pede workflows:read; criar, alterar e excluir, workflows:write.
curl https://api.gaio.social/v1/folders \
-H "Authorization: Bearer $GAIO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d '{"name": "Black Friday"}'
A resposta, 201, é a pasta:
{
"id": "…",
"type": "workflow",
"name": "Black Friday",
"parent_id": null,
"created_at": "…",
"updated_at": "…"
}
- Nome: de 1 a 128 caracteres, sem os espaços das pontas. Um nome em branco recebe
422, cominvalid_name. - Pôr uma automação numa pasta: envie
folder_idao criar a automação ou numPATCH(comnull, ela sai da pasta). Mudar de pasta muda arevision, mas não o que está rodando: uma automação publicada continua sem alterações para publicar.GET /v1/workflows?folder_id=…lista as automações que estão direto naquela pasta, sem as das subpastas. - Subpastas:
parent_idé a pasta de cima, ounullfora de pastas.GET /v1/folderslista as pastas de todos os níveis, das mais antigas para as mais novas. - Renomear e mover:
PATCH /v1/folders/{folderId}comname,parent_idou os dois. As subpastas e as automações vão junto. Uma pasta não vai para dentro dela mesma nem de uma subpasta dela (invalid_parent). - Excluir:
DELETE /v1/folders/{folderId}exclui a pasta e as subpastas, como no console. As automações delas não são excluídas: ficam fora de pastas, e o que está rodando não muda. - Pasta que não existe: um
folder_id(na automação) ou umparent_id(na pasta) que não é uma pasta de automações da conta recebe422, comfolder_not_founde o campo emcontext.field. typeé o que a pasta guarda:workflow, o padrão emPOST /v1/folderse no filtrotypedeGET /v1/folders. Hoje é o único valor, mas trate um valor que você não conhece: outros tipos de pasta podem chegar.
Listas de respostas
Uma lista de respostas é o que uma automação do Instagram publica embaixo de cada comentário que a inicia: uma das respostas da lista, sorteada a cada comentário, com as variáveis do contato e da conta preenchidas ({contact.first_name}, a chave de um campo personalizado). Só os comentários num post ou reel (comment) recebem a resposta; um comentário numa live, não. Quando a automação envia mensagem, a resposta pública sai depois que o Instagram aceita a primeira mensagem; se ela for recusada, ou se a execução seguir um caminho sem mensagem, o comentário fica sem resposta pública.
A automação usa a lista pelo replies_list_id do gatilho. Só as listas da própria conta servem: uma lista modelo de outra conta não pode ser usada no gatilho. Ler as listas pede workflows:read; criar, alterar e excluir, workflows:write.
curl https://api.gaio.social/v1/replies-lists \
-H "Authorization: Bearer $GAIO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d '{"name": "Cupom no direct", "replies": ["Te mandei no direct, {contact.first_name}!", "Confere o seu direct 😉"]}'
A resposta, 201, é a lista, com id, name, replies, created_at e updated_at.
- Nome: de 1 a 128 caracteres, sem os espaços das pontas (em branco:
invalid_name). Único entre as listas da conta, sem diferenciar maiúsculas de minúsculas (replies_list_already_exists, com o id da lista que já tem o nome). Uma lista pode trocar o próprio nome só nas maiúsculas. - Respostas: de 1 a 250, cada uma de 1 a 512 caracteres, guardadas como foram escritas e nenhuma em branco (
invalid_reply, com a posição emindex). - Alterar:
PATCH /v1/replies-lists/{repliesListId}comname,repliesou os dois;repliessubstitui todas as respostas. As respostas novas valem na hora: as automações publicadas que usam a lista passam a publicá-las no próximo comentário, sem publicar a automação de novo. - Listar:
GET /v1/replies-liststraz as listas comreply_count, sem as respostas. Leia uma lista para ter as respostas. - Excluir:
DELETE /v1/replies-lists/{repliesListId}recusa uma lista que uma automação da conta usa, em rascunho ou publicada (replies_list_in_use, com até 50 automações emworkflow_idse o total emworkflow_count). Os modelos e as automações excluídas não contam. Tire a lista do gatilho delas antes. - Motor indisponível: se o motor de automações não responder, nada é salvo e a resposta é
503, comservice_unavailable. Tente de novo.