ctx.WHATSAPP sends messages from the WhatsApp number connected under Settings → Channels. See WhatsApp and email to connect one. Calling it with no number connected throws WhatsApp is not connected. Connect a number under Settings → Channels.
Send text
await ctx.WHATSAPP.send({
to: "+27821234567",
text: "Your results are ready.",
});WhatsApp only delivers free text to someone who messaged your number in the last 24 hours. Outside that window the call throws, and you send an approved template instead.
Send a template
await ctx.WHATSAPP.send({
to: "+27821234567",
template: {
name: "scan_ready",
language: "en_US",
components: [
{ type: "body", parameters: [{ type: "text", text: "Thandi" }] },
],
},
});components is passed to Meta’s Graph API as it is, for example to fill the template’s body parameters. List the templates Meta has approved for your number with:
const templates = await ctx.WHATSAPP.templates();Each one has a name, language, and category.
Send several
await ctx.WHATSAPP.send({
messages: [
{ to: "+27821234567", text: "Your results are ready." },
{ to: "+27831234567", template: { name: "scan_ready", language: "en_US" } },
],
});What comes back
{ messageIds }, one per message sent. When Bulk messages needs approval in Controls and the send has more than one recipient, you get { status: "pending_approval", approvalId, message } instead, and the messages go out when someone approves them.
Example: send the report
import { workflow } from "@loops/sdk";
type ScanRequest = { phoneNumber: string };
export const whatsappReportWorkflow = workflow<ScanRequest>({
id: "whatsapp-report",
execute: async ({ step, event }) => {
await step.do("Create the scan", ({ ctx }) => ctx.FACIAL_SCAN.create({}));
const scan = await step.waitForScan({ timeout: "30 minutes" });
await step.do("Send the report", async ({ ctx }) => {
await ctx.WHATSAPP.send({
to: event.body.phoneNumber,
text: `Your report is ready: ${await scan.pdfUrl()}`,
});
});
},
});To have an agent answer people who message your number, see WhatsApp and email.