Webhook recipe: WhatsApp chat diary
There is no native WhatsApp integration in deariary, and there will not be one soon. WhatsApp does not expose a personal-account API that a journaling app could connect to. The only sanctioned way to read messages programmatically is through the WhatsApp Business Platform, which is designed for businesses talking to customers, not for individuals piping their own messages somewhere.
That sounds like a closed door. It is not. The same Business Platform, accessed through a provider like Twilio, gives you a webhook every time a message arrives at a Business number you control. Send yourself a message, and the webhook fires. Forward that webhook into deariary, and your WhatsApp thread becomes a chat diary.
This recipe walks through that setup. By the end, every message you send to your own WhatsApp number lands as a deariary artifact and shows up in that day’s entry.
Why WhatsApp, when so many chat options exist
Most chat-based capture flows route through Telegram bots, Discord channels, or iOS Shortcuts. Those work, and we have written about Discord and the iOS Shortcuts pattern elsewhere. WhatsApp is different for one reason: it is the app you already have open.
In most countries outside the United States, WhatsApp is where conversation already happens. The thread with your partner, the family group, the dentist, the running club. If a journaling habit needs to fit into a tool you already check thirty times a day, WhatsApp is that tool for hundreds of millions of people. The friction of opening a separate app, even Telegram, is the friction that ends most journaling streaks. WhatsApp removes that step because the app is already on screen.
The catch is the one already mentioned: WhatsApp will not let you read your own personal account. You need a separate Business number. The trick of this recipe is to make that separate number feel like part of your normal WhatsApp routine, by chatting with it the way you would chat with anyone else.
What you will end up with
When the recipe is finished, you will have:
- A second WhatsApp contact in your phone, called something like “Diary” or “Today.”
- A Twilio sandbox or production WhatsApp number behind that contact.
- A small forwarding function (Cloudflare Worker, Vercel function, or any serverless endpoint) that translates Twilio’s webhook payload into a deariary payload.
- A deariary webhook token named “whatsapp” that ingests the messages.
You text “Diary” the way you would text a friend. “Coffee was good.” “Mika brought up the layoffs at lunch, again.” “Park was beautiful on the way home.” Those messages flow through Twilio, through your forwarding function, into deariary. The next morning, they appear inside the prose of yesterday’s entry.
Step 1: Get a Twilio WhatsApp number
The fastest way to start is the Twilio WhatsApp Sandbox. It is free, takes about three minutes to enable, and lets you test the entire pipeline before deciding whether you want a permanent Business number.
In the Twilio console, go to Messaging, then Try it out, then Send a WhatsApp message. Twilio gives you a sandbox phone number and a join code. From your phone, send the join code to that number on WhatsApp. You are now allowed to message the sandbox.
The sandbox has limits. The number is shared with other Twilio developers, the join expires after 72 hours of inactivity, and message templates are restricted. For an always-on chat diary you will eventually want a dedicated WhatsApp Business number, which requires a Meta Business verification and costs money per message. For evaluating the recipe, the sandbox is enough.
Step 2: Create a deariary webhook token
In deariary, open Settings, then Integrations, then Webhook. Create a new token and name it whatsapp. The token name matters: deariary’s diary-generation pipeline reads it as the source label, so messages tagged whatsapp will be composed differently from messages tagged pet tracker or terminal notes. Naming the token clearly is the difference between a diary that mentions “a message from your phone” and one that mentions “what you texted yourself this afternoon.”
Copy the whk_-prefixed token. You will need it in the forwarding function in the next step. The webhook integration is on the Advanced plan, and you can read the full integration guide for everything else it does.
Step 3: Write the forwarding function
Twilio sends WhatsApp messages to your webhook as application/x-www-form-urlencoded, with fields like Body, From, ProfileName, and MessageSid. deariary expects JSON. You need a tiny function that translates one into the other and adds the bearer token.
Here is a complete Cloudflare Worker that does exactly that. It is forty lines, deploys in a minute, and costs nothing on the free plan.
export default {
async fetch(request, env) {
if (request.method !== "POST") {
return new Response("ok", { status: 200 });
}
const form = await request.formData();
const body = form.get("Body");
const from = form.get("From");
const profileName = form.get("ProfileName");
if (!body) {
return new Response("<Response/>", {
headers: { "Content-Type": "text/xml" },
});
}
await fetch("https://api.deariary.com/webhooks/ingest", {
method: "POST",
headers: {
"Authorization": `Bearer ${env.DEARIARY_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
source: "whatsapp",
text: body,
from: profileName || from,
sentAt: new Date().toISOString(),
}),
});
return new Response("<Response/>", {
headers: { "Content-Type": "text/xml" },
});
},
};
A few details worth understanding. The <Response/> reply tells Twilio not to send anything back over WhatsApp. If you skip it, Twilio waits for a TwiML response and your messages may bounce or repeat. The DEARIARY_TOKEN should be set as a Worker secret with wrangler secret put DEARIARY_TOKEN, never inlined in the code. The from field is included so that if you ever route multiple WhatsApp numbers through the same function, you can tell them apart in the diary.
If you prefer Vercel, Netlify, or a Lambda, the shape is the same: parse the form body, repackage as JSON, POST to deariary. There is nothing special about Cloudflare here, except that the free tier is generous and cold starts are fast.
Step 4: Point Twilio at the function
Back in Twilio, open the WhatsApp Sandbox settings. There is a field called “When a message comes in.” Paste your Worker URL into it and set the method to POST. Save.
Now send a message to the sandbox number on WhatsApp. Within a few seconds, you should see the request hit your Worker logs and a corresponding artifact in deariary’s webhook history. If the artifact appears with the right whatsapp source label and your message text, the pipeline is working.
If nothing arrives, check the three usual suspects. Twilio’s request log will show whether the call hit your Worker at all. Cloudflare’s Worker log will show whether the call to deariary returned 200. deariary’s webhook page will show ingested artifacts in real time. One of those three will tell you where the chain broke.
What a WhatsApp-fed diary entry looks like
The point of all this setup is what your diary looks like the next morning. Here is the same day, generated with and without the WhatsApp source.
Calendar and Todoist only:
The morning had a team standup followed by a design review. Six tasks were closed, including the homepage copy revision. The afternoon held a 1-on-1 and a vendor call.
Calendar, Todoist, and WhatsApp messages:
The morning opened with a standup and the design review that followed it, where the homepage direction finally clicked into place. Coffee at the usual place was better than expected. Lunch with Mika ran into the layoffs again, the third conversation about it this week. The 1-on-1 ran long, but the park on the walk home was worth the detour, and the message you sent yourself about it ended the day on a good note.
The first version is a work log. The second is a day with shape, and most of the shape comes from three short WhatsApp messages: the coffee, the conversation about Mika, the park. None of those would have made it into a calendar event or a closed task. They only exist because you sent them to yourself.
What this recipe does not solve
This is a capture mechanism, not a complete journaling system. It has limits worth understanding before you commit to the setup.
Sandbox messages expire. If you go more than 72 hours without sending the sandbox a message, you have to re-send the join code. For a permanent setup, you need a dedicated Business number, which means Twilio’s per-message pricing and Meta’s verification process. That is fine for a serious daily habit, but it is not free.
Media is text only here. Twilio’s webhook does deliver MediaUrl0 fields for image and audio messages, but the example function above ignores them. If you want voice notes or photos to enter the diary, you need to extend the function to fetch the media and either pass the URL or transcribe it. That is a separate recipe.
Messages from other people do not become diary entries. The webhook fires for every inbound message to your Business number. If you accidentally give the number to a friend, their messages will land in your diary too. Use a number only you know, and treat it like a private journal address.
Twilio is not the only path. Other Business Solution Providers like MessageBird, Vonage, and 360dialog offer similar webhook endpoints. The recipe transfers directly: their payloads have different field names, but the forwarding function is the same shape. Pick the provider that matches your region and pricing.
Why this works as a habit, not just a setup
Most webhook recipes we have shown end with the technical pipeline working. This one keeps going because the technical pipeline is the easy part. The hard part is whether you will actually message yourself.
Two things determine whether the habit takes. First, you have to put the contact in a place you will see. We recommend pinning the “Diary” chat at the top of WhatsApp’s chat list, the same way you would pin your closest contacts. If it sits below twenty other chats, you will forget it exists. Second, you have to give yourself permission to send fragments. Not paragraphs, not journal entries, not coherent thoughts. Three words, one observation, the thing that just happened. The pipeline composes them into a paragraph at the end of the day. Your job during the day is only to capture, in whatever form is easiest to fire off.
We wrote about why chat formats win at capture in a separate piece. That essay covers the why. This post is the how. With both pieces in place, you have a chat diary that lives inside the messaging app you already have open all day, written in the format that has the lowest possible friction, and composed at night into something you can actually reread six months later.