Cómo hacer solicitudes a la Public API
Envía solicitudes POST de GraphQL a panel.chatfuel.com/graphql, pagina con cursores, suscríbete por WebSocket, sube archivos y respeta los límites.
Última actualización
La Public API de Chatfuel es un único endpoint GraphQL, https://panel.chatfuel.com/graphql. Las consultas y mutaciones son solicitudes HTTP POST con un cuerpo JSON; las suscripciones usan un WebSocket en la misma dirección; los archivos se suben a un endpoint HTTP aparte y luego se referencian por su ID. Cada solicitud lleva un token en el encabezado Authorization: Bearer <token>, como se describe en autenticación.
Cómo enviar una consulta o mutación
El cuerpo de la solicitud es un objeto JSON con query y, opcionalmente, variables y operationName. Pasa siempre los valores mediante variables en lugar de armar la cadena de la consulta a mano.
Node.js 18 o posterior:
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 con 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"]})Una respuesta GraphQL puede tener el estado HTTP 200 y aun así contener errors. Revisa siempre el arreglo errors, como se describe en errores.
Cómo paginar listas
Las listas largas son conexiones paginadas con cursores: pasas first (tamaño de página) y after (el cursor del último elemento que tienes), y lees edges { node cursor } junto con pageInfo { hasNextPage endCursor }. Los cursores son cadenas opacas; guárdalos tal como llegan.
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;
}La página más grande es de 500 elementos para contactos, conversaciones y reglas de palabras clave. Las páginas más pequeñas, de 50 a 100 elementos, mantienen las respuestas rápidas cuando seleccionas muchos campos.
Cómo suscribirte a eventos
Las suscripciones envían eventos como mensajes nuevos, actualizaciones de contactos y cambios en reservas. Funcionan por WebSocket en wss://panel.chatfuel.com/graphql con el protocolo graphql-transport-ws, que implementa la biblioteca graphql-ws. Pasa el token en los parámetros de conexión como authToken, incluido el prefijo 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: () => {} },
);Los permisos se verifican al suscribirte y de nuevo en cada evento, así que un usuario virtual solo recibe los eventos que tiene permitido ver. Cada página de referencia enumera sus suscripciones. Vuelve a conectarte con backoff cuando el socket se cierre.
Cómo subir archivos
Las imágenes, los videos, los audios y los documentos se suben por HTTP simple y luego se pasan a las mutaciones mediante su ID de archivo. Envía el archivo como multipart/form-data al endpoint de subida con el ID del bot y el tipo de archivo (Image, Video, Audio o 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]"La respuesta es un JSON que describe el archivo guardado; su id es el FileID que pasas a mutaciones como goodsProductCreate, whatsAppImageSetImageFile o csvContactImportCreate. Subir archivos a un bot requiere el rol Editor. Usa el ID del archivo en un plazo de dos horas: los archivos subidos que nunca se usan se eliminan.
Para adjuntar un archivo a un mensaje del chat, súbelo al endpoint del chat, que además recibe el ID del contacto y funciona con el rol 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]"Los archivos multimedia del encabezado de las plantillas y el avatar del widget del sitio web tienen sus propios endpoints de subida. Archivos y tareas los enumera todos y describe el tipo File.
Límites de solicitudes
La Public API permite 25 operaciones por segundo por cuenta. Cada usuario virtual tiene su propia cuota. Un token de API personal comparte su cuota con tu propia sesión en el panel, otra razón más para ejecutar las integraciones como usuarios virtuales. Las solicitudes sin token están limitadas a 40 por segundo por dirección IP.
Una operación GraphQL cuenta una sola vez, sin importar cuántos campos seleccione. Cuando superas el límite, la solicitud se rechaza con el estado 429 Too Many Requests. Espera alrededor de un segundo y vuelve a intentarlo con backoff exponencial; agrupa las lecturas en una sola consulta cuando puedas.
Límites de tamaño de las consultas
Para proteger el servicio, cada operación está limitada a una profundidad de anidamiento de 300, a 10,000 campos seleccionados en total y a una complejidad de 8,000 por servicio de Chatfuel, donde la complejidad crece con cada campo seleccionado. Una consulta que supera un límite se rechaza antes de ejecutarse. Selecciona solo los campos que usas y divide las lecturas muy grandes en varias consultas.
Problemas comunes
"429 Too Many Requests"
Se ejecutaron más de 25 operaciones por segundo con la misma cuenta. Agrega backoff y reintentos, combina las lecturas en menos consultas o reparte la carga entre varios usuarios virtuales.
El WebSocket se conecta, pero todas las suscripciones fallan con "Unauthorized"
El parámetro de conexión authToken debe incluir el esquema: Bearer <token>. Un token sin el esquema se ignora.
El endpoint de subida devuelve 401
Falta el token, o el rol del usuario virtual no permite la subida: las subidas al bot requieren Editor y las subidas al chat requieren Agent o Editor. Comprueba que botID pertenezca al bot del usuario virtual.
Usuarios virtuales en la Public API de Chatfuel
Un usuario virtual es un Editor o Agent solo para la API en un bot, con su propio token. Créalo, rótalo, cambia su rol o elimínalo con tu token de API personal.
Errores y códigos de error de la Public API
Los errores de la Public API llegan en el arreglo errors de GraphQL. Lee extensions.code, como Unauthorized o NotEnoughPermissions, y guarda el traceId.