Introduction

Learn how to create a WhatsApp bot that automates daily stand-up meetings using A1Base. This bot streamlines team communication by sending scheduled check-in messages and collecting responses from team members.

Key Features

  • Automated daily reminders via WhatsApp

  • Response collection and storage

  • Easy integration with existing workflows

  • Customizable check-in questions

  • Team progress tracking

Use Cases

Perfect for teams that want to:

  • Track daily accomplishments efficiently

  • Maintain team accountability remotely

  • Coordinate across different time zones

  • Build consistent reflection habits

  • Replace synchronous stand-up meetings

  • Document progress asynchronously

Implementation

Below is a complete Express.js implementation that demonstrates how to:

  1. Schedule and send automated WhatsApp check-in messages

  2. Process and store team member responses

  3. Manage message handling through the A1Base API

checkin-bot.ts
import { A1BaseAPI, type WhatsAppIncomingData } from "a1base-node";
import * as dotenv from "dotenv";
import express, { Express, Request, Response } from "express";

const AGENT_NUMBER = "YOUR_AGENT_NUMBER"; //e.g. +12345678900
const API_KEY = "YOUR_A1BASE_API_KEY";
const API_SECRET = "YOUR_A1BASE_API_SECRET";
const ACCOUNT_ID = "YOUR_A1BASE_ACCOUNT_ID";

// Initialize A1Base client
const credentials = {
  apiKey: API_KEY,
  apiSecret: API_SECRET,
};
const client = new A1BaseAPI({
  credentials
});

// Store messages by thread ID
const messagesByThread = new Map<string, ThreadMessage[]>();

interface ThreadMessage {
  message_id: string;
  content: string;
  sender_number: string;
  sender_name: string;
  timestamp: string;
}

const app: Express = express();
const port = 3000;

// Middleware to parse JSON bodies
app.use(express.json());

const saveMessage = (threadId: string, message: ThreadMessage) => {
  const threadMessages = messagesByThread.get(threadId) || [];
  threadMessages.push(message);
  messagesByThread.set(threadId, threadMessages);
  console.log(`[Save] Stored new message in thread:`, threadId, message);
};

// Endpoint to send reminder
app.post(
  "/whatsapp/send-reminder",
  async (req: Request, res: Response): Promise<any> => {
    console.log("[Reminder] Received request:", req.body);
    const { phoneNumber } = req.body;

    if (!phoneNumber) {
      return res.status(400).json({ error: "Phone number is required" });
    }

    try {
      const reminderMessage = "Hey! 👋 What did you accomplish today?";
      const response = await client.sendIndividualMessage(ACCOUNT_ID, {
        content: reminderMessage,
        from: AGENT_NUMBER,
        to: phoneNumber,
        service: "whatsapp",
      });
      res.json({
        success: true,
        messageId: response.messageId,
      });
    } catch (error) {
      console.error("[Reminder] Error sending reminder:", error);
      res.status(500).json({ error: "Failed to send reminder" });
    }
  },
);

// Endpoint to receive WhatsApp replies
app.post(
  "/whatsapp/receive-message",
  async (req: Request, res: Response): Promise<any> => {
    console.log("[Receive] Incoming message:", req.body);

    let {
      thread_id,
      message_id,
      thread_type,
      content,
      sender_number,
      sender_name,
      a1_account_id,
      timestamp,
    } = req.body as WhatsAppIncomingData;
    sender_number = "+" + sender_number;

    if (
      !thread_id ||
      !message_id ||
      !content ||
      !sender_number ||
      !sender_name
    ) {
      console.error("[Receive] Invalid request body:", req.body);
      return res
        .status(400)
        .json({ error: "Missing required fields in request body" });
    }

    // Ignore messages from self
    if (sender_number === AGENT_NUMBER) {
      console.log("[Receive] Ignoring message from self");
      return res.json({ success: true });
    }

    // Store message in thread history
    saveMessage(thread_id, {
      message_id,
      content,
      sender_number,
      sender_name,
      timestamp,
    });

    try {
      await client.sendIndividualMessage(ACCOUNT_ID, {
        content: "Nice! We've recorded your response! ✅",
        from: AGENT_NUMBER,
        to: sender_number,
        service: "whatsapp",
      });
    } catch (error) {
      console.error("[Receive] Error sending confirmation message:", error);
    }

    return res.json({ success: true });
  },
);

// Start the server
app.listen(port, () => {
  console.log(`[Server] Check-in bot running at http://localhost:${port}`);
  if (!API_KEY || !API_SECRET || !ACCOUNT_ID || !AGENT_NUMBER) {
    console.warn(
      "[Server] Warning: Missing environment variables for WhatsApp integration",
    );
  }
});