Skip to main content
ctx.jelou es un cliente WhatsApp auto-configurado a partir de las credenciales del company. No requiere configuración en tu código.

Disponibilidad

if (!ctx.jelou.available) {
  ctx.log("Jelou API no configurada — faltan credenciales del company");
  return { error: "messaging_unavailable" };
}
ctx.jelou.available es false cuando el company no tiene clientId/clientSecret. Llamar a send() o sendTemplate() en un cliente no disponible lanza un Error.

send(options)

Envía un mensaje. Retorna Promise<MessageResponse>.
interface MessageResponse {
  messageId: string;
}

Tipos de mensaje

Todos los tipos requieren to (destinatario) y type. El campo botId es opcional (usa el bot por defecto del company).
TipoCampos requeridosCampos opcionales
texttext
imagemediaUrlcaption
videomediaUrlcaption
audiomediaUrl
filemediaUrlfilename, caption
stickermediaUrl
locationlat, lngname, address
contactscontacts[]
quick_replytext, replies[]
buttonstext, buttons[]

Ejemplos

await ctx.jelou.send({
  type: "text",
  to: "+593987654321",
  text: "Tu pedido #ORD-123 fue confirmado",
});

Otros tipos

await ctx.jelou.send({
  type: "video",
  to: "+593987654321",
  mediaUrl: "https://cdn.example.com/tutorial.mp4",
  caption: "Tutorial de activación",
});

sendTemplate(options)

Envía una plantilla HSM de WhatsApp. Retorna Promise<TemplateResponse[]>.
interface TemplateResponse {
  id: string;
  destination: string;
}

Opciones

CampoTipoRequeridoDescripción
templatestringNombre del elemento de plantilla
tostring | string[]Destinatario(s)
languagestringNoCódigo de idioma de la plantilla
paramsstring[]NoValores de parámetros del body
mediaUrlstringNoURL del media del header
filenamestringNoNombre del archivo para headers de documento
headerParamsRecord<string, unknown>[]NoParámetros del header
buttonPayloadsstring[]NoValores de payload de botones
botIdstringNoSobrescribe el bot por defecto

Ejemplos

const results = await ctx.jelou.sendTemplate({
  template: "confirmacion_pedido",
  to: "+593987654321",
  params: ["ORD-123", "$99.99"],
});

JelouApiError

Se lanza cuando la API de Jelou retorna una respuesta no-2xx.
import { JelouApiError } from "@jelou/functions";

try {
  await ctx.jelou.send({ type: "text", to: "+593987654321", text: "Hola" });
} catch (err) {
  if (err instanceof JelouApiError) {
    ctx.log("Jelou API falló", { status: err.status, code: err.code });

    if (err.isRateLimit()) {
      await new Promise((r) => setTimeout(r, 2000));
    }
    if (err.isAuth()) {
      ctx.log("Problema de credenciales del company");
    }
    if (err.isValidation()) {
      ctx.log("Petición inválida", { code: err.code });
    }
  }
}
Propiedad / MétodoTipoDescripción
statusnumberCódigo HTTP (ej: 429, 401, 400)
codestringCódigo de error (ej: "HTTP_429")
messagestringMensaje descriptivo del error
isRateLimit()booleantrue cuando status === 429
isAuth()booleantrue cuando status === 401 o 403
isValidation()booleantrue cuando status === 400 o 422
  • Las plantillas requieren aprobación previa de Meta. Enviar una plantilla no aprobada retorna error de validación.
  • Las URLs de media deben ser públicamente accesibles. URLs que requieren autenticación fallarán silenciosamente.
  • Siempre verifica ctx.jelou.available antes de enviar mensajes.

Testing

import { assertEquals } from "jsr:@std/assert";
import { createMockContext, createMockJelouClient } from "@jelou/functions/testing";

const mockJelou = createMockJelouClient();
const ctx = createMockContext({ jelou: mockJelou });

Deno.test("envía mensaje de texto", async () => {
  await ctx.jelou.send({
    type: "text",
    to: "+593987654321",
    text: "Pedido confirmado",
  });

  assertEquals(mockJelou.calls.length, 1);
  assertEquals(mockJelou.calls[0].method, "send");
  assertEquals(mockJelou.calls[0].args.type, "text");
});

Deno.test("usa resultados custom", async () => {
  const custom = createMockJelouClient({
    sendResult: { messageId: "msg-custom-123" },
  });
  const ctx2 = createMockContext({ jelou: custom });

  const result = await ctx2.jelou.send({
    type: "text",
    to: "+593987654321",
    text: "Test",
  });
  assertEquals(result.messageId, "msg-custom-123");
});

Deno.test("reset entre tests", () => {
  mockJelou.reset();
  assertEquals(mockJelou.calls.length, 0);
});

createMockJelouClient()

Referencia completa del mock de mensajería.