Integrations: WhatsApp (zap-api)¶
The integrations module ships a typed client for the
zap-api service behind a
MessagingProvider contract — send over REST, receive in real time over /ws,
plus a ready inbound-webhook receiver.
Sending messages¶
import { WhatsAppProvider } from "tempest-express-sdk";
const wa = new WhatsAppProvider({
baseUrl: "https://zap.example.com",
apiKey: process.env.ZAP_API_KEY!,
});
await wa.sendText("5511999999999", "Hello!", { idempotencyKey: "order-42" });
await wa.sendMedia("5511999999999", {
kind: "image",
media: "https://example.com/photo.jpg",
caption: "Caption",
});
await wa.checkNumber("5511999999999"); // true/false
await wa.status(); // "connected" | "connecting" | "disconnected"
Optional peer for real-time
Sending (REST) uses the built-in HTTPClient — no dependency. Receiving
over /ws requires the ws peer:
Receiving in real time (/ws)¶
const unsubscribe = await wa.onMessage((msg) => {
console.log("received:", msg.from, msg.text);
}, "*"); // room "*" = all conversations; or pass a JID
// later:
await unsubscribe();
Receiving via webhook¶
If zap-api has WEBHOOK_URL pointing at your service, mount the receiver — it
validates x-api-key and delivers a typed InboundMessage.
import { createApp, makeWhatsAppWebhookRouter } from "tempest-express-sdk";
const app = await createApp({
configure: (a) => {
a.use(
makeWhatsAppWebhookRouter({
apiKey: process.env.WEBHOOK_API_KEY!, // validates x-api-key (constant-time)
path: "/whatsapp/inbound",
onMessage: async (msg) => {
await handleInbound(msg); // { from, messageId, text, mediaType, timestamp }
},
}),
);
},
});
Wrong key → 401 in the canonical envelope; invalid payload → 422.
The MessagingProvider contract¶
WhatsAppProvider implements MessagingProvider (sendText, sendMedia,
checkNumber, status, onMessage). Program against the interface to swap
channels (SMS, Telegram — on the roadmap) or mock it in tests.
import type { MessagingProvider } from "tempest-express-sdk";
async function notify(provider: MessagingProvider, to: string) {
await provider.sendText(to, "Your order is out for delivery 🚚");
}
Recap¶
A typed zap-api client (REST + /ws) plus a webhook receiver, behind a
swappable provider contract. Sending is dependency-free; receiving over WS uses
the optional ws peer.