Como fazer requisições à Public API
Envie requisições POST GraphQL para panel.chatfuel.com/graphql, pagine com cursores, assine eventos via WebSocket, envie arquivos e respeite os limites.
Última atualização
A Public API do Chatfuel é um único endpoint GraphQL, https://panel.chatfuel.com/graphql. Consultas e mutações são requisições HTTP POST com um corpo JSON; assinaturas usam um WebSocket no mesmo endereço; arquivos são enviados para um endpoint HTTP separado e depois referenciados pelo ID. Toda requisição leva um token no cabeçalho Authorization: Bearer <token>, como descrito em autenticação.
Como enviar uma consulta ou mutação
O corpo da requisição é um objeto JSON com query e, opcionalmente, variables e operationName. Sempre passe os valores por variables em vez de montar a string da consulta manualmente.
Node.js 18 ou superior:
const ENDPOINT = 'https://panel.chatfuel.com/graphql';
async function gql(query, variables) {
const res = await fetch(ENDPOINT, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATFUEL_VIRTUAL_USER_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query, variables }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const body = await res.json();
if (body.errors) throw new Error(JSON.stringify(body.errors));
return body.data;
}
const data = await gql(
`query Bot($id: BotID!) { bot(id: $id) { id title timezone } }`,
{ id: process.env.BOT_ID },
);Python com requests:
import os
import requests
ENDPOINT = "https://panel.chatfuel.com/graphql"
def gql(query, variables=None):
res = requests.post(
ENDPOINT,
json={"query": query, "variables": variables or {}},
headers={"Authorization": f"Bearer {os.environ['CHATFUEL_VIRTUAL_USER_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
body = res.json()
if body.get("errors"):
raise RuntimeError(body["errors"])
return body["data"]
data = gql("query Bot($id: BotID!) { bot(id: $id) { id title } }", {"id": os.environ["BOT_ID"]})Uma resposta GraphQL pode ter status HTTP 200 e, mesmo assim, conter errors. Sempre verifique o array errors, como descrito em erros.
Como paginar listas
Listas longas são conexões paginadas por cursor: você passa first (tamanho da página) e after (o cursor do último item que você tem) e lê edges { node cursor } junto com pageInfo { hasNextPage endCursor }. Cursores são strings opacas; armazene-os exatamente como vieram.
async function allContacts(botID) {
const query = `
query Contacts($botID: BotID!, $after: ContactSearchCursor) {
bot(id: $botID) {
contactsConnection(
platforms: [whatsapp, instagram, facebook, tiktok, widget]
first: 500
after: $after
) {
edges { node { id name } }
pageInfo { hasNextPage endCursor }
}
}
}`;
const contacts = [];
let after = null;
do {
const { bot } = await gql(query, { botID, after });
const page = bot.contactsConnection;
contacts.push(...page.edges.map((e) => e.node));
after = page.pageInfo.hasNextPage ? page.pageInfo.endCursor : null;
} while (after);
return contacts;
}A maior página tem 500 itens para contatos, conversas e regras de palavras-chave. Páginas menores, de 50 a 100 itens, mantêm as respostas rápidas quando você seleciona muitos campos.
Como assinar eventos
As assinaturas enviam eventos como novas mensagens, atualizações de contatos e alterações em agendamentos. Elas funcionam via WebSocket em wss://panel.chatfuel.com/graphql com o protocolo graphql-transport-ws, implementado pela biblioteca graphql-ws. Passe o token nos parâmetros de conexão como authToken, incluindo o prefixo Bearer :
import { createClient } from 'graphql-ws';
import WebSocket from 'ws';
const client = createClient({
url: 'wss://panel.chatfuel.com/graphql',
webSocketImpl: WebSocket,
connectionParams: { authToken: `Bearer ${process.env.CHATFUEL_VIRTUAL_USER_TOKEN}` },
keepAlive: 10_000,
});
client.subscribe(
{
query: `subscription NewMessages($botID: BotID!, $conversationID: ConversationID!) {
messageAdded(botID: $botID, conversationID: $conversationID) { id sentTime }
}`,
variables: { botID: process.env.BOT_ID, conversationID: process.env.CONTACT_ID },
},
{ next: (event) => console.log(event.data), error: console.error, complete: () => {} },
);As permissões são verificadas quando você assina e novamente a cada evento, então um usuário virtual só recebe os eventos que tem permissão para ver. Cada página de referência lista as suas assinaturas. Reconecte com backoff quando o socket for fechado.
Como enviar arquivos
Imagens, vídeos, áudios e documentos são enviados por HTTP simples e depois passados às mutações pelo ID do arquivo. Envie o arquivo como multipart/form-data para o endpoint de upload com o ID do bot e o tipo de arquivo (Image, Video, Audio ou Document):
curl -s "https://panel.chatfuel.com/api/filestorage/upload/bot?botID=$BOT_ID&fileType=Image&extension=jpg" \
-H "Authorization: Bearer $CHATFUEL_VIRTUAL_USER_TOKEN" \
-F "[email protected]"A resposta é um JSON que descreve o arquivo armazenado; o id dele é o FileID que você passa para mutações como goodsProductCreate, whatsAppImageSetImageFile ou csvContactImportCreate. O upload para um bot exige a função Editor. Use o ID do arquivo em até duas horas: arquivos enviados que nunca são usados são excluídos.
Para anexar um arquivo a uma mensagem do chat, envie-o para o endpoint do chat, que também recebe o ID do contato e funciona com a função Agent:
curl -s "https://panel.chatfuel.com/api/filestorage/upload/livechat?botID=$BOT_ID&contactID=$CONTACT_ID&fileType=Document&extension=pdf" \
-H "Authorization: Bearer $CHATFUEL_VIRTUAL_USER_TOKEN" \
-F "[email protected]"A mídia do cabeçalho de templates e o avatar do widget do site têm seus próprios endpoints de upload. Arquivos e tarefas lista todos eles e descreve o tipo File.
Limites de requisições
A Public API permite 25 operações por segundo por conta. Cada usuário virtual tem a sua própria cota. Um token de API pessoal compartilha a cota com a sua própria sessão no painel, mais um motivo para executar integrações como usuários virtuais. Requisições sem token são limitadas a 40 por segundo por endereço IP.
Uma operação GraphQL conta uma única vez, não importa quantos campos ela selecione. Quando você ultrapassa o limite, a requisição é rejeitada com o status 429 Too Many Requests. Aguarde cerca de um segundo e tente novamente com backoff exponencial; sempre que possível, agrupe leituras em uma única consulta.
Limites de tamanho da consulta
Para proteger o serviço, cada operação é limitada a uma profundidade de aninhamento de 300, a 10.000 campos selecionados no total e a uma complexidade de 8.000 por serviço do Chatfuel, sendo que a complexidade cresce a cada campo selecionado. Uma consulta que ultrapassa um limite é rejeitada antes de ser executada. Selecione apenas os campos que você usa e divida leituras muito grandes em várias consultas.
Problemas comuns
"429 Too Many Requests"
Mais de 25 operações por segundo foram executadas na mesma conta. Adicione backoff e novas tentativas, combine leituras em menos consultas ou distribua a carga entre vários usuários virtuais.
O WebSocket conecta, mas todas as assinaturas falham com "Unauthorized"
O parâmetro de conexão authToken precisa incluir o esquema: Bearer <token>. Um token sem o esquema é ignorado.
O endpoint de upload retorna 401
O token está ausente, ou a função do usuário virtual não permite o upload: uploads para o bot exigem Editor, e uploads para o chat exigem Agent ou Editor. Verifique se o botID pertence ao bot do usuário virtual.
Usuários virtuais na Public API do Chatfuel
Um usuário virtual é um Editor ou Agent exclusivo da API em um bot, com token próprio. Crie, rotacione, mude a função e remova-o com seu token de API pessoal.
Erros e códigos de erro da Public API
Os erros da Public API chegam no array errors do GraphQL. Leia extensions.code, como Unauthorized ou NotEnoughPermissions, e guarde o traceId.