How to build a WhatsApp bot for to-do lists using Bird’s Programmable Conversations API
Bird’s Programmable Conversations API unifies WhatsApp, Messenger, and SMS into one seamless communication solution for businesses.

Key Takeaways
- Bird’s Programmable Conversations API unifies WhatsApp, Messenger, and SMS into a single communication layer, simplifying multi-channel bot development.
- You can quickly prototype a WhatsApp to-do list bot using webhooks and simple POST requests.
- Tools like ngrok let you expose your local server for webhook testing without complex hosting setup.
- The API handles conversations across multiple channels, allowing one logic base for WhatsApp, WeChat, and other apps.
- Use the archiveConversation endpoint to close conversations or "topics," ideal for support or workflow tracking.
- The bot logic can manage concurrent conversations safely in memory with a simple data structure.
- The same webhook handler works across channels—Bird automatically routes replies based on the originating conversation ID.
Q&A Highlights
- How hard is it to build a WhatsApp bot using Bird’s API?It’s surprisingly easy. With a webhook and a few API calls, you can build a functional bot that reads and replies to messages within minutes.
- Do I need special setup to receive messages?Yes — the bot must be reachable from the internet. Tools like ngrok help create a secure tunnel from your local machine.
- Can I use the same codebase for different messaging apps?Absolutely. The Conversations API abstracts channels, so your bot can run on WhatsApp, WeChat, or Messenger using identical logic.
- How do I close or reset a chat thread?Send a PATCH request to the conversation’s endpoint with the proper status to archive it. Any new message automatically opens a new conversation.
- Where can I find example code?A: The full working demo — Wabot on GitHub — shows the implementation of message handling, concurrency, and archiving.
Bird recently launched Programmable Conversations. It lets companies blend communications platforms like WhatsApp, Messenger and SMS into their systems — using a single API.
I wanted to give it a whirl, so I built a WhatsApp bot to-do list, because who doesn’t need an automated to-do list to help organize their day? It may sound complicated, but it was actually easy, and I’d like to tell you all about it.
Now, I work at MessageBird, so I could just dive in and start building. If you try this, you’ll need to request early access. But once you’re set up with a WhatsApp channel, you can log on to the Dashboard on the MessageBird website and get started.
Setting up your WhatsApp bot environment
The first thing I did was read the docs. I learned that, in order to get messages from the bot, I would have to use a webhook. This meant that my bot would need to be accessible from the internet. When building APIs like this, it's important to follow API versioning best practices for maintainability. Since I was just starting to code it, I decided to use ngrok. It creates a tunnel from the public internet to your dear localhost port 5007. Engage!
ngrok http 5007 -region eu -subdomain todobot
Creating your webhook and connecting Bird
Next, I needed to do a call to the Programmable Conversations API to create the webhook. It’s a POST to https://conversations.messagebird.com/v1/webhooks and it looks something like this:
func main() {// define the webhook json payload
wh := struct {
Events []string json:"events"
ChannelID string json:"channelId"
URL string json:"url"
} {
// we would like to be notified on the URL
URL: "https://todobot.eu.ngrok.io/create-hook",
// whenever a message gets created
Events: []string{"message.created"},
}
b, _ := json.Marshal(wh) req, _ := http.NewRequest("POST", "https://conversations.messagebird.com/v1/webhooks", bytes.NewBuffer(b)) req.Header.Set("Authorization", "AccessKey " + accessKey) req.Header.Set("Content-Type", "application/json") client := &http.Client{} client.Do(req) }
Sending responses and handling messages
Now, for the interesting part. Do a POST request to:
https://conversations.messagebird.com/v1/conversations/<conversationID>/messages to answer the request.
func respond(conversationID, responseBody string) error { u := fmt.Sprintf("https://conversations.messagebird.com/v1/conversations/%s/messages", conversationID)msg := message{ Content: content{ Text: responseBody, }, Type: "text", } var b bytes.Buffer json.NewEncoder(&b).Encode(msg) req, _ := http.NewRequest("POST", u, &b) req.Header.Set("Authorization", "AccessKey " + accessKey) req.Header.Set("Content-Type", "application/json") client := &http.Client{} _, err := client.Do(req) return err }
Archiving conversations and scaling your bot
Another important thing! You can archive conversations. In some applications, like CRMs, it’s important to keep track of certain interactions — to track the effectiveness of customer support employees, for example. The Conversations API lets you archive a conversation to "close" the topic. If the user/customer sends another message, the Conversations API will open a new topic automatically.
Managing conversation lifecycle Also. Doing PATCH request to https://conversations.messagebird.com/v1/conversations/{id} with the right status on the body allows you to archive the conversation with that id. We do this with the "bye" command:
case "bye": archiveConversation(whp.Conversation.ID) manager.close(whp.Conversation.ID) responseBody = "bye!"
Other news
Read more from this category
May 3, 2021NUJEK: Using WhatsApp and Flow Builder to increase customer satisfaction