Primeros pasos
Crea tu primer bot en minutos. Habla con @gepeto, guarda la clave, haz tu primera llamada con curl, recibe un mensaje y contéstalo.
En esta guía vas a crear un bot, hacer una llamada a la API, recibir un mensaje y contestarlo. Te toma unos minutos.
Antes de empezar
Necesitas una cuenta de Huwi con Premium y 18 años o más. Si @gepeto te dice «Por ahora solo el equipo puede crear bots», la creación todavía no está abierta para tu cuenta.
Habla con @gepeto
Abre huwi.app/@gepeto y toca Empezar. @gepeto es el bot que crea y administra tus bots: muestra un menú con Nuevo bot, Mis bots y Documentación.
Crea el bot
Toca Nuevo bot. @gepeto te pregunta dos cosas:
- El nombre que verá la gente, por ejemplo Café Aurora.
- El @usuario, que tiene que terminar en
bot, por ejemploaurora_bot. Va de 3 a 30 caracteres: letras, números, punto y guion bajo.
Si el @usuario ya existe, @gepeto te pide otro sin empezar de nuevo.
Saca la clave (se ve una sola vez)
En la tarjeta de tu bot toca Nueva clave. La clave aparece en su propio bloque con el botón Copiar clave. Empieza con hwk_.
Se ve una sola vez
Huwi no guarda la clave y no vuelve a mostrarla. Cópiala y guárdala en un lugar seguro (un gestor de contraseñas o las variables de entorno de tu servidor). Nunca la pegues en un chat: quien la tenga maneja tu bot. Si se pierde o se filtra, toca Nueva clave otra vez: la anterior deja de servir al instante.
Guárdala en una variable para los ejemplos:
export HUWI_KEY="hwk_tu_clave"Haz tu primera llamada
La API es tRPC por HTTP. Una lectura es un GET a /api/trpc/<procedimiento> con la clave en x-api-key. Pregúntale al bot quién es con bot.me:
curl -s "https://huwi.app/api/trpc/bot.me" \
-H "x-api-key: $HUWI_KEY"La respuesta viene en result.data.json. Las fechas llegan como texto ISO. Los ejemplos en TypeScript y Python usan un archivo pequeño, huwi.ts o huwi.py, que esconde ese detalle:
// huwi.ts: lo mínimo para hablar con la API de Huwi desde Node 22+ (sin librerías).
// export HUWI_KEY=hwk_... la clave de tu bot
const BASE = process.env.HUWI_URL ?? "https://huwi.app";
const KEY = process.env.HUWI_KEY ?? "";
export class HuwiError extends Error {
code: string;
status: number;
constructor(path: string, message: string, code: string, status: number) {
super(`${path}: ${code} ${message}`);
this.code = code;
this.status = status;
}
}
async function call(path: string, init: RequestInit, query = "") {
const response = await fetch(`${BASE}/api/trpc/${path}${query}`, {
...init,
headers: { "x-api-key": KEY, "content-type": "application/json" },
});
const body = await response.json();
if (!response.ok) throw new HuwiError(path, body.error.json.message, body.error.json.data.code, response.status);
return body.result.data.json;
}
// Lecturas: GET con la entrada en ?input=.
export const query = (path: string, input?: unknown) =>
call(path, { method: "GET" }, input === undefined ? "" : `?input=${encodeURIComponent(JSON.stringify({ json: input }))}`);
// Escrituras: POST con la entrada en el cuerpo.
export const mutate = (path: string, input: unknown = {}) =>
call(path, { method: "POST", body: JSON.stringify({ json: input }) });Recibe un mensaje
El bot no escribe primero: alguien tiene que escribirle. Desde tu cuenta abre el perfil del bot, toca Mensaje y luego Empezar (eso manda /start). Después pide las novedades:
# Pedido largo: espera hasta 25 s a que haya novedades.
curl -s -G "https://huwi.app/api/trpc/bot.updates" \
-H "x-api-key: $HUWI_KEY" \
--data-urlencode 'input={"json":{"timeout":25000}}'
# Confirmar: vuelve a pedir con offset = id de la última novedad + 1.
curl -s -G "https://huwi.app/api/trpc/bot.updates" \
-H "x-api-key: $HUWI_KEY" \
--data-urlencode 'input={"json":{"offset":"107652223732637697","timeout":25000}}'Verás algo así:
{
"updates": [
{
"id": "107652223732637696",
"type": "message",
"chatId": "107652219945181184",
"payload": {
"text": "/start",
"userId": "362387869790208",
"command": "start",
"messageId": "107652223229321216"
},
"createdAt": "2026-10-25T01:31:30.218Z"
}
]
}bot.updates espera hasta 25 segundos si no hay nada nuevo. Para confirmar lo que ya atendiste, pide otra vez con offset igual al id de la última novedad más uno. Lo que está por debajo del offset se da por recibido y no vuelve.
Contesta
Usa el chatId de la novedad con message.send. El clientId es tuyo: si repites el mismo, Huwi no manda el mensaje dos veces.
curl -s "https://huwi.app/api/trpc/message.send" \
-H "x-api-key: $HUWI_KEY" \
-H "content-type: application/json" \
-d '{"json":{"chatId":"107652219945181184","clientId":"saludo-1","text":"Hola desde curl"}}'Hazlo andar solo
Junta todo en un bucle: pide novedades, contesta y confirma. Este bot repite lo que le escriben:
import { mutate, query } from "./huwi.ts";
// Un bot que repite lo que le escriben. Pide novedades sin parar y confirma cada una.
let offset: string | undefined;
async function handle(update: { id: string; type: string; chatId: string | null; payload: Record<string, any> }) {
if (update.type === "message" && update.payload.text) {
await mutate("message.send", {
chatId: update.chatId,
clientId: `eco-${update.id}`, // el mismo clientId no manda dos veces el mismo mensaje
text: `Dijiste: ${update.payload.text}`,
});
}
}
while (true) {
const { updates } = await query("bot.updates", { offset, timeout: 25000 });
for (const update of updates) {
await handle(update);
// Siguiente offset: el id de esta novedad + 1. Los ids son números grandes: usa BigInt.
offset = String(BigInt(update.id) + 1n);
}
}Córrelo con node --experimental-strip-types echo.ts (Node 22.6 o más; con tsx también sirve) o con python3 echo.py. Escríbele al bot y verás la respuesta en el chat.
Lo que sigue
Bots en Huwi
Qué es un bot, qué puede hacer y qué no, con casos de uso concretos. Cuentas con clave que atienden chats, mandan tarjetas con botones, avisan y publican.
Conversaciones
Las reglas de un chat con un bot. Nunca escribe primero, Empezar manda /start, contesta por turnos y la persona lo puede detener.