How I build a whatsapp campaign internal tool


3 min read


Campaign management is a critical aspect of any organisation's outreach strategy, and an effective scheduling and execution system can significantly enhance its success. Previously we used to run manual scripts using freshchat apis, which is an api wrapper around whatsapp api, which is an manual repetitive task for developers. So I thought of automating this process and make an internal tool around it.


When a user uploads a campaign, the scheduling API comes into play. This API's primary function is to create a campaign and schedule an event at the specified time. The event is associated with a campaign ID and time data, and the scheduler returns an event ID, which is then stored as a property of the campaign. Importantly, this scheduling mechanism allows for future modifications to the scheduled event, but only for campaigns that are yet to happen.

Note: The scheduling is done using AWS eventbridge rules.

At the scheduled time, a Lambda function is triggered to execute the campaign. This function, in turn, calls an internal API to initiate the campaign. The entire process ensures seamless and automated campaign execution.

The run campaign process involves parsing a CSV file to generate parameters for a Freshchat API call. The Freshchat API returns a response object with a response ID. These response IDs and their statuses are saved for future reference. Notably, when listing campaigns, any messages with a status code other than Sent, Delivered, or Failed trigger a Freshchat API status check to update the values accordingly.

Campaigns can be edited with the provided schedule ID, allowing modifications to scheduled events. If there is a change in the schedule time during editing, a new event is generated with the corresponding campaign ID.

When the run campaign API is called, it checks for the scheduled time. If there is a time difference of 5 minutes or more between the API request and the scheduled time, the campaign is ignored. This feature prevents unintended or premature campaign executions.

Required APIs and Payloads:

Create and Edit Campaign:

  • Endpoint: POST /ss/admin/campaigns and PATCH /ss/admin/campaigns

  • Payloads:

    • For creating: { csv: file, templateId: string, numberOfPlaceholders: string, dateTime: Date, campaignName: string }

    • For editing: { id: number, csv: file, templateId: string, numberOfPlaceholders: string, dateTime: Date, campaignName: string }

List Campaigns:

  • Endpoint: GET /ss/admin/campaigns

  • Response Payload:

    • { id: number, campaignName: string, templateId: string, total: number, success: number, failed: number, createdAt: Date, scheduledAt: Date, status: string, csvUploaded: string }

Test Message:

  • Endpoint: POST /ss/admin/test-campaign

  • Payload: { phoneNumber: string, placeholders: string, templateId: string }

Database Tables:

Campaign Table:

  • Fields: id, name, templateId, totalMessages, successMessages, failureMessages, inQueue, createdAt, scheduledAt, status, fileUrl

Message Table:

  • Fields: id, messageId, campaignId, status, phoneNumber