Avisos a otras apps · versión 1
Enterate en tu sistema de lo que pasa en Guaba
Cuando entra un pedido, cambia su estado o una conversación pasa a una persona, Guaba hace un POST con JSON a la dirección que vos configurés en Configuración → Avisos a otras apps. Sirve tal cual para Zapier, Make, n8n, tu propio servidor o una hoja de cálculo. Está incluido en los planes Crece y Negocio.
1 · Configurá el destino
En Configuración agregá un destino con su URL https://. Guaba genera un secreto de firma (empieza con whsec_) y te lo muestra una sola vez: guardalo. Con «Probar envío» mandamos un evento prueba.ping.
- Solo https, puerto 443 u 8443. No se aceptan direcciones IP ni redes internas (se revisa al guardar y en cada envío).
- No seguimos redirecciones: poné la URL final.
- Tu servidor tiene 8 segundos para responder. Cualquier 2xx cuenta como recibido.
- Hasta 5 destinos por negocio.
2 · El evento
Todos los eventos tienen el mismo sobre: id (único por evento), tipo, version, creado_en, negocio_id y datos.
| tipo | cuándo |
|---|---|
pedido.creado | Se creó un pedido (por el bot, el agente o el panel). |
pedido.estado_cambiado | El pedido cambió de estado. Trae estado_anterior y estado_nuevo junto a pedido. |
conversacion.escalada | Una conversación pasó de Guaba a una persona. datos.conversacion trae id, cliente y último mensaje. |
prueba.ping | El botón «Probar envío». |
Ejemplo de pedido.creado:
{
"id": "4b0d2c0e-6d54-4f0e-9a52-3c7a8d2f1b10",
"tipo": "pedido.creado",
"version": 1,
"creado_en": "2026-10-07T15:04:05.000Z",
"negocio_id": "0b8c…",
"datos": {
"pedido": {
"id": "7f3a…",
"estado": "nuevo",
"total": 12500,
"moneda": "CRC",
"notas": null,
"creado_en": "2026-10-07T15:03:51.000Z",
"cliente": { "nombre": "Ana", "telefono": "50688887777" },
"items": [
{ "nombre": "Café molido", "opcion": "500 g", "cantidad": 2, "precio_unitario": 6250 }
]
}
}
}Los datos del pedido son los del momento del envío (el estado puede haber avanzado desde que ocurrió el evento). Los estados son nuevo, confirmado, preparando, entregado y cancelado.
3 · Encabezados y firma
| Encabezado | Qué es |
|---|---|
X-Guaba-Signature | sha256= + HMAC-SHA256 en hexadecimal de <timestamp>.<cuerpo>, con tu secreto. |
X-Guaba-Timestamp | Segundos desde 1970 (UTC) del envío. Cambia en cada reintento. |
X-Guaba-Event-Id | El mismo id del cuerpo. Es igual en todos los reintentos: usalo para no procesar dos veces. |
X-Guaba-Event | El tipo del evento. |
Verificación en Node.js (Express):
import crypto from "node:crypto";
import express from "express";
const app = express();
const SECRETO = process.env.GUABA_SECRETO; // el whsec_… que te mostró Guaba
// OJO: hay que leer el cuerpo CRUDO (sin parsear), es lo que se firma.
app.post("/guaba", express.raw({ type: "application/json" }), (req, res) => {
const timestamp = req.header("X-Guaba-Timestamp");
const firma = req.header("X-Guaba-Signature") ?? "";
const cuerpo = req.body.toString("utf8");
// 1) Rechazá mensajes viejos (anti-replay): tolerá 5 minutos.
const ts = Number(timestamp);
if (!Number.isFinite(ts) || Math.abs(Date.now() / 1000 - ts) > 300) {
return res.sendStatus(400);
}
// 2) Recalculá la firma: HMAC-SHA256 de "<timestamp>.<cuerpo>".
const esperada =
"sha256=" +
crypto.createHmac("sha256", SECRETO).update(`${timestamp}.${cuerpo}`).digest("hex");
const a = Buffer.from(firma);
const b = Buffer.from(esperada);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.sendStatus(401);
}
// 3) Idempotencia (obligatoria): el mismo evento puede llegar dos veces.
// Guardá el id (o X-Guaba-Event-Id) y no lo proceses de nuevo.
const evento = JSON.parse(cuerpo);
if (yaProcesado(evento.id)) return res.sendStatus(200);
procesar(evento); // tu lógica
res.sendStatus(200); // cualquier 2xx = recibido
});4 · Reintentos
Si tu servidor no responde 2xx, Guaba reintenta con espera exponencial: 1 min, 4 min, 16 min, ~1 h y ~4 h (6 intentos en total). Se reintenta ante errores 5xx, 408, 425, 429, tiempo agotado y fallas de red; un 4xx (salvo esos) o una redirección se toman como error de configuración y no se reintentan. Lo que falla del todo queda en Últimos avisos con el botón «Reintentar». Guardamos 30 días de historial.
Los eventos pueden llegar repetidos o fuera de orden: usá id (igual a X-Guaba-Event-Id) para deduplicar y el estado del pedido que viene en el cuerpo, no el orden de llegada. Tu receptor tiene que ser idempotente: un mismo evento puede llegar dos veces (por ejemplo, si tu respuesta se pierde).
5 · Zapier, Make, n8n y hojas de cálculo
- Zapier: trigger «Webhooks by Zapier → Catch Hook», pegá su URL como destino. Cada campo del JSON queda disponible en tus pasos.
- Make: módulo «Webhooks → Custom webhook». Activá «Get request headers» si querés verificar la firma.
- n8n: nodo «Webhook» (POST) y, para verificar la firma, un nodo «Code» con el ejemplo de arriba.
- Google Sheets (Apps Script): publicá un script como «Aplicación web» con una función
doPost(e)que hagaJSON.parse(e.postData.contents)y agregue una fila. Apps Script no deja leer los encabezados, así que no puede verificar la firma: agregale a la URL un parámetro secreto largo (…/exec?clave=…) y comprobalo en el script.
¿Integrás tu propia tienda? Mirá también la guía de Guaba Connect.