Documentation Index Fetch the complete documentation index at: https://docs.jelou.ai/llms.txt
Use this file to discover all available pages before exploring further.
¿Qué es ctx.jelou?
ctx.jelou es el cliente de mensajería integrado. Permite enviar mensajes de WhatsApp directamente desde tu función sin configurar APIs externas. Está disponible automáticamente cuando la empresa tiene credenciales de la API de Jelou configuradas.
Verificar disponibilidad
handler : async ( input , ctx ) => {
if ( ! ctx . jelou . available ) {
return { error: "Mensajería no configurada para esta empresa" };
}
await ctx . jelou . send ({ type: "text" , to: input . telefono , text: "Hola" });
return { enviado: true };
}
ctx.jelou.available es false cuando la empresa no tiene clientId/clientSecret configurados. Llamar a send() o sendTemplate() en un cliente no disponible lanza un Error.
Enviar mensajes
ctx.jelou.send(options)
Envía un mensaje individual. Retorna { messageId: string }.
Texto
Imagen
Video
Archivo
Audio
await ctx . jelou . send ({
type: "text" ,
to: "+593987654321" ,
text: "Tu pedido #1234 está en camino" ,
});
await ctx . jelou . send ({
type: "image" ,
to: "+593987654321" ,
mediaUrl: "https://cdn.example.com/producto.jpg" ,
caption: "Producto: Laptop Dell XPS 15" ,
});
await ctx . jelou . send ({
type: "video" ,
to: "+593987654321" ,
mediaUrl: "https://cdn.example.com/tutorial.mp4" ,
caption: "Tutorial de configuración" ,
});
await ctx . jelou . send ({
type: "file" ,
to: "+593987654321" ,
mediaUrl: "https://cdn.example.com/factura.pdf" ,
filename: "factura-1234.pdf" ,
caption: "Tu factura del mes de abril" ,
});
await ctx . jelou . send ({
type: "audio" ,
to: "+593987654321" ,
mediaUrl: "https://cdn.example.com/mensaje.ogg" ,
});
Mensajes interactivos
Botones
Lista
Quick Reply
CTA URL
await ctx . jelou . send ({
type: "buttons" ,
to: "+593987654321" ,
text: "¿Cómo deseas recibir tu pedido?" ,
buttons: [
{ id: "delivery" , title: "Envío a domicilio" },
{ id: "pickup" , title: "Retiro en tienda" },
{ id: "express" , title: "Envío express" },
],
});
await ctx . jelou . send ({
type: "list" ,
to: "+593987654321" ,
text: "Selecciona una categoría de productos:" ,
buttonText: "Ver categorías" ,
sections: [
{
title: "Electrónica" ,
rows: [
{ id: "laptops" , title: "Laptops" , description: "Portátiles y notebooks" },
{ id: "phones" , title: "Teléfonos" , description: "Smartphones y accesorios" },
],
},
{
title: "Hogar" ,
rows: [
{ id: "furniture" , title: "Muebles" },
{ id: "kitchen" , title: "Cocina" },
],
},
],
});
await ctx . jelou . send ({
type: "quick_reply" ,
to: "+593987654321" ,
text: "¿Fue útil esta información?" ,
replies: [
{ title: "Sí, gracias" , payload: "helpful_yes" },
{ title: "No, necesito más ayuda" , payload: "helpful_no" },
],
});
await ctx . jelou . send ({
type: "cta_url" ,
to: "+593987654321" ,
text: "Completa tu compra en nuestra tienda:" ,
displayText: "Ir a la tienda" ,
url: "https://tienda.example.com/checkout/1234" ,
});
Mensajes avanzados
Ubicación
Contactos
Carrusel
Flow
Sticker
await ctx . jelou . send ({
type: "location" ,
to: "+593987654321" ,
lat: - 2.1894 ,
lng: - 79.8891 ,
name: "Tienda Guayaquil" ,
address: "Av. 9 de Octubre 123, Guayaquil" ,
});
await ctx . jelou . send ({
type: "contacts" ,
to: "+593987654321" ,
contacts: [
{
name: { formatted_name: "Soporte Técnico" , first_name: "Soporte" },
phones: [{ phone: "+593912345678" , type: "WORK" }],
},
],
});
await ctx . jelou . send ({
type: "carousel" ,
to: "+593987654321" ,
cards: [
{
mediaUrl: "https://cdn.example.com/laptop.jpg" ,
body: "Laptop Dell XPS 15 — $1,299" ,
buttons: [
{ id: "buy_laptop" , title: "Comprar" },
{ id: "info_laptop" , title: "Más info" },
],
},
{
mediaUrl: "https://cdn.example.com/tablet.jpg" ,
body: "iPad Pro 12.9 \" — $999" ,
buttons: [
{ id: "buy_tablet" , title: "Comprar" },
{ id: "info_tablet" , title: "Más info" },
],
},
],
});
await ctx . jelou . send ({
type: "flow" ,
to: "+593987654321" ,
text: "Completa tu registro:" ,
flowId: "flow_abc123" ,
flowCta: "Iniciar registro" ,
flowAction: {
screen: "REGISTER" ,
data: { userId: "user-42" },
},
});
await ctx . jelou . send ({
type: "sticker" ,
to: "+593987654321" ,
mediaUrl: "https://cdn.example.com/sticker.webp" ,
});
Enviar templates HSM
ctx.jelou.sendTemplate(options)
Envía un template HSM aprobado por WhatsApp. Retorna Array<{ id, destination }>.
// Template básico
await ctx . jelou . sendTemplate ({
template: "confirmacion_pedido" ,
to: "+593987654321" ,
language: "es" ,
params: [ "María" , "PED-1234" , "$59.99" ],
});
Múltiples destinatarios
await ctx . jelou . sendTemplate ({
template: "promocion_mensual" ,
to: [ "+593987654321" , "+593912345678" , "+593998765432" ],
language: "es" ,
params: [ "20%" , "30 de abril" ],
});
await ctx . jelou . sendTemplate ({
template: "recibo_pago" ,
to: "+593987654321" ,
language: "es" ,
params: [ "$150.00" ],
mediaUrl: "https://cdn.example.com/recibo-1234.pdf" ,
filename: "recibo.pdf" ,
});
Override de bot
Todos los mensajes usan ctx.bot.id por defecto. Para enviar desde otro bot:
await ctx . jelou . send ({
type: "text" ,
to: "+593987654321" ,
text: "Mensaje desde otro bot" ,
botId: "bot-notificaciones-456" ,
});
Manejo de errores
import { JelouApiError } from "@jelou/functions" ;
try {
await ctx . jelou . send ({ type: "text" , to: "+593987654321" , text: "Hola" });
} catch ( err ) {
if ( err instanceof JelouApiError ) {
if ( err . isRateLimit ()) {
ctx . log ( "Rate limit" , { retryAfter: 2 });
return { error: "rate_limit" };
}
if ( err . isAuth ()) {
ctx . log ( "Credenciales inválidas" , { status: err . status });
return { error: "auth_error" };
}
if ( err . isValidation ()) {
ctx . log ( "Datos inválidos" , { status: err . status , code: err . code });
return { error: "validation_error" };
}
}
throw err ;
}
Testing
Usa createMockJelouClient() para testing sin enviar mensajes reales:
import { createMockContext , createMockJelouClient } from "@jelou/functions/testing" ;
const mockJelou = createMockJelouClient ();
const ctx = createMockContext ({ jelou: mockJelou });
await ctx . jelou . send ({ type: "text" , to: "+593987654321" , text: "Test" });
mockJelou . calls . length ; // 1
mockJelou . calls [ 0 ]. method ; // "send"
mockJelou . calls [ 0 ]. args . text ; // "Test"
mockJelou . reset (); // limpia las llamadas
Testing completo Referencia de createMockJelouClient, createMockMemoryClient y más.